1 
2 #include <esp_types.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include "esp32/rom/lldesc.h"
6 #include "driver/periph_ctrl.h"
7 #include "hal/gpio_hal.h"
8 #include "freertos/FreeRTOS.h"
9 #include "freertos/task.h"
10 #include "freertos/semphr.h"
11 #include "freertos/queue.h"
12 #include "freertos/xtensa_api.h"
13 
14 #include "unity.h"
15 
16 #include "soc/uart_periph.h"
17 #include "soc/dport_reg.h"
18 #include "soc/gpio_periph.h"
19 #include "soc/i2s_periph.h"
20 
21 
22 
23 #define DPORT_I2S0_CLK_EN   (BIT(4))
24 #define DPORT_I2S0_RST   (BIT(4))
25 
26 
27 /*
28 This test tests the s32c1i instruction when the AHB bus is also used. To create some AHB traffic, we use the I2S interface
29 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
30 the point where they happened to do what I want.
31 */
32 
lcdIfaceInit(void)33 static void lcdIfaceInit(void)
34 {
35     periph_module_enable(PERIPH_I2S0_MODULE);
36 
37     //Init pins to i2s functions
38     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
39 
40     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, 0);
41     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO2_U, 0);
42     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO5_U, 0);
43     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, 0);
44     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, 0);
45     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO18_U, 0);
46     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, 0);
47     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO20_U, 0);
48     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, 2); //11
49     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, 0); //RS
50 
51     WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S));
52     WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S));
53     WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S));
54     WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S));
55     WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S));
56     WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S));
57     WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S));
58     WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S));
59     WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS
60     WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S));
61 //  WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX<<GPIO_GPIO_FUNC0_OUT_SEL_S));
62 
63     //GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
64     WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
65 
66     //Reset I2S subsystem
67     CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
68     SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
69     CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
70 
71     WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_SIG_LOOPBACK);
72     WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
73 
74     WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
75                    (16 << I2S_RX_BITS_MOD_S) |
76                    (16 << I2S_TX_BITS_MOD_S) |
77                    (1 << I2S_RX_BCK_DIV_NUM_S) |
78                    (1 << I2S_TX_BCK_DIV_NUM_S));
79     WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
80                    I2S_CLKA_ENA | I2S_CLK_EN |
81                    (1 << I2S_CLKM_DIV_A_S) |
82                    (1 << I2S_CLKM_DIV_B_S) |
83                    (1 << I2S_CLKM_DIV_NUM_S));
84     WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
85                    (32 << I2S_TX_DATA_NUM_S) |     //Low watermark for IRQ
86                    (32 << I2S_RX_DATA_NUM_S));
87 
88     WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
89 
90     WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
91 
92     //Invert WS to active-low
93     SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
94     WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
95 }
96 
97 
98 static volatile lldesc_t dmaDesc[2];
99 
finishDma(void)100 static void finishDma(void)
101 {
102     //No need to finish if no DMA transfer going on
103     if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
104         return;
105     }
106 
107     //Wait till fifo done
108     while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
109     //Wait for last bytes to leave i2s xmit thing
110     //ToDo: poll bit in next hw
111 //  for (i=0; i<(1<<8); i++);
112     while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
113 
114     //Reset I2S for next transfer
115     CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
116     CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
117 
118     SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
119     CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
120 
121 //  for (i=0; i<(1<<8); i++);
122     while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
123 }
124 
125 
126 /*
127 This is a very, very, very hacked up LCD routine which ends up basically doing a memcpy from sbuf to rbuf.
128 */
sendRecvBufDma(uint16_t * sbuf,uint16_t * rbuf,int len)129 static void sendRecvBufDma(uint16_t *sbuf, uint16_t *rbuf, int len)
130 {
131     //Fill DMA descriptor
132     dmaDesc[0].length = len * 2;
133     dmaDesc[0].size = len * 2;
134     dmaDesc[0].owner = 1;
135     dmaDesc[0].sosf = 0;
136     dmaDesc[0].buf = (uint8_t *)sbuf;
137     dmaDesc[0].offset = 0; //unused in hw
138     dmaDesc[0].empty = 0;
139     dmaDesc[0].eof = 1;
140     dmaDesc[1].length = len * 2;
141     dmaDesc[1].size = len * 2;
142     dmaDesc[1].owner = 1;
143     dmaDesc[1].sosf = 0;
144     dmaDesc[1].buf = (uint8_t *)rbuf;
145     dmaDesc[1].offset = 0; //unused in hw
146     dmaDesc[1].empty = 0;
147     dmaDesc[1].eof = 1;
148 
149     //Reset DMA
150     SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
151     CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
152 
153     //Reset I2S FIFO
154     SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
155     CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
156 
157     //Set desc addr
158     CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
159     SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
160     CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
161     SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
162 
163     SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
164 
165     WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
166 
167     //Enable and configure DMA
168     WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN  |
169                    I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
170                    I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
171 
172     //Start transmission
173     SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
174     SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
175 
176     SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
177     //Clear int flags
178     WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
179 }
180 
181 
182 #define DMALEN (2048-2)
183 
tskLcd(void * pvParameters)184 static void tskLcd(void *pvParameters)
185 {
186     uint16_t *sbuf = malloc(DMALEN * 2);
187     uint16_t *rbuf = malloc(DMALEN * 2);
188     uint16_t xorval = 0;
189     int x;
190     lcdIfaceInit();
191 //  lcdFlush();
192     while (1) {
193         for (x = 0; x < DMALEN; x++) {
194             sbuf[x] = x ^ xorval;
195         }
196         for (x = 0; x < DMALEN; x++) {
197             rbuf[x] = 0;    //clear rbuf
198         }
199         sendRecvBufDma(sbuf, rbuf, DMALEN);
200         vTaskDelay(20 / portTICK_PERIOD_MS);
201         finishDma();
202         for (x = 0; x < DMALEN; x++) if (rbuf[x] != (x ^ xorval)) {
203                 printf("Rxbuf err! pos %d val %x xor %x", x, (int)rbuf[x], (int)xorval);
204             }
205         printf(".");
206         fflush(stdout);
207         xorval++;
208     }
209 }
210 
211 
212 
213 void test_s32c1i_lock(volatile int *lockvar, int lockval, int unlockval, volatile int *ctr);
214 
215 static volatile int ctr = 0, state = 0;
216 static volatile int lock = 0;
217 
tskOne(void * pvParameters)218 static void tskOne(void *pvParameters)
219 {
220     int x;
221     int err = 0, run = 0;
222     while (1) {
223         ctr = 0; lock = 0;
224         state = 1;
225         for (x = 0; x < 16 * 1024; x++) {
226             test_s32c1i_lock(&lock, 1, 0, &ctr);
227         }
228         vTaskDelay(60 / portTICK_PERIOD_MS);
229         state = 2;
230         if (ctr != 16 * 1024 * 2) {
231             printf("Lock malfunction detected! Ctr=0x%x instead of %x\n", ctr, 16 * 1024 * 2);
232             err++;
233         }
234         run++;
235         printf("Run %d err %d\n", run, err);
236         vTaskDelay(20 / portTICK_PERIOD_MS);
237     }
238 }
239 
240 #define FB2ADDR 0x40098000
241 
tskTwo(void * pvParameters)242 static void tskTwo(void *pvParameters)
243 {
244     int x;
245     int *p = (int *)FB2ADDR;
246     int *s = (int *)test_s32c1i_lock;
247     void (*test_s32c1i_lock2)(volatile int * lockvar, int lockval, int unlockval, volatile int * ctr) = (void *)FB2ADDR;
248     volatile int w;
249     int delay;
250     for (x = 0; x < 100; x++) {
251         *p++ = *s++;    //copy routine to different pool
252     }
253 
254     while (1) {
255         while (state != 1) ;
256         for (x = 0; x < 16 * 1024; x++) {
257             test_s32c1i_lock2(&lock, 2, 0, &ctr);
258             //Some random delay to increase chance of weirdness
259             if ((x & 0x1f) == 0) {
260                 delay = rand() & 0x1f;
261                 for (w = 0; w < delay; w++);
262             }
263         }
264         while (state != 2);
265     }
266 }
267 
268 
269 TEST_CASE("S32C1I vs AHB test (needs I2S)", "[hw][ignore]")
270 {
271     int i;
272     TaskHandle_t th[3];
273     state = 0;
274 
275     printf("Creating tasks\n");
276     xTaskCreatePinnedToCore(tskTwo  , "tsktwo"  , 2048, NULL, 3, &th[1], 1);
277     xTaskCreatePinnedToCore(tskOne  , "tskone"  , 2048, NULL, 3, &th[0], 0);
278     xTaskCreatePinnedToCore(tskLcd  , "tsklcd"  , 2048, NULL, 3, &th[2], 0);
279 
280     // Let stuff run for 20s
281     while (1) {
282         vTaskDelay(20000 / portTICK_PERIOD_MS);
283     }
284 
285     //Shut down all the tasks
286     for (i = 0; i < 3; i++) {
287         vTaskDelete(th[i]);
288     }
289 }
290