Merge branch 'master' into feature/wpa2_enterprise

This commit is contained in:
Xia Xiaotian
2016-11-23 16:34:01 +08:00
102 changed files with 7666 additions and 333 deletions

View File

@@ -44,6 +44,7 @@ typedef enum {
SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
SYSTEM_EVENT_AP_STA_GOT_IP6, /**< ESP32 station or ap interface v6IP addr is preferred */
SYSTEM_EVENT_MAX
} system_event_id_t;
@@ -79,7 +80,11 @@ typedef struct {
typedef struct {
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
}system_event_sta_wps_er_pin_t;
} system_event_sta_wps_er_pin_t;
typedef struct {
tcpip_adapter_ip6_info_t ip6_info;
} system_event_ap_sta_got_ip6_t;
typedef struct {
uint8_t mac[6]; /**< MAC address of the station connected to ESP32 soft-AP */
@@ -106,6 +111,7 @@ typedef union {
system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */
system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */
system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 soft-AP receive probe request packet */
system_event_ap_sta_got_ip6_t got_ip6; /**< ESP32 station or ap ipv6 addr state change to preferred */
} system_event_info_t;
typedef struct {

View File

@@ -82,126 +82,6 @@ extern "C" {
#define ESP_INTR_DISABLE(inum) \
xt_ints_off((1<<inum))
#define ESP_CCOMPARE_INTR_ENBALE() \
ESP_INTR_ENABLE(ETS_CCOMPARE_INUM)
#define ESP_CCOMPARE_INTR_DISBALE() \
ESP_INTR_DISABLE(ETS_CCOMPARE_INUM)
#define ESP_SPI1_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_SPI1_INUM)
#define ESP_SPI1_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_SPI1_INUM)
#define ESP_SPI2_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_SPI2_INUM)
#define ESP_PWM_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_PWM_INUM)
#define ESP_PWM_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_PWM_INUM)
#define ESP_SPI2_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_SPI2_INUM)
#define ESP_SPI3_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_SPI3_INUM)
#define ESP_SPI3_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_SPI3_INUM)
#define ESP_I2S0_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_I2S0_INUM)
#define ESP_I2S0_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_I2S0_INUM)
#define ESP_I2S1_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_I2S1_INUM)
#define ESP_I2S1_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_I2S1_INUM)
#define ESP_MPWM_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_MPWM_INUM)
#define ESP_EPWM_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_EPWM_INUM)
#define ESP_MPWM_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_MPWM_INUM)
#define ESP_EPWM_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_EPWM_INUM)
#define ESP_BB_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_BB_INUM)
#define ESP_BB_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_BB_INUM)
#define ESP_UART0_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_UART0_INUM)
#define ESP_UART0_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_UART0_INUM)
#define ESP_LEDC_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_LEDC_INUM)
#define ESP_LEDC_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_LEDC_INUM)
#define ESP_GPIO_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_GPIO_INUM)
#define ESP_GPIO_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_GPIO_INUM)
#define ESP_WDT_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_WDT_INUM)
#define ESP_WDT_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_WDT_INUM)
#define ESP_FRC1_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_FRC_TIMER1_INUM)
#define ESP_FRC1_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_FRC_TIMER1_INUM)
#define ESP_FRC2_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_FRC_TIMER2_INUM)
#define ESP_FRC2_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_FRC_TIMER2_INUM)
#define ESP_RTC_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_RTC_INUM)
#define ESP_RTC_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_RTC_INUM)
#define ESP_SLC_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_SLC_INUM)
#define ESP_SLC_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_SLC_INUM)
#define ESP_PCNT_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_PCNT_INUM)
#define ESP_PCNT_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_PCNT_INUM)
#define ESP_RMT_CTRL_ENABLE() \
ESP_INTR_ENABLE(ETS_RMT_CTRL_INUM)
#define ESP_RMT_CTRL_DIABLE() \
ESP_INTR_DISABLE(ETS_RMT_CTRL_INUM)
#ifdef __cplusplus
}
#endif

View File

@@ -2163,7 +2163,8 @@
#define RMT_DATE_V 0xFFFFFFFF
#define RMT_DATE_S 0
/* RMT memory block address */
#define RMT_CHANNEL_MEM(i) (DR_REG_RMT_BASE + 0x800 + 64 * 4 * (i))
#endif /*_SOC_RMT_REG_H_ */

View File

@@ -226,18 +226,35 @@ typedef volatile struct {
} rmt_dev_t;
extern rmt_dev_t RMT;
//Allow access to RMT memory using RMTMEM.chan[0].data[8]
typedef struct {
union {
struct {
uint32_t duration0 :15;
uint32_t level0 :1;
uint32_t duration1 :15;
uint32_t level1 :1;
};
uint32_t val;
};
} rmt_item32_t;
typedef struct {
union {
struct {
uint16_t duration :15;
uint16_t level :1;
};
uint16_t val;
};
} rmt_item16_t;
//Allow access to RMT memory using RMTMEM.chan[0].data32[8]
typedef volatile struct {
struct {
union {
struct {
uint32_t duration0: 15;
uint32_t level0: 1;
uint32_t duration1: 15;
uint32_t level1: 1;
};
uint32_t val;
} data[64];
rmt_item32_t data32[64];
rmt_item16_t data16[128];
};
} chan[8];
} rmt_mem_t;
extern rmt_mem_t RMTMEM;

View File

@@ -0,0 +1,9 @@
menu "TESTS"
config FP_TEST_ENABLE
bool "Enable test fp"
default "y"
help
For FPGA single core CPU which has no floating point support, floating point test should be disabled.
endmenu

View File

@@ -0,0 +1,17 @@
#
#Component Makefile
#
COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
COMPONENT_SRCDIRS := . test_vectors
include $(IDF_PATH)/make/component_common.mk
test_tjpgd.o: test_tjpgd_logo.h
test_tjpgd_logo.h: $(COMPONENT_PATH)/logo.jpg
$(summary) XXD logo.jpg
$(Q) cd $(COMPONENT_PATH); xxd -i logo.jpg $(COMPONENT_BUILD_DIR)/test_tjpgd_logo.h

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -0,0 +1,293 @@
#include <esp_types.h>
#include <stdio.h>
#include <stdlib.h>
#include "rom/ets_sys.h"
#include "rom/lldesc.h"
#include "rom/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "soc/uart_reg.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_reg.h"
#include "soc/i2s_reg.h"
#define DPORT_I2S0_CLK_EN (BIT(4))
#define DPORT_I2S0_RST (BIT(4))
/*
This test tests the s32c1i instruction when the AHB bus is also used. To create some AHB traffic, we use the I2S interface
to copy bytes over from one memory location to another. DO NOT USE the i2s routines inhere, they've been trial-and-error'ed until
the point where they happened to do what I want.
*/
static void lcdIfaceInit()
{
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
//Init pins to i2s functions
SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS
WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS
WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S));
// WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX<<GPIO_GPIO_FUNC0_OUT_SEL_S));
//GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
//Reset I2S subsystem
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_SIG_LOOPBACK);
WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
(16 << I2S_RX_BITS_MOD_S) |
(16 << I2S_TX_BITS_MOD_S) |
(1 << I2S_RX_BCK_DIV_NUM_S) |
(1 << I2S_TX_BCK_DIV_NUM_S));
WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
I2S_CLKA_ENA | I2S_CLK_EN |
(1 << I2S_CLKM_DIV_A_S) |
(1 << I2S_CLKM_DIV_B_S) |
(1 << I2S_CLKM_DIV_NUM_S));
WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
(32 << I2S_TX_DATA_NUM_S) | //Low watermark for IRQ
(32 << I2S_RX_DATA_NUM_S));
WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
//Invert WS to active-low
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
}
static volatile lldesc_t dmaDesc[2];
static void finishDma()
{
//No need to finish if no DMA transfer going on
if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
return;
}
//Wait till fifo done
while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
//Wait for last bytes to leave i2s xmit thing
//ToDo: poll bit in next hw
// for (i=0; i<(1<<8); i++);
while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
//Reset I2S for next transfer
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
// for (i=0; i<(1<<8); i++);
while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
}
/*
This is a very, very, very hacked up LCD routine which ends up basically doing a memcpy from sbuf to rbuf.
*/
static void sendRecvBufDma(uint16_t *sbuf, uint16_t *rbuf, int len)
{
//Fill DMA descriptor
dmaDesc[0].length = len * 2;
dmaDesc[0].size = len * 2;
dmaDesc[0].owner = 1;
dmaDesc[0].sosf = 0;
dmaDesc[0].buf = (uint8_t *)sbuf;
dmaDesc[0].offset = 0; //unused in hw
dmaDesc[0].empty = 0;
dmaDesc[0].eof = 1;
dmaDesc[1].length = len * 2;
dmaDesc[1].size = len * 2;
dmaDesc[1].owner = 1;
dmaDesc[1].sosf = 0;
dmaDesc[1].buf = (uint8_t *)rbuf;
dmaDesc[1].offset = 0; //unused in hw
dmaDesc[1].empty = 0;
dmaDesc[1].eof = 1;
//Reset DMA
SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
//Reset I2S FIFO
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
//Set desc addr
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
//Enable and configure DMA
WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN |
I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
//Start transmission
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
//Clear int flags
WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
}
#define DMALEN (2048-2)
static void tskLcd(void *pvParameters)
{
uint16_t *sbuf = malloc(DMALEN * 2);
uint16_t *rbuf = malloc(DMALEN * 2);
uint16_t xorval = 0;
int x;
lcdIfaceInit();
// lcdFlush();
while (1) {
for (x = 0; x < DMALEN; x++) {
sbuf[x] = x ^ xorval;
}
for (x = 0; x < DMALEN; x++) {
rbuf[x] = 0; //clear rbuf
}
sendRecvBufDma(sbuf, rbuf, DMALEN);
vTaskDelay(20 / portTICK_PERIOD_MS);
finishDma();
for (x = 0; x < DMALEN; x++) if (rbuf[x] != (x ^ xorval)) {
printf("Rxbuf err! pos %d val %x xor %x", x, (int)rbuf[x], (int)xorval);
}
printf(".");
fflush(stdout);
xorval++;
}
}
void test_s32c1i_lock(volatile int *lockvar, int lockval, int unlockval, volatile int *ctr);
static volatile int ctr = 0, state = 0;
static volatile int lock = 0;
static void tskOne(void *pvParameters)
{
int x;
int err = 0, run = 0;
while (1) {
ctr = 0; lock = 0;
state = 1;
for (x = 0; x < 16 * 1024; x++) {
test_s32c1i_lock(&lock, 1, 0, &ctr);
}
vTaskDelay(60 / portTICK_PERIOD_MS);
state = 2;
if (ctr != 16 * 1024 * 2) {
printf("Lock malfunction detected! Ctr=0x%x instead of %x\n", ctr, 16 * 1024 * 2);
err++;
}
run++;
printf("Run %d err %d\n", run, err);
vTaskDelay(20 / portTICK_PERIOD_MS);
}
}
#define FB2ADDR 0x40098000
static void tskTwo(void *pvParameters)
{
int x;
int *p = (int *)FB2ADDR;
int *s = (int *)test_s32c1i_lock;
void (*test_s32c1i_lock2)(volatile int * lockvar, int lockval, int unlockval, volatile int * ctr) = (void *)FB2ADDR;
volatile int w;
int delay;
for (x = 0; x < 100; x++) {
*p++ = *s++; //copy routine to different pool
}
while (1) {
while (state != 1) ;
for (x = 0; x < 16 * 1024; x++) {
test_s32c1i_lock2(&lock, 2, 0, &ctr);
//Some random delay to increase chance of weirdness
if ((x & 0x1f) == 0) {
delay = rand() & 0x1f;
for (w = 0; w < delay; w++);
}
}
while (state != 2);
}
}
TEST_CASE("S32C1I vs AHB test (needs I2S)", "[hw]")
{
int i;
TaskHandle_t th[3];
state = 0;
printf("Creating tasks\n");
xTaskCreatePinnedToCore(tskTwo , "tsktwo" , 2048, NULL, 3, &th[1], 1);
xTaskCreatePinnedToCore(tskOne , "tskone" , 2048, NULL, 3, &th[0], 0);
xTaskCreatePinnedToCore(tskLcd , "tsklcd" , 2048, NULL, 3, &th[2], 0);
// Let stuff run for 20s
while (1) {
vTaskDelay(20000 / portTICK_PERIOD_MS);
}
//Shut down all the tasks
for (i = 0; i < 3; i++) {
vTaskDelete(th[i]);
}
}

