test_ahb_arb.c 10 KB

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