test_spi_bus_lock.c 11 KB

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