View File

@@ -0,0 +1,51 @@
/*
This little bit of code is executed in-place by one CPU, but copied to a different memory region
by the other CPU. Make sure it stays position-independent.
*/
.text
.align 4
.global test_s32c1i_lock
.type test_s32c1i_lock,@function
//Args:
//a2 - lock addr
//a3 - val to lock with
//a4 - val to unlock with
//a5 - addr to increase
test_s32c1i_lock:
entry a1, 64
wsr a4, SCOMPARE1
lockloop:
mov a6, a3
s32c1i a6, a2, 0
bne a4, a6, lockloop
l32i a6, a5, 0
//Give other CPU the time to mess up the inc if the lock somehow malfunctions
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
addi a6, a6, 1
s32i a6, a5, 0
//No need to actually let this loop but hey, a hang indicates an error, right?
wsr a3, SCOMPARE1
unlockloop:
mov a6, a4
s32c1i a6, a2, 0
bne a3, a6, unlockloop
retw

View File

@@ -0,0 +1,132 @@
#include <esp_types.h>
#include <stdio.h>
#include "rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "soc/uart_reg.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
/*
This test tests the 'fast' peripherial bus at 0x3ff40000. This bus is connected directly to the core, and as such
can receive 'speculative' reads, that is, reads that may or may not actually be executed in the code flow. This
may mess with any FIFOs mapped in the region: if a byte gets dropped due to a missed speculative read, the fifo
may advance to the next byte anyway.
This code tests reading/writing from the UART1 FIFO, using both cores. For this to work, it's required that the
UARTs RX and TX lines are connected.
*/
void test_fastbus_cp(int fifo_addr, unsigned char *buf, int len, int *dummy);
static volatile int state = 0;
static volatile int xor = 0;
static unsigned char res[128];
static void tskOne(void *pvParameters)
{
int run = 0, err = 0;
int x;
int ct[256];
volatile int w;
int dummy;
while (1) {
state = 1;
for (x = 0; x < 64; x++) {
WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor);
}
for (w = 0; w < (1 << 14); w++); //delay
state = 2;
test_fastbus_cp(UART_FIFO_REG(1), &res[0], 64, &dummy);
for (w = 0; w < (1 << 10); w++); //delay
for (x = 0; x < 255; x++) {
ct[x] = 0; //zero ctrs
}
for (x = 0; x < 128; x++) {
ct[(int)res[x]^xor]++; //count values
}
for (x = 0; x < 255; x++) { //check counts
if (ct[x] != (x < 128 ? 1 : 0)) {
//Disregard first few loops; there may be crap in the fifo.
if (run > 2) {
err++;
printf("Error! Received value %d %d times!\n", x, ct[x]);
}
}
}
run++;
if ((run & 255) == 0) {
printf("Loop %d errct %d\n", run, err);
}
xor = (xor + 1) & 0xff;
}
}
#define FB2ADDR 0x40098000
static void tskTwo(void *pvParameters)
{
int x;
int dummy;
int *p = (int *)FB2ADDR;
int *s = (int *)test_fastbus_cp;
for (x = 0; x < 100; x++) {
*p++ = *s++;
}
void (*test_fastbus_cp2)(int fifo_addr, unsigned char * buf, int len, int * dummy) = (void *)FB2ADDR;
while (1) {
while (state != 1) ;
for (x = 64; x < 128; x++) {
WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor);
}
while (state != 2);
test_fastbus_cp2(UART_FIFO_REG(1), &res[64], 64, &dummy);
}
}
// TODO: split this thing into separate orthogonal tests
TEST_CASE("Fast I/O bus test", "[hw]")
{
int i;
if ((REG_UART_BASE(0) >> 16) != 0x3ff4) {
printf("Error! Uart base isn't on fast bus.\n");
TEST_ASSERT(0);
}
PIN_PULLUP_DIS(PERIPHS_IO_MUX_SD_DATA3_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, FUNC_SD_DATA2_U1RXD);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_SD_DATA3_U1TXD);
int reg_val = (1 << UART_RXFIFO_FULL_THRHD_S);
WRITE_PERI_REG(UART_CONF1_REG(1), reg_val);
WRITE_PERI_REG(UART_CLKDIV_REG(1), 0x30); //semi-random
// CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(1), UART_TXFIFO_EMPTY_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
TaskHandle_t th[2];
printf("Creating tasks\n");
xTaskCreatePinnedToCore(tskOne , "tskone" , 2048, NULL, 3, &th[0], 0);
xTaskCreatePinnedToCore(tskTwo , "tsktwo" , 2048, NULL, 3, &th[1], 1);
// Let stuff run for 20s
while (1) {
vTaskDelay(20000 / portTICK_PERIOD_MS);
}
//Shut down all the tasks
for (i = 0; i < 2; i++) {
vTaskDelete(th[i]);
}
xt_ints_off(1 << ETS_UART0_INUM);
}

