test_spi_bus_lock.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "sdkconfig.h"
  7. #include "esp_log.h"
  8. #include "driver/spi_master.h"
  9. #include "driver/gpio.h"
  10. #include "esp_flash_spi_init.h"
  11. #include "test/test_common_spi.h"
  12. #include "unity.h"
  13. #if CONFIG_IDF_TARGET_ESP32
  14. // The VSPI pins on UT_T1_ESP_FLASH are connected to a external flash
  15. #define TEST_BUS_PIN_NUM_MISO VSPI_IOMUX_PIN_NUM_MISO
  16. #define TEST_BUS_PIN_NUM_MOSI VSPI_IOMUX_PIN_NUM_MOSI
  17. #define TEST_BUS_PIN_NUM_CLK VSPI_IOMUX_PIN_NUM_CLK
  18. #define TEST_BUS_PIN_NUM_CS VSPI_IOMUX_PIN_NUM_CS
  19. #define TEST_BUS_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP
  20. #define TEST_BUS_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD
  21. #else
  22. #define TEST_BUS_PIN_NUM_MISO SPI2_IOMUX_PIN_NUM_MISO
  23. #define TEST_BUS_PIN_NUM_MOSI SPI2_IOMUX_PIN_NUM_MOSI
  24. #define TEST_BUS_PIN_NUM_CLK SPI2_IOMUX_PIN_NUM_CLK
  25. #define TEST_BUS_PIN_NUM_CS SPI2_IOMUX_PIN_NUM_CS
  26. #define TEST_BUS_PIN_NUM_WP SPI2_IOMUX_PIN_NUM_WP
  27. #define TEST_BUS_PIN_NUM_HD SPI2_IOMUX_PIN_NUM_HD
  28. #endif
  29. // H2 and C2 will not support external flash.
  30. #define TEST_FLASH_FREQ_MHZ 5
  31. typedef struct {
  32. union {
  33. spi_device_handle_t handle;
  34. esp_flash_t* chip;
  35. };
  36. bool finished;
  37. } task_context_t;
  38. #if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32)
  39. const static char TAG[] = "test_spi";
  40. void spi_task1(void* arg)
  41. {
  42. //task1 send 50 polling transactions, acquire the bus and send another 50
  43. int count=0;
  44. spi_transaction_t t = {
  45. .flags = SPI_TRANS_USE_TXDATA,
  46. .tx_data = { 0x80, 0x12, 0x34, 0x56 },
  47. .length = 4*8,
  48. };
  49. spi_device_handle_t handle = ((task_context_t*)arg)->handle;
  50. for( int j = 0; j < 50; j ++ ) {
  51. TEST_ESP_OK(spi_device_polling_transmit( handle, &t ));
  52. ESP_LOGI(TAG, "task1:%d", count++ );
  53. }
  54. TEST_ESP_OK(spi_device_acquire_bus( handle, portMAX_DELAY ));
  55. for( int j = 0; j < 50; j ++ ) {
  56. TEST_ESP_OK(spi_device_polling_transmit( handle, &t ));
  57. ESP_LOGI(TAG, "task1:%d", count++ );
  58. }
  59. spi_device_release_bus(handle);
  60. ESP_LOGI(TAG, "task1 terminates");
  61. ((task_context_t*)arg)->finished = true;
  62. vTaskDelete(NULL);
  63. }
  64. void spi_task2(void* arg)
  65. {
  66. int count=0;
  67. //task2 acquire the bus, send 50 polling transactions and then 50 non-polling
  68. spi_transaction_t t = {
  69. .flags = SPI_TRANS_USE_TXDATA,
  70. .tx_data = { 0x80, 0x12, 0x34, 0x56 },
  71. .length = 4*8,
  72. };
  73. spi_transaction_t *ret_t;
  74. spi_device_handle_t handle = ((task_context_t*)arg)->handle;
  75. TEST_ESP_OK(spi_device_acquire_bus( handle, portMAX_DELAY ));
  76. for (int i = 0; i < 50; i ++) {
  77. TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
  78. ESP_LOGI( TAG, "task2: %d", count++ );
  79. }
  80. for( int j = 0; j < 50; j ++ ) {
  81. TEST_ESP_OK(spi_device_queue_trans(handle, &t, portMAX_DELAY));
  82. }
  83. for( int j = 0; j < 50; j ++ ) {
  84. TEST_ESP_OK(spi_device_get_trans_result(handle, &ret_t, portMAX_DELAY));
  85. assert(ret_t == &t);
  86. ESP_LOGI( TAG, "task2: %d", count++ );
  87. }
  88. spi_device_release_bus(handle);
  89. vTaskDelay(1);
  90. ESP_LOGI(TAG, "task2 terminates");
  91. ((task_context_t*)arg)->finished = true;
  92. vTaskDelete(NULL);
  93. }
  94. void spi_task3(void* arg)
  95. {
  96. //task3 send 30 polling transactions, acquire the bus, send 20 polling transactions and then 50 non-polling
  97. int count=0;
  98. spi_transaction_t t = {
  99. .flags = SPI_TRANS_USE_TXDATA,
  100. .tx_data = { 0x80, 0x12, 0x34, 0x56 },
  101. .length = 4*8,
  102. };
  103. spi_transaction_t *ret_t;
  104. spi_device_handle_t handle = ((task_context_t*)arg)->handle;
  105. for (int i = 0; i < 30; i ++) {
  106. TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
  107. ESP_LOGI( TAG, "task3: %d", count++ );
  108. }
  109. TEST_ESP_OK(spi_device_acquire_bus( handle, portMAX_DELAY ));
  110. for (int i = 0; i < 20; i ++) {
  111. TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
  112. ESP_LOGI( TAG, "task3: %d", count++ );
  113. }
  114. for (int j = 0; j < 50; j++) {
  115. TEST_ESP_OK(spi_device_queue_trans(handle, &t, portMAX_DELAY));
  116. }
  117. for (int j = 0; j < 50; j++) {
  118. TEST_ESP_OK(spi_device_get_trans_result(handle, &ret_t, portMAX_DELAY));
  119. assert(ret_t == &t);
  120. ESP_LOGI(TAG, "task3: %d", count++);
  121. }
  122. spi_device_release_bus(handle);
  123. ESP_LOGI(TAG, "task3 terminates");
  124. ((task_context_t*)arg)->finished = true;
  125. vTaskDelete(NULL);
  126. }
  127. static void write_large_buffer(esp_flash_t *chip, const esp_partition_t *part, const uint8_t *source, size_t length)
  128. {
  129. printf("Erasing chip %p, %d bytes\n", chip, length);
  130. TEST_ESP_OK(esp_flash_erase_region(chip, part->address, (length + SPI_FLASH_SEC_SIZE) & ~(SPI_FLASH_SEC_SIZE - 1)) );
  131. printf("Writing chip %p, %d bytes from source %p\n", chip, length, source);
  132. // note writing to unaligned address
  133. TEST_ESP_OK(esp_flash_write(chip, source, part->address + 1, length) );
  134. printf("Write done.\n");
  135. }
  136. static void read_and_check(esp_flash_t *chip, const esp_partition_t *part, const uint8_t *source, size_t length)
  137. {
  138. printf("Checking chip %p, %d bytes\n", chip, length);
  139. uint8_t *buf = malloc(length);
  140. TEST_ASSERT_NOT_NULL(buf);
  141. TEST_ESP_OK(esp_flash_read(chip, buf, part->address + 1, length) );
  142. TEST_ASSERT_EQUAL_HEX8_ARRAY(source, buf, length);
  143. free(buf);
  144. // check nothing was written at beginning or end
  145. uint8_t ends[8];
  146. TEST_ESP_OK(esp_flash_read(chip, ends, part->address, sizeof(ends)) );
  147. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[0]);
  148. TEST_ASSERT_EQUAL_HEX8(source[0], ends[1]);
  149. TEST_ESP_OK(esp_flash_read(chip, ends, part->address + length, sizeof(ends)) );
  150. TEST_ASSERT_EQUAL_HEX8(source[length - 1], ends[0]);
  151. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[1]);
  152. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[2]);
  153. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[3]);
  154. }
  155. void spi_task4(void* arg)
  156. {
  157. esp_flash_t *chip = ((task_context_t*)arg)->chip;
  158. // buffer in RAM
  159. const int test_len = 16400;
  160. uint8_t *source_buf = heap_caps_malloc(test_len, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  161. TEST_ASSERT_NOT_NULL(source_buf);
  162. srand(676);
  163. for (int i = 0; i < test_len; i++) {
  164. source_buf[i] = rand();
  165. }
  166. ESP_LOGI(TAG, "Testing chip %p...", chip);
  167. const esp_partition_t *part = get_test_data_partition();
  168. TEST_ASSERT(part->size > test_len + 2 + SPI_FLASH_SEC_SIZE);
  169. write_large_buffer(chip, part, source_buf, test_len);
  170. read_and_check(chip, part, source_buf, test_len);
  171. free(source_buf);
  172. ESP_LOGI(TAG, "task4 terminates");
  173. ((task_context_t*)arg)->finished = true;
  174. vTaskDelete(NULL);
  175. }
  176. static void test_bus_lock(bool test_flash)
  177. {
  178. task_context_t context1={};
  179. task_context_t context2={};
  180. task_context_t context3={};
  181. task_context_t context4={};
  182. TaskHandle_t task1, task2, task3, task4;
  183. esp_err_t ret;
  184. spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
  185. buscfg.miso_io_num = TEST_BUS_PIN_NUM_MISO;
  186. buscfg.mosi_io_num = TEST_BUS_PIN_NUM_MOSI;
  187. buscfg.sclk_io_num = TEST_BUS_PIN_NUM_CLK;
  188. spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG();
  189. devcfg.queue_size = 100;
  190. //Initialize the SPI bus and 3 devices
  191. TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
  192. TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context1.handle));
  193. TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context2.handle));
  194. //only have 3 cs pins, leave one for the flash
  195. devcfg.spics_io_num = -1;
  196. TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context3.handle));
  197. esp_flash_spi_device_config_t flash_cfg = {
  198. .host_id = TEST_SPI_HOST,
  199. .cs_id = 2,
  200. .cs_io_num = TEST_BUS_PIN_NUM_CS,
  201. .io_mode = SPI_FLASH_DIO,
  202. .freq_mhz = TEST_FLASH_FREQ_MHZ,
  203. .input_delay_ns = 0,
  204. };
  205. //Clamp the WP and HD pins to VDD to make it work in DIO mode
  206. gpio_set_direction(TEST_BUS_PIN_NUM_HD, GPIO_MODE_OUTPUT);
  207. gpio_set_direction(TEST_BUS_PIN_NUM_WP, GPIO_MODE_OUTPUT);
  208. gpio_set_level(TEST_BUS_PIN_NUM_HD, 1);
  209. gpio_set_level(TEST_BUS_PIN_NUM_WP, 1);
  210. esp_flash_t *chip;
  211. (void) chip;
  212. if (test_flash) {
  213. ret = spi_bus_add_flash_device(&chip, &flash_cfg);
  214. TEST_ESP_OK(ret);
  215. ret = esp_flash_init(chip);
  216. TEST_ESP_OK(ret);
  217. context4.chip = chip;
  218. }
  219. ESP_LOGI(TAG, "Start testing...");
  220. xTaskCreate( spi_task1, "task1", 4096, &context1, 0, &task1 );
  221. xTaskCreate( spi_task2, "task2", 4096, &context2, 0, &task2 );
  222. xTaskCreate( spi_task3, "task3", 4096, &context3, 0, &task3 );
  223. if (test_flash) {
  224. xTaskCreate( spi_task4, "task4", 2048, &context4, 0, &task4 );
  225. } else {
  226. context4.finished = true;
  227. }
  228. for(;;){
  229. vTaskDelay(10);
  230. if (context1.finished && context2.finished && context3.finished && context4.finished) break;
  231. }
  232. TEST_ESP_OK(spi_bus_remove_device(context1.handle));
  233. TEST_ESP_OK(spi_bus_remove_device(context2.handle));
  234. TEST_ESP_OK(spi_bus_remove_device(context3.handle));
  235. if (test_flash) {
  236. TEST_ESP_OK(spi_bus_remove_flash_device(chip));
  237. }
  238. TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST) );
  239. }
  240. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP32S3, ESP32C2)
  241. //no runners
  242. //IDF-5049
  243. TEST_CASE("spi bus lock, with flash","[spi][test_env=UT_T1_ESP_FLASH]")
  244. {
  245. test_bus_lock(true);
  246. }
  247. #endif //!TEMPORARY_DISABLED_FOR_TARGETS(...)
  248. TEST_CASE("spi bus lock","[spi]")
  249. {
  250. test_bus_lock(false);
  251. }
  252. #if !DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP32S3, ESP32C2, ESP32H2)
  253. //disable, SPI1 is not available for GPSPI usage on chips later than ESP32
  254. static IRAM_ATTR esp_err_t test_polling_send(spi_device_handle_t handle)
  255. {
  256. for (int i = 0; i < 10; i++) {
  257. spi_transaction_t trans = {
  258. .length = 16,
  259. .flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA,
  260. };
  261. esp_err_t err = spi_device_polling_transmit(handle, &trans);
  262. if (err != ESP_OK) {
  263. return err;
  264. }
  265. }
  266. return ESP_OK;
  267. }
  268. static IRAM_ATTR NOINLINE_ATTR void test_acquire(spi_device_handle_t handle)
  269. {
  270. esp_err_t err = spi_device_acquire_bus(handle, portMAX_DELAY);
  271. if (err == ESP_OK) {
  272. err = test_polling_send(handle);
  273. spi_device_release_bus(handle);
  274. }
  275. TEST_ESP_OK(err);
  276. }
  277. TEST_CASE("spi master can be used on SPI1", "[spi]")
  278. {
  279. spi_device_interface_config_t dev_cfg = {
  280. .mode = 1,
  281. .clock_speed_hz = 1*1000*1000,
  282. .spics_io_num = -1,
  283. .queue_size = 1,
  284. };
  285. spi_device_handle_t handle;
  286. esp_err_t err;
  287. err = spi_bus_add_device(SPI1_HOST, &dev_cfg, &handle);
  288. TEST_ESP_OK(err);
  289. err = test_polling_send(handle);
  290. TEST_ESP_OK(err);
  291. test_acquire(handle);
  292. err = spi_bus_remove_device(handle);
  293. TEST_ESP_OK(err);
  294. }
  295. #endif //disable, SPI1 is not available for GPSPI usage on chips later than ESP32
  296. //TODO: add a case when a non-polling transaction happened in the bus-acquiring time and then release the bus then queue a new trans
  297. #endif //!(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32)