test_spi_slave_hd.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /*
  2. Tests for the spi slave hd mode
  3. */
  4. #include "esp_log.h"
  5. #include "freertos/FreeRTOS.h"
  6. #include "freertos/task.h"
  7. #include "freertos/semphr.h"
  8. #include "unity.h"
  9. #include "soc/spi_periph.h"
  10. #include "driver/spi_master.h"
  11. #include "esp_serial_slave_link/essl_spi.h"
  12. #if !DISABLED_FOR_TARGETS(ESP32C3)
  13. //There is only one GPSPI controller on ESP32C3, so single-board test is disabled.
  14. #if SOC_SPI_SUPPORT_SLAVE_HD_VER2
  15. #include "driver/spi_slave_hd.h"
  16. #include "esp_rom_gpio.h"
  17. #include "unity.h"
  18. #include "test/test_common_spi.h"
  19. #define TEST_DMA_MAX_SIZE 4092
  20. #define TEST_BUFFER_SIZE 256 ///< buffer size of each wrdma buffer in fifo mode
  21. #define TEST_SEG_SIZE 25
  22. //ESP32-S2 cannot do single board test over IOMUX+GPIO matrix
  23. #define TEST_MASTER_GPIO_MATRIX 1
  24. #define SPI_SLOT_TEST_DEFAULT_CONFIG() {\
  25. .spics_io_num = PIN_NUM_CS, \
  26. .flags = 0, \
  27. .mode = 0, \
  28. .command_bits = 8,\
  29. .address_bits = 8,\
  30. .dummy_bits = 8,\
  31. .queue_size = 10,\
  32. }
  33. //context definition for the tcf framework
  34. typedef struct {
  35. WORD_ALIGNED_ATTR uint8_t master_wrdma_buf[TEST_DMA_MAX_SIZE];
  36. WORD_ALIGNED_ATTR uint8_t master_rddma_buf[TEST_DMA_MAX_SIZE];
  37. WORD_ALIGNED_ATTR uint8_t slave_wrdma_buf[TEST_DMA_MAX_SIZE];
  38. WORD_ALIGNED_ATTR uint8_t slave_rddma_buf[TEST_DMA_MAX_SIZE];
  39. SemaphoreHandle_t ev_rdbuf;
  40. SemaphoreHandle_t ev_wrbuf;
  41. spi_slave_hd_data_t tx_data;
  42. spi_slave_hd_data_t rx_data;
  43. } testhd_context_t;
  44. static uint32_t get_hd_flags(void)
  45. {
  46. #if !defined(SLAVE_SUPPORT_QIO)
  47. return 0;
  48. #endif
  49. int flag_id = rand() % 5;
  50. ESP_LOGI("io mode", "%d", flag_id);
  51. switch (flag_id) {
  52. case 1:
  53. return SPI_TRANS_MODE_DIO;
  54. case 2:
  55. return SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_DIOQIO_ADDR;
  56. case 3:
  57. return SPI_TRANS_MODE_QIO;
  58. case 4:
  59. return SPI_TRANS_MODE_QIO | SPI_TRANS_MODE_DIOQIO_ADDR;
  60. default:
  61. return 0;
  62. }
  63. }
  64. void config_single_board_test_pin(void)
  65. {
  66. esp_rom_gpio_connect_out_signal(PIN_NUM_MOSI, spi_periph_signal[TEST_SPI_HOST].spid_out, 0, 0);
  67. esp_rom_gpio_connect_in_signal(PIN_NUM_MOSI, spi_periph_signal[TEST_SLAVE_HOST].spid_in, 0);
  68. esp_rom_gpio_connect_out_signal(PIN_NUM_MISO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out, 0, 0);
  69. esp_rom_gpio_connect_in_signal(PIN_NUM_MISO, spi_periph_signal[TEST_SPI_HOST].spiq_in, 0);
  70. esp_rom_gpio_connect_out_signal(PIN_NUM_CS, spi_periph_signal[TEST_SPI_HOST].spics_out[0], 0, 0);
  71. esp_rom_gpio_connect_in_signal(PIN_NUM_CS, spi_periph_signal[TEST_SLAVE_HOST].spics_in, 0);
  72. esp_rom_gpio_connect_out_signal(PIN_NUM_CLK, spi_periph_signal[TEST_SPI_HOST].spiclk_out, 0, 0);
  73. esp_rom_gpio_connect_in_signal(PIN_NUM_CLK, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in, 0);
  74. }
  75. static void init_master_hd(spi_device_handle_t* spi, const spitest_param_set_t* config, int freq)
  76. {
  77. spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
  78. bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE*30;
  79. bus_cfg.quadhd_io_num = PIN_NUM_HD;
  80. bus_cfg.quadwp_io_num = PIN_NUM_WP;
  81. #if defined(TEST_MASTER_GPIO_MATRIX) && CONFIG_IDF_TARGET_ESP32S2
  82. bus_cfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
  83. #endif
  84. TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
  85. spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
  86. dev_cfg.flags = SPI_DEVICE_HALFDUPLEX;
  87. dev_cfg.command_bits = 8;
  88. dev_cfg.address_bits = 8;
  89. dev_cfg.dummy_bits = 8;
  90. dev_cfg.clock_speed_hz = freq;
  91. dev_cfg.mode = config->mode;
  92. dev_cfg.input_delay_ns = config->slave_tv_ns;
  93. TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, spi));
  94. }
  95. static void init_slave_hd(int mode, bool append_mode, const spi_slave_hd_callback_config_t* callback)
  96. {
  97. spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
  98. bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE*30;
  99. bus_cfg.quadwp_io_num = -1;
  100. bus_cfg.quadhd_io_num = -1;
  101. #ifdef TEST_SLAVE_GPIO_MATRIX
  102. bus_cfg.flags |= SPICOMMON_BUSFLAG_FORCE_GPIO;
  103. #endif
  104. spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
  105. slave_hd_cfg.mode = mode;
  106. slave_hd_cfg.dma_chan = SPI_DMA_CH_AUTO;
  107. if (append_mode) {
  108. slave_hd_cfg.flags |= SPI_SLAVE_HD_APPEND_MODE;
  109. }
  110. if (callback) {
  111. slave_hd_cfg.cb_config = *callback;
  112. } else {
  113. slave_hd_cfg.cb_config = (spi_slave_hd_callback_config_t){};
  114. }
  115. TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
  116. }
  117. static void test_hd_init(void** arg)
  118. {
  119. TEST_ASSERT(*arg==NULL);
  120. *arg = malloc(sizeof(testhd_context_t));
  121. assert(((int)arg%4)==0);
  122. testhd_context_t* context = (testhd_context_t*)*arg;
  123. TEST_ASSERT(context!=NULL);
  124. context->ev_rdbuf = xSemaphoreCreateBinary();
  125. context->ev_wrbuf = xSemaphoreCreateBinary();
  126. }
  127. static void test_hd_deinit(void* arg)
  128. {
  129. testhd_context_t *context = arg;
  130. vSemaphoreDelete(context->ev_rdbuf);
  131. vSemaphoreDelete(context->ev_wrbuf);
  132. }
  133. esp_err_t wait_wrbuf_sig(testhd_context_t* context, TickType_t wait)
  134. {
  135. BaseType_t r = xSemaphoreTake(context->ev_wrbuf, wait);
  136. if (r==pdTRUE) {
  137. return ESP_OK;
  138. } else {
  139. return ESP_ERR_TIMEOUT;
  140. }
  141. }
  142. esp_err_t wait_rdbuf_sig(testhd_context_t* context, TickType_t wait)
  143. {
  144. BaseType_t r = xSemaphoreTake(context->ev_rdbuf, wait);
  145. if (r==pdTRUE) {
  146. return ESP_OK;
  147. } else {
  148. return ESP_ERR_TIMEOUT;
  149. }
  150. }
  151. static void check_no_rx(testhd_context_t* context)
  152. {
  153. spi_slave_hd_data_t* ret_trans;
  154. esp_err_t ret = spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, 0);
  155. TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, ret);
  156. }
  157. static void check_no_tx(testhd_context_t* context)
  158. {
  159. spi_slave_hd_data_t* ret_trans;
  160. esp_err_t ret = spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, 0);
  161. TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, ret);
  162. }
  163. bool wrbuf_cb(void* arg, spi_slave_hd_event_t* ev, BaseType_t* awoken)
  164. {
  165. TEST_ASSERT_EQUAL(SPI_EV_BUF_RX, ev->event);
  166. testhd_context_t* ctx = (testhd_context_t*)arg;
  167. BaseType_t r = xSemaphoreGiveFromISR(ctx->ev_wrbuf, awoken);
  168. TEST_ASSERT_TRUE(r);
  169. return true;
  170. }
  171. bool rdbuf_cb(void* arg, spi_slave_hd_event_t* ev, BaseType_t* awoken)
  172. {
  173. TEST_ASSERT_EQUAL(SPI_EV_BUF_TX, ev->event);
  174. testhd_context_t* ctx = (testhd_context_t*)arg;
  175. BaseType_t r = xSemaphoreGiveFromISR(ctx->ev_rdbuf, awoken);
  176. TEST_ASSERT_TRUE(r);
  177. return true;
  178. }
  179. static void test_hd_start(spi_device_handle_t *spi, int freq, const spitest_param_set_t* cfg, testhd_context_t* ctx)
  180. {
  181. init_master_hd(spi, cfg, freq);
  182. spi_slave_hd_callback_config_t callback = {
  183. .cb_buffer_rx = wrbuf_cb,
  184. .cb_buffer_tx = rdbuf_cb,
  185. .arg = ctx,
  186. };
  187. init_slave_hd(cfg->mode, 0, &callback);
  188. //when test with single board via same set of mosi, miso, clk and cs pins.
  189. config_single_board_test_pin();
  190. wait_wrbuf_sig(ctx, 0);
  191. wait_rdbuf_sig(ctx, 0);
  192. check_no_rx(ctx);
  193. check_no_tx(ctx);
  194. srand(9322);
  195. for (int i = 0; i < TEST_DMA_MAX_SIZE; i++) ctx->slave_rddma_buf[i] = rand();
  196. for (int i = 0; i < TEST_DMA_MAX_SIZE; i++) ctx->master_wrdma_buf[i] = rand();
  197. int pos = rand() % TEST_DMA_MAX_SIZE;
  198. int len = rand() % TEST_DMA_MAX_SIZE + 1;
  199. if (pos + len > TEST_DMA_MAX_SIZE) len = TEST_DMA_MAX_SIZE - pos;
  200. ESP_LOGI("rddma_load_len", "%d", len);
  201. ctx->tx_data = (spi_slave_hd_data_t) {
  202. .data = &ctx->slave_rddma_buf[pos],
  203. .len = len,
  204. };
  205. esp_err_t err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ctx->tx_data, portMAX_DELAY);
  206. TEST_ESP_OK(err);
  207. ctx->rx_data = (spi_slave_hd_data_t) {
  208. .data = ctx->slave_wrdma_buf,
  209. .len = TEST_DMA_MAX_SIZE,
  210. };
  211. err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ctx->rx_data, portMAX_DELAY);
  212. TEST_ESP_OK(err);
  213. }
  214. #define REG_REGION_SIZE SOC_SPI_MAXIMUM_BUFFER_SIZE
  215. void check_no_signal(testhd_context_t* context)
  216. {
  217. vTaskDelay(1);
  218. TEST_ASSERT(wait_wrbuf_sig(context, 0) == ESP_ERR_TIMEOUT);
  219. TEST_ASSERT(wait_rdbuf_sig(context, 0) == ESP_ERR_TIMEOUT);
  220. check_no_rx(context);
  221. check_no_tx(context);
  222. }
  223. void test_wrdma(testhd_context_t* ctx, const spitest_param_set_t *cfg, spi_device_handle_t spi)
  224. {
  225. int pos = rand() % TEST_DMA_MAX_SIZE;
  226. int len = rand() % TEST_DMA_MAX_SIZE+1;
  227. if (pos+len > TEST_DMA_MAX_SIZE) len = TEST_DMA_MAX_SIZE - pos;
  228. int test_seg_size = len;//TEST_SEG_SIZE;
  229. ESP_LOGW("test_wrdma", "len: %d, seg_size: %d\n", len, test_seg_size);
  230. TEST_ESP_OK(essl_spi_wrdma(spi, &ctx->master_wrdma_buf[pos], len, test_seg_size, get_hd_flags()));
  231. spi_slave_hd_data_t* ret_trans;
  232. esp_err_t ret = spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY);
  233. TEST_ESP_OK(ret);
  234. TEST_ASSERT_EQUAL(&ctx->rx_data, ret_trans);
  235. TEST_ASSERT_EQUAL(len, ret_trans->trans_len);
  236. TEST_ASSERT_EQUAL_HEX8_ARRAY(&ctx->master_wrdma_buf[pos], ctx->slave_wrdma_buf, len);
  237. ctx->rx_data = (spi_slave_hd_data_t) {
  238. .data = ctx->slave_wrdma_buf,
  239. .len = TEST_DMA_MAX_SIZE,
  240. };
  241. esp_err_t err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ctx->rx_data, portMAX_DELAY);
  242. TEST_ESP_OK(err);
  243. }
  244. void test_rddma(testhd_context_t* ctx, const spitest_param_set_t* cfg, spi_device_handle_t spi)
  245. {
  246. uint8_t* data_expected = ctx->tx_data.data;
  247. int len;
  248. int test_seg_size;
  249. len = ctx->tx_data.len;
  250. test_seg_size = TEST_SEG_SIZE;
  251. ESP_LOGW("test_rddma", "pos: %d, len: %d, slave_tx: %d, seg_size: %d\n", data_expected - ctx->slave_rddma_buf, len, ctx->tx_data.len, test_seg_size);
  252. TEST_ESP_OK(essl_spi_rddma(spi, ctx->master_rddma_buf, len, test_seg_size, get_hd_flags()));
  253. spi_slave_hd_data_t* ret_trans;
  254. esp_err_t ret = spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY);
  255. TEST_ESP_OK(ret);
  256. TEST_ASSERT_EQUAL(&ctx->tx_data, ret_trans);
  257. spitest_cmp_or_dump(data_expected, ctx->master_rddma_buf, len);
  258. int pos = rand() % TEST_DMA_MAX_SIZE;
  259. len = rand() % TEST_DMA_MAX_SIZE+1;
  260. if (pos + len > TEST_DMA_MAX_SIZE) len = TEST_DMA_MAX_SIZE - pos;
  261. ctx->tx_data = (spi_slave_hd_data_t) {
  262. .data = &ctx->slave_rddma_buf[pos],
  263. .len = len,
  264. };
  265. esp_err_t err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ctx->tx_data, portMAX_DELAY);
  266. TEST_ESP_OK(err);
  267. }
  268. static void test_hd_loop(const void* arg1, void* arg2)
  269. {
  270. const spitest_param_set_t *test_cfg = arg1;
  271. testhd_context_t *context = arg2;
  272. const int *timing_speed_array = test_cfg->freq_list;
  273. ESP_LOGI(MASTER_TAG, "****************** %s ***************", test_cfg->pset_name);
  274. for (int j = 0; ; j++) {
  275. spi_device_handle_t spi;
  276. const int freq = timing_speed_array[j];
  277. if (freq==0) break;
  278. if (test_cfg->freq_limit && freq > test_cfg->freq_limit) break;
  279. ESP_LOGI(MASTER_TAG, "======> %dk", freq / 1000);
  280. test_hd_start(&spi, freq, test_cfg, context);
  281. uint8_t* mem_ptr;
  282. uint8_t slave_mem[REG_REGION_SIZE];
  283. uint8_t recv_buffer[REG_REGION_SIZE];
  284. srand(123);
  285. uint32_t mem[(REG_REGION_SIZE/4)];
  286. for (int i = 0; i < (REG_REGION_SIZE/4); i++) {
  287. mem[i] = rand();
  288. }
  289. mem_ptr = (uint8_t*)mem;
  290. check_no_signal(context);
  291. spi_slave_hd_write_buffer(TEST_SLAVE_HOST, 0, (uint8_t *) mem, SOC_SPI_MAXIMUM_BUFFER_SIZE);
  292. srand(123);
  293. for (int i = 0; i < (REG_REGION_SIZE/4); i++) {
  294. TEST_ASSERT(mem[i] == rand());
  295. }
  296. check_no_signal(context);
  297. test_rddma(context, test_cfg, spi);
  298. for (int i = 0; i < 128; i ++) {
  299. int pos = rand()%REG_REGION_SIZE;
  300. int len = rand()%REG_REGION_SIZE+1;
  301. if (len+pos>REG_REGION_SIZE) len = REG_REGION_SIZE-pos;
  302. memset(recv_buffer, 0xcc, sizeof(recv_buffer));
  303. check_no_signal(context);
  304. test_wrdma(context, test_cfg, spi);
  305. check_no_signal(context);
  306. test_rddma(context, test_cfg, spi);
  307. check_no_signal(context);
  308. TEST_ESP_OK(essl_spi_rdbuf(spi, recv_buffer, pos, len, get_hd_flags()));
  309. wait_rdbuf_sig(context, portMAX_DELAY);
  310. ESP_LOGI("mem", "pos: %d, len: %d", pos, len);
  311. // ESP_LOG_BUFFER_HEX("recv_buffer", recv_buffer, len);
  312. // ESP_LOG_BUFFER_HEX("mem", &mem_ptr[pos], len);
  313. TEST_ASSERT_EQUAL_HEX8_ARRAY(&mem_ptr[pos], recv_buffer, len);
  314. }
  315. check_no_signal(context);
  316. //clear slave buffer
  317. memset(mem, 0xcc, REG_REGION_SIZE);
  318. memcpy(slave_mem, mem, REG_REGION_SIZE);
  319. TEST_ESP_OK(essl_spi_wrbuf(spi, mem_ptr, 0, REG_REGION_SIZE, get_hd_flags()));
  320. wait_wrbuf_sig(context, portMAX_DELAY);
  321. TEST_ESP_OK(essl_spi_rdbuf(spi, recv_buffer, 0, REG_REGION_SIZE, get_hd_flags()));
  322. wait_rdbuf_sig(context, portMAX_DELAY);
  323. TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_mem, recv_buffer, REG_REGION_SIZE);
  324. srand(466);
  325. for (int i = 0; i < 64; i ++) {
  326. ESP_LOGI("temp_i", "^^^^^^^^^^^^^^^^ %d ^^^^^^^^^^", i);
  327. for (int j = 0; j < (REG_REGION_SIZE/4); j++) {
  328. mem[j] = rand();
  329. }
  330. for (int k = 0; k < 2; k++) {
  331. int pos = rand() % REG_REGION_SIZE;
  332. int len = rand() % REG_REGION_SIZE + 1;
  333. if (len + pos > REG_REGION_SIZE) len = REG_REGION_SIZE - pos;
  334. printf("pos: %d, len: %d\n", pos, len);
  335. TEST_ESP_OK(essl_spi_wrbuf(spi, &mem_ptr[pos], pos, len, get_hd_flags()));
  336. wait_wrbuf_sig(context, portMAX_DELAY);
  337. memcpy(&slave_mem[pos], &mem_ptr[pos], len);
  338. }
  339. check_no_signal(context);
  340. test_rddma(context, test_cfg, spi);
  341. check_no_signal(context);
  342. test_wrdma(context, test_cfg, spi);
  343. TEST_ESP_OK(essl_spi_rdbuf(spi, recv_buffer, 0, REG_REGION_SIZE, get_hd_flags()));
  344. wait_rdbuf_sig(context, portMAX_DELAY);
  345. check_no_signal(context);
  346. TEST_ASSERT_EQUAL_HEX8_ARRAY(&slave_mem, recv_buffer, REG_REGION_SIZE);
  347. }
  348. master_free_device_bus(spi);
  349. spi_slave_hd_deinit(TEST_SLAVE_HOST);
  350. }
  351. }
  352. static const ptest_func_t hd_test_func = {
  353. .pre_test = test_hd_init,
  354. .post_test = test_hd_deinit,
  355. .loop = test_hd_loop,
  356. .def_param = spitest_def_param,
  357. };
  358. #define TEST_SPI_HD(name, test_set) \
  359. PARAM_GROUP_DECLARE(name, test_set) \
  360. TEST_SINGLE_BOARD(name, test_set, "[spi][timeout=120]", &hd_test_func)
  361. static int test_freq_hd[] = {
  362. // 100*1000,
  363. // SPI_MASTER_FREQ_10M, //maximum freq MISO stable before next latch edge
  364. // SPI_MASTER_FREQ_20M, //maximum freq MISO stable before next latch edge
  365. SPI_MASTER_FREQ_40M, //maximum freq MISO stable before next latch edge
  366. 0,
  367. };
  368. #define TEST_HD_IN_CONTINUOUS_MODE true
  369. static spitest_param_set_t hd_conf[] = {
  370. { .pset_name = "MODE0",
  371. .freq_list = test_freq_hd,
  372. .dup = FULL_DUPLEX,
  373. .master_iomux = false,
  374. .slave_iomux = false,
  375. .slave_tv_ns = TV_WITH_ESP_SLAVE,
  376. .mode = 0,
  377. },
  378. { .pset_name = "MODE1",
  379. .freq_list = test_freq_hd,
  380. .dup = FULL_DUPLEX,
  381. .master_iomux = false,
  382. .slave_iomux = false,
  383. .slave_tv_ns = TV_WITH_ESP_SLAVE,
  384. .mode = 1,
  385. },
  386. { .pset_name = "MODE2",
  387. .freq_list = test_freq_hd,
  388. .dup = FULL_DUPLEX,
  389. .master_iomux = false,
  390. .slave_iomux = false,
  391. .slave_tv_ns = TV_WITH_ESP_SLAVE,
  392. .mode = 2,
  393. },
  394. { .pset_name = "MODE3",
  395. .freq_list = test_freq_hd,
  396. .dup = FULL_DUPLEX,
  397. .master_iomux = false,
  398. .slave_iomux = false,
  399. .slave_tv_ns = TV_WITH_ESP_SLAVE,
  400. .mode = 3,
  401. },
  402. };
  403. TEST_SPI_HD(HD, hd_conf);
  404. /*
  405. * When the previous transaction of master exceeds the length of slave prepared too long, the
  406. * interrupt of slave will be triggered in side that transaction. In the ISR slave has to prepare
  407. * for the next transaction, while the master is still sending the previous one.
  408. *
  409. * This test checks that the previous trans will not influence the data slave prepared for the next transaction.
  410. */
  411. TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]")
  412. {
  413. spi_device_handle_t spi;
  414. spitest_param_set_t *cfg = &hd_conf[0];
  415. int freq = 100*1000; // the frequency should be small enough for the slave to prepare new trans
  416. init_master_hd(&spi, cfg, freq);
  417. //no callback needed
  418. init_slave_hd(cfg->mode, 0, NULL);
  419. //Use GPIO matrix to connect signal of master and slave via same set of pins on one board.
  420. config_single_board_test_pin();
  421. const int send_buf_size = 1024;
  422. WORD_ALIGNED_ATTR uint8_t* slave_send_buf = malloc(send_buf_size * 2);
  423. WORD_ALIGNED_ATTR uint8_t* master_send_buf = malloc(send_buf_size * 2);
  424. WORD_ALIGNED_ATTR uint8_t* slave_recv_buf = malloc(send_buf_size * 2);
  425. WORD_ALIGNED_ATTR uint8_t* master_recv_buf = malloc(send_buf_size * 2);
  426. memset(slave_recv_buf, 0xcc, send_buf_size * 2);
  427. memset(master_recv_buf, 0xcc, send_buf_size * 2);
  428. srand (939);
  429. for (int i = 0; i< send_buf_size * 2; i++) {
  430. master_send_buf[i] = rand();
  431. slave_send_buf[i] = rand();
  432. }
  433. //make the first transaction short, so that the second one will be loaded while the master is
  434. //still doing the first transaction.
  435. int trans_len[] = {5, send_buf_size};
  436. spi_slave_hd_data_t slave_trans[4] = {
  437. //recv, the buffer size should be aligned to 4
  438. {
  439. .data = slave_recv_buf,
  440. .len = (trans_len[0] + 3) & (~3),
  441. },
  442. {
  443. .data = slave_recv_buf + send_buf_size,
  444. .len = (trans_len[1] + 3) & (~3),
  445. },
  446. //send
  447. {
  448. .data = slave_send_buf,
  449. .len = trans_len[0],
  450. },
  451. {
  452. .data = slave_send_buf + send_buf_size,
  453. .len = trans_len[1],
  454. },
  455. };
  456. for (int i = 0; i < 2; i ++) {
  457. TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &slave_trans[i], portMAX_DELAY));
  458. }
  459. for (int i = 2; i < 4; i ++) {
  460. TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &slave_trans[i], portMAX_DELAY));
  461. }
  462. essl_spi_wrdma(spi, master_send_buf, send_buf_size, -1, 0);
  463. essl_spi_wrdma(spi, master_send_buf + send_buf_size, send_buf_size, 5, 0);
  464. essl_spi_rddma(spi, master_recv_buf, send_buf_size, -1, 0);
  465. essl_spi_rddma(spi, master_recv_buf + send_buf_size, send_buf_size, 5, 0);
  466. for (int i = 0; i < 2; i ++) {
  467. spi_slave_hd_data_t *ret_trans;
  468. TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));
  469. TEST_ASSERT(ret_trans == &slave_trans[i]);
  470. TEST_ASSERT_EQUAL(slave_trans[i].len, ret_trans->trans_len);
  471. }
  472. for (int i = 2; i < 4; i ++) {
  473. spi_slave_hd_data_t *ret_trans;
  474. TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
  475. TEST_ASSERT(ret_trans == &slave_trans[i]);
  476. }
  477. spitest_cmp_or_dump(slave_send_buf, master_recv_buf, trans_len[0]);
  478. spitest_cmp_or_dump(slave_send_buf + send_buf_size, master_recv_buf + send_buf_size, trans_len[1]);
  479. spitest_cmp_or_dump(master_send_buf, slave_recv_buf, trans_len[0]);
  480. spitest_cmp_or_dump(master_send_buf + send_buf_size, slave_recv_buf + send_buf_size, trans_len[1]);
  481. free(master_recv_buf);
  482. free(slave_recv_buf);
  483. free(master_send_buf);
  484. free(slave_send_buf);
  485. spi_slave_hd_deinit(TEST_SLAVE_HOST);
  486. master_free_device_bus(spi);
  487. }
  488. #endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2
  489. #endif //#if !DISABLED_FOR_TARGETS(ESP32C3)