View File

@@ -0,0 +1,32 @@
/*
This little bit of code is executed in-place by one CPU, but copied to a different memory region
by the other CPU. Make sure it stays position-independent.
*/
.text
.align 4
.global test_fastbus_cp
.type test_fastbus_cp,@function
//Args:
//a2 - fifo addr
//a3 - buf addr
//a4 - len
//a5 - ptr to int to use
test_fastbus_cp:
entry a1,64
back:
beqi a4, 0, out //check if loop done
s32i a4, a5, 0 //store value, for shits and/or giggles
memw //make sure write happens
l32i a4, a5, 0 //load value again, to thwart any prediction in the pipeline
bbsi a4, 0, pred //Random jump to check predictive reads. Both branches should do the same.
l32i a6, a2, 0 //read from fifo 1
j predout
pred:
l32i a6, a2, 0 //read from fifo 2
predout:
s8i a6, a3, 0 //store result
addi a3, a3, 1 //inc ptr
addi a4, a4, -1 //next
j back //loop again
out:
retw //and we are done

View File

@@ -0,0 +1,195 @@
#include <math.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#if CONFIG_FP_TEST_ENABLE
static float addsf(float a, float b)
{
float result;
asm volatile (
"wfr f0, %1\n"
"wfr f1, %2\n"
"add.s f2, f0, f1\n"
"rfr %0, f2\n"
:"=r"(result):"r"(a), "r"(b)
);
return result;
}
static float mulsf(float a, float b)
{
float result;
asm volatile (
"wfr f0, %1\n"
"wfr f1, %2\n"
"mul.s f2, f0, f1\n"
"rfr %0, f2\n"
:"=r"(result):"r"(a), "r"(b)
);
return result;
}
static float divsf(float a, float b)
{
float result;
asm volatile (
"wfr f0, %1\n"
"wfr f1, %2\n"
"div0.s f3, f1 \n"
"nexp01.s f4, f1 \n"
"const.s f5, 1 \n"
"maddn.s f5, f4, f3 \n"
"mov.s f6, f3 \n"
"mov.s f7, f1 \n"
"nexp01.s f8, f0 \n"
"maddn.s f6, f5, f3 \n"
"const.s f5, 1 \n"
"const.s f2, 0 \n"
"neg.s f9, f8 \n"
"maddn.s f5,f4,f6 \n"
"maddn.s f2, f0, f3 \n"
"mkdadj.s f7, f0 \n"
"maddn.s f6,f5,f6 \n"
"maddn.s f9,f4,f2 \n"
"const.s f5, 1 \n"
"maddn.s f5,f4,f6 \n"
"maddn.s f2,f9,f6 \n"
"neg.s f9, f8 \n"
"maddn.s f6,f5,f6 \n"
"maddn.s f9,f4,f2 \n"
"addexpm.s f2, f7 \n"
"addexp.s f6, f7 \n"
"divn.s f2,f9,f6\n"
"rfr %0, f2\n"
:"=r"(result):"r"(a), "r"(b)
);
return result;
}
static float sqrtsf(float a)
{
float result;
asm volatile (
"wfr f0, %1\n"
"sqrt0.s f2, f0\n"
"const.s f5, 0\n"
"maddn.s f5, f2, f2\n"
"nexp01.s f3, f0\n"
"const.s f4, 3\n"
"addexp.s f3, f4\n"
"maddn.s f4, f5, f3\n"
"nexp01.s f5, f0\n"
"neg.s f6, f5\n"
"maddn.s f2, f4, f2\n"
"const.s f1, 0\n"
"const.s f4, 0\n"
"const.s f7, 0\n"
"maddn.s f1, f6, f2\n"
"maddn.s f4, f2, f3\n"
"const.s f6, 3\n"
"maddn.s f7, f6, f2\n"
"maddn.s f5, f1, f1\n"
"maddn.s f6, f4, f2\n"
"neg.s f3, f7\n"
"maddn.s f1, f5, f3\n"
"maddn.s f7, f6, f7\n"
"mksadj.s f2, f0\n"
"nexp01.s f5, f0\n"
"maddn.s f5, f1, f1\n"
"neg.s f3, f7\n"
"addexpm.s f1, f2\n"
"addexp.s f3, f2\n"
"divn.s f1, f5, f3\n"
"rfr %0, f1\n"
:"=r"(result):"r"(a)
);
return result;
}
TEST_CASE("test FP add", "[fp]")
{
float a = 100.0f;
float b = 0.5f;
float c = addsf(a, b);
float eps = c - 100.5f;
printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps);
TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
}
TEST_CASE("test FP mul", "[fp]")
{
float a = 100.0f;
float b = 0.05f;
float c = mulsf(a, b);
float eps = c - 5.0f;
printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps);
TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
}
TEST_CASE("test FP div", "[fp]")
{
float a = 100.0f;
float b = 5.0f;
float c = divsf(a, b);
float eps = c - 20.0f;
printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps);
TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
}
TEST_CASE("test FP sqrt", "[fp]")
{
float a = 100.0f;
float c = sqrtsf(a);
float eps = c - 10.0f;
printf("a=%g c=%g eps=%g\r\n", a, c, eps);
TEST_ASSERT_TRUE(fabs(eps) < 0.000001);
}
struct TestFPState {
int fail;
int done;
};
static const int testFpIter = 100000;
static void tskTestFP(void *pvParameters)
{
struct TestFPState *state = (struct TestFPState *) pvParameters;
for (int i = 0; i < testFpIter; ++i) {
// calculate zero in a slightly obscure way
float y = sqrtsf(addsf(1.0f, divsf(mulsf(sqrtsf(2), sqrtsf(2)), 2.0f)));
y = mulsf(y, y);
y = addsf(y, -2.0f);
// check that result is not far from zero
float eps = fabs(y);
if (eps > 1e-6f) {
state->fail++;
printf("%s: i=%d y=%f eps=%f\r\n", __func__, i, y, eps);
}
}
state->done++;
vTaskDelete(NULL);
}
TEST_CASE("context switch saves FP registers", "[fp]")
{
struct TestFPState state;
state.done = 0;
state.fail = 0;
xTaskCreatePinnedToCore(tskTestFP, "tsk1", 2048, &state, 3, NULL, 0);
xTaskCreatePinnedToCore(tskTestFP, "tsk2", 2048, &state, 3, NULL, 0);
xTaskCreatePinnedToCore(tskTestFP, "tsk3", 2048, &state, 3, NULL, 1);
xTaskCreatePinnedToCore(tskTestFP, "tsk4", 2048, &state, 3, NULL, 0);
while (state.done != 4) {
vTaskDelay(100 / portTICK_PERIOD_MS);
}
if (state.fail) {
const int total = testFpIter * 4;
printf("Failed: %d, total: %d\r\n", state.fail, total);
}
TEST_ASSERT(state.fail == 0);
}
#endif

