test_spi_bus_lock.c 11 KB

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