View File

@@ -0,0 +1,77 @@
#include <stdio.h>
#include "rom/miniz.h"
#include "unity.h"
#define DATASIZE (1024*64)
TEST_CASE("Test miniz compression/decompression", "[miniz]")
{
int x;
char b;
char *inbuf, *outbuf;
tdefl_compressor *comp;
tinfl_decompressor *decomp;
tdefl_status status;
size_t inbytes = 0, outbytes = 0, inpos = 0, outpos = 0, compsz;
printf("Allocating data buffer and filling it with semi-random data\n");
inbuf = malloc(DATASIZE);
TEST_ASSERT(inbuf != NULL);
srand(0);
for (x = 0; x < DATASIZE; x++) {
inbuf[x] = (x & 1) ? rand() & 0xff : 0;
}
printf("Allocating compressor & outbuf (%d bytes)\n", sizeof(tdefl_compressor));
comp = malloc(sizeof(tdefl_compressor));
TEST_ASSERT(comp != NULL);
outbuf = malloc(DATASIZE);
TEST_ASSERT(outbuf != NULL);
printf("Compressing...\n");
status = tdefl_init(comp, NULL, NULL, TDEFL_WRITE_ZLIB_HEADER | 1500);
TEST_ASSERT(status == TDEFL_STATUS_OKAY);
while (inbytes != DATASIZE) {
outbytes = DATASIZE - outpos;
inbytes = DATASIZE - inpos;
tdefl_compress(comp, &inbuf[inpos], &inbytes, &outbuf[outpos], &outbytes, TDEFL_FINISH);
printf("...Compressed %d into %d bytes\n", inbytes, outbytes);
inpos += inbytes; outpos += outbytes;
}
compsz = outpos;
free(comp);
//Kill inbuffer
for (x = 0; x < DATASIZE; x++) {
inbuf[x] = 0;
}
free(inbuf);
inbuf = outbuf;
outbuf = malloc(DATASIZE);
TEST_ASSERT(outbuf != NULL);
printf("Reinflating...\n");
decomp = malloc(sizeof(tinfl_decompressor));
TEST_ASSERT(decomp != NULL);
tinfl_init(decomp);
inpos = 0; outpos = 0;
while (inbytes != compsz) {
outbytes = DATASIZE - outpos;
inbytes = compsz - inpos;
tinfl_decompress(decomp, (const mz_uint8 *)&inbuf[inpos], &inbytes, (uint8_t *)outbuf, (mz_uint8 *)&outbuf[outpos], &outbytes, TINFL_FLAG_PARSE_ZLIB_HEADER);
printf("...Decompressed %d into %d bytes\n", inbytes, outbytes);
inpos += inbytes; outpos += outbytes;
}
printf("Checking if same...\n");
srand(0);
for (x = 0; x < DATASIZE; x++) {
b = (x & 1) ? rand() & 0xff : 0;
if (outbuf[x] != b) {
printf("Pos %x: %hhx!=%hhx\n", x, outbuf[x], b);
TEST_ASSERT(0);
}
}
printf("Great Success!\n");
free(inbuf);
free(outbuf);
free(decomp);
}

View File

@@ -0,0 +1,91 @@
#include <stdio.h>
#include "rom/tjpgd.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "unity.h"
#include "test_tjpgd_logo.h"
typedef struct {
const unsigned char *inData;
int inPos;
unsigned char *outData;
int outW;
int outH;
} JpegDev;
static UINT infunc(JDEC *decoder, BYTE *buf, UINT len)
{
JpegDev *jd = (JpegDev *)decoder->device;
printf("Reading %d bytes from pos %d\n", len, jd->inPos);
if (buf != NULL) {
memcpy(buf, jd->inData + jd->inPos, len);
}
jd->inPos += len;
return len;
}
static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect)
{
unsigned char *in = (unsigned char *)bitmap;
unsigned char *out;
int y;
printf("Rect %d,%d - %d,%d\n", rect->top, rect->left, rect->bottom, rect->right);
JpegDev *jd = (JpegDev *)decoder->device;
for (y = rect->top; y <= rect->bottom; y++) {
out = jd->outData + ((jd->outW * y) + rect->left) * 3;
memcpy(out, in, ((rect->right - rect->left) + 1) * 3);
in += ((rect->right - rect->left) + 1) * 3;
}
return 1;
}
#define TESTW 48
#define TESTH 48
#define WORKSZ 3100
TEST_CASE("Test JPEG decompression library", "[tjpgd]")
{
char aapix[] = " .:;+=xX$$";
unsigned char *decoded, *p;
char *work;
int r;
int x, y, v;
JDEC decoder;
JpegDev jd;
decoded = malloc(48 * 48 * 3);
for (x = 0; x < 48 * 48 * 3; x += 2) {
decoded[x] = 0; decoded[x + 1] = 0xff;
}
work = malloc(WORKSZ);
memset(work, 0, WORKSZ);
jd.inData = logo_jpg;
jd.inPos = 0;
jd.outData = decoded;
jd.outW = TESTW;
jd.outH = TESTH;
r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd);
TEST_ASSERT_EQUAL(r, JDR_OK);
r = jd_decomp(&decoder, outfunc, 0);
TEST_ASSERT_EQUAL(r, JDR_OK);
p = decoded + 2;
for (y = 0; y < TESTH; y++) {
for (x = 0; x < TESTH; x++) {
v = ((*p) * (sizeof(aapix) - 2) * 2) / 256;
printf("%c%c", aapix[v / 2], aapix[(v + 1) / 2]);
p += 3;
}
printf("%c%c", ' ', '\n');
}
free(work);
free(decoded);
}

View File

@@ -0,0 +1,205 @@
#include <esp_types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rom/ets_sys.h"
#include "rom/lldesc.h"
#include "rom/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "soc/uart_reg.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_reg.h"
#include "soc/i2s_reg.h"
#define DPORT_I2S0_CLK_EN (BIT(4))
#define DPORT_I2S0_RST (BIT(4))
static volatile lldesc_t dmaDesc[2];
//hacked up routine to essentially do a memcpy() using dma. Supports max 4K-1 bytes.
static void dmaMemcpy(void *in, void *out, int len)
{
volatile int i;
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
//Init pins to i2s functions
SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS
WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S));
WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS
WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S));
// WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX<<GPIO_GPIO_FUNC0_OUT_SEL_S));
//GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
//Reset I2S subsystem
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_I2S_SIG_LOOPBACK);
WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
(16 << I2S_RX_BITS_MOD_S) |
(16 << I2S_TX_BITS_MOD_S) |
(1 << I2S_RX_BCK_DIV_NUM_S) |
(1 << I2S_TX_BCK_DIV_NUM_S));
WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
I2S_CLKA_ENA | I2S_CLK_EN |
(1 << I2S_CLKM_DIV_A_S) |
(1 << I2S_CLKM_DIV_B_S) |
(1 << I2S_CLKM_DIV_NUM_S));
WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
(32 << I2S_TX_DATA_NUM_S) | //Low watermark for IRQ
(32 << I2S_RX_DATA_NUM_S));
WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
//Invert WS to active-low
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
//--
//Fill DMA descriptor
dmaDesc[0].length = len;
dmaDesc[0].size = len;
dmaDesc[0].owner = 1;
dmaDesc[0].sosf = 0;
dmaDesc[0].buf = (uint8_t *)in;
dmaDesc[0].offset = 0; //unused in hw
dmaDesc[0].empty = 0;
dmaDesc[0].eof = 1;
dmaDesc[1].length = len;
dmaDesc[1].size = len;
dmaDesc[1].owner = 1;
dmaDesc[1].sosf = 0;
dmaDesc[1].buf = (uint8_t *)out;
dmaDesc[1].offset = 0; //unused in hw
dmaDesc[1].empty = 0;
dmaDesc[1].eof = 1;
//Reset DMA
SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
//Reset I2S FIFO
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
//Set desc addr
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
//Enable and configure DMA
WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN |
I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
//Start transmission
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
//Clear int flags
WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
//--
//No need to finish if no DMA transfer going on
if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
return;
}
//Wait till fifo done
while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
//Wait for last bytes to leave i2s xmit thing
//ToDo: poll bit in next hw
for (i = 0; i < (1 << 8); i++);
while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
//Reset I2S for next transfer
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
// for (i=0; i<(1<<8); i++);
while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
}
int mymemcmp(char *a, char *b, int len)
{
int x;
for (x = 0; x < len; x++) {
if (a[x] != b[x]) {
printf("Not equal at byte %d. a=%x, b=%x\n", x, (int)a[x], (int)b[x]);
return 1;
}
}
return 0;
}
TEST_CASE("Unaligned DMA test (needs I2S)", "[hw]")
{
int x;
char src[2049], dest[2049];
for (x = 0; x < sizeof(src); x++) {
src[x] = x & 0xff;
}
printf("Aligned dma\n");
memset(dest, 0, 2049);
dmaMemcpy(src, dest, 2048 + 1);
TEST_ASSERT(mymemcmp(src, dest, 2048) == 0);
printf("Src unaligned\n");
dmaMemcpy(src + 1, dest, 2048 + 1);
TEST_ASSERT(mymemcmp(src + 1, dest, 2048) == 0);
printf("Dst unaligned\n");
dmaMemcpy(src, dest + 1, 2048 + 2);
TEST_ASSERT(mymemcmp(src, dest + 1, 2048) == 0);
}