test_esp_flash.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <freertos/FreeRTOS.h>
  4. #include <freertos/task.h>
  5. #include <freertos/semphr.h>
  6. #include <unity.h>
  7. #include "esp_flash.h"
  8. #include "driver/spi_common_internal.h"
  9. #include "esp_flash_spi_init.h"
  10. #include "memspi_host_driver.h"
  11. #include <esp_attr.h>
  12. #include "esp_log.h"
  13. #include <test_utils.h>
  14. #include "unity.h"
  15. #include "driver/gpio.h"
  16. #include "soc/io_mux_reg.h"
  17. #include "sdkconfig.h"
  18. #include "ccomp_timer.h"
  19. #include "esp_rom_gpio.h"
  20. #include "esp_rom_sys.h"
  21. #include "esp_timer.h"
  22. #define FUNC_SPI 1
  23. static uint8_t sector_buf[4096];
  24. #define MAX_ADDR_24BIT 0x1000000
  25. #define TEST_SPI_SPEED ESP_FLASH_10MHZ
  26. #define TEST_SPI_READ_MODE SPI_FLASH_FASTRD
  27. // #define FORCE_GPIO_MATRIX
  28. #if CONFIG_IDF_TARGET_ESP32
  29. #define EXTRA_SPI1_CLK_IO 17 //the pin which is usually used by the PSRAM clk
  30. #define SPI1_CS_IO 16 //the pin which is usually used by the PSRAM cs
  31. #define HSPI_PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI
  32. #define HSPI_PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO
  33. #define HSPI_PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK
  34. #define HSPI_PIN_NUM_HD HSPI_IOMUX_PIN_NUM_HD
  35. #define HSPI_PIN_NUM_WP HSPI_IOMUX_PIN_NUM_WP
  36. #define HSPI_PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS
  37. #define VSPI_PIN_NUM_MOSI VSPI_IOMUX_PIN_NUM_MOSI
  38. #define VSPI_PIN_NUM_MISO VSPI_IOMUX_PIN_NUM_MISO
  39. #define VSPI_PIN_NUM_CLK VSPI_IOMUX_PIN_NUM_CLK
  40. #define VSPI_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD
  41. #define VSPI_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP
  42. #define VSPI_PIN_NUM_CS VSPI_IOMUX_PIN_NUM_CS
  43. #elif CONFIG_IDF_TARGET_ESP32S2
  44. #define SPI1_CS_IO 26 //the pin which is usually used by the PSRAM cs
  45. #define SPI1_HD_IO 27 //the pin which is usually used by the PSRAM hd
  46. #define SPI1_WP_IO 28 //the pin which is usually used by the PSRAM wp
  47. #define FSPI_PIN_NUM_MOSI 35
  48. #define FSPI_PIN_NUM_MISO 37
  49. #define FSPI_PIN_NUM_CLK 36
  50. #define FSPI_PIN_NUM_HD 33
  51. #define FSPI_PIN_NUM_WP 38
  52. #define FSPI_PIN_NUM_CS 34
  53. // Just use the same pins for HSPI
  54. #define HSPI_PIN_NUM_MOSI FSPI_PIN_NUM_MOSI
  55. #define HSPI_PIN_NUM_MISO FSPI_PIN_NUM_MISO
  56. #define HSPI_PIN_NUM_CLK FSPI_PIN_NUM_CLK
  57. #define HSPI_PIN_NUM_HD FSPI_PIN_NUM_HD
  58. #define HSPI_PIN_NUM_WP FSPI_PIN_NUM_WP
  59. #define HSPI_PIN_NUM_CS FSPI_PIN_NUM_CS
  60. #elif CONFIG_IDF_TARGET_ESP32S3
  61. #define SPI1_CS_IO 26 //the pin which is usually used by the PSRAM cs
  62. #define SPI1_HD_IO 27 //the pin which is usually used by the PSRAM hd
  63. #define SPI1_WP_IO 28 //the pin which is usually used by the PSRAM wp
  64. #define FSPI_PIN_NUM_MOSI 35
  65. #define FSPI_PIN_NUM_MISO 37
  66. #define FSPI_PIN_NUM_CLK 36
  67. #define FSPI_PIN_NUM_HD 33
  68. #define FSPI_PIN_NUM_WP 38
  69. #define FSPI_PIN_NUM_CS 34
  70. // Just use the same pins for HSPI
  71. #define HSPI_PIN_NUM_MOSI FSPI_PIN_NUM_MOSI
  72. #define HSPI_PIN_NUM_MISO FSPI_PIN_NUM_MISO
  73. #define HSPI_PIN_NUM_CLK FSPI_PIN_NUM_CLK
  74. #define HSPI_PIN_NUM_HD FSPI_PIN_NUM_HD
  75. #define HSPI_PIN_NUM_WP FSPI_PIN_NUM_WP
  76. #define HSPI_PIN_NUM_CS FSPI_PIN_NUM_CS
  77. #elif CONFIG_IDF_TARGET_ESP32C3
  78. #define SPI1_CS_IO 26 //the pin which is usually used by the PSRAM cs
  79. #define SPI1_HD_IO 27 //the pin which is usually used by the PSRAM hd
  80. #define SPI1_WP_IO 28 //the pin which is usually used by the PSRAM wp
  81. #define FSPI_PIN_NUM_MOSI 7
  82. #define FSPI_PIN_NUM_MISO 2
  83. #define FSPI_PIN_NUM_CLK 6
  84. #define FSPI_PIN_NUM_HD 4
  85. #define FSPI_PIN_NUM_WP 5
  86. #define FSPI_PIN_NUM_CS 10
  87. // Just use the same pins for HSPI
  88. #define HSPI_PIN_NUM_MOSI FSPI_PIN_NUM_MOSI
  89. #define HSPI_PIN_NUM_MISO FSPI_PIN_NUM_MISO
  90. #define HSPI_PIN_NUM_CLK FSPI_PIN_NUM_CLK
  91. #define HSPI_PIN_NUM_HD FSPI_PIN_NUM_HD
  92. #define HSPI_PIN_NUM_WP FSPI_PIN_NUM_WP
  93. #define HSPI_PIN_NUM_CS FSPI_PIN_NUM_CS
  94. #endif
  95. #define TEST_CONFIG_NUM (sizeof(config_list)/sizeof(flashtest_config_t))
  96. typedef void (*flash_test_func_t)(const esp_partition_t *part);
  97. /* Use FLASH_TEST_CASE for SPI flash tests that only use the main SPI flash chip
  98. */
  99. #define FLASH_TEST_CASE(STR, FUNC_TO_RUN) \
  100. TEST_CASE(STR, "[esp_flash]") {flash_test_func(FUNC_TO_RUN, 1 /* first index reserved for main flash */ );}
  101. #define FLASH_TEST_CASE_IGNORE(STR, FUNC_TO_RUN) \
  102. TEST_CASE(STR, "[esp_flash][ignore]") {flash_test_func(FUNC_TO_RUN, 1 /* first index reserved for main flash */ );}
  103. /* Use FLASH_TEST_CASE_3 for tests which also run on external flash, which sits in the place of PSRAM
  104. (these tests are incompatible with PSRAM)
  105. These tests run for all the flash chip configs shown in config_list, below (internal and external).
  106. */
  107. #if defined(CONFIG_SPIRAM) || TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
  108. #define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
  109. #define FLASH_TEST_CASE_3_IGNORE(STR, FUNCT_TO_RUN)
  110. #else
  111. #define FLASH_TEST_CASE_3(STR, FUNC_TO_RUN) \
  112. TEST_CASE(STR", 3 chips", "[esp_flash_3][test_env=UT_T1_ESP_FLASH]") {flash_test_func(FUNC_TO_RUN, TEST_CONFIG_NUM);}
  113. #define FLASH_TEST_CASE_3_IGNORE(STR, FUNC_TO_RUN) \
  114. TEST_CASE(STR", 3 chips", "[esp_flash_3][test_env=UT_T1_ESP_FLASH][ignore]") {flash_test_func(FUNC_TO_RUN, TEST_CONFIG_NUM);}
  115. #endif
  116. //currently all the configs are the same with esp_flash_spi_device_config_t, no more information required
  117. typedef esp_flash_spi_device_config_t flashtest_config_t;
  118. static const char TAG[] = "test_esp_flash";
  119. #define FLASHTEST_CONFIG_COMMON \
  120. /* 0 always reserved for main flash */ \
  121. { \
  122. /* no need to init */ \
  123. .host_id = -1, \
  124. } \
  125. , \
  126. { \
  127. .io_mode = TEST_SPI_READ_MODE,\
  128. .speed = TEST_SPI_SPEED, \
  129. .host_id = SPI_HOST, \
  130. .cs_id = 1, \
  131. /* the pin which is usually used by the PSRAM */ \
  132. .cs_io_num = SPI1_CS_IO, \
  133. .input_delay_ns = 0, \
  134. }
  135. #if CONFIG_IDF_TARGET_ESP32
  136. flashtest_config_t config_list[] = {
  137. FLASHTEST_CONFIG_COMMON,
  138. /* current runner doesn't have a flash on HSPI */
  139. // {
  140. // .io_mode = TEST_SPI_READ_MODE,
  141. // .speed = TEST_SPI_SPEED,
  142. // .host_id = HSPI_HOST,
  143. // .cs_id = 0,
  144. // // uses GPIO matrix on esp32s2 regardless if FORCE_GPIO_MATRIX
  145. // .cs_io_num = HSPI_PIN_NUM_CS,
  146. // .input_delay_ns = 20,
  147. // },
  148. {
  149. .io_mode = TEST_SPI_READ_MODE,
  150. .speed = TEST_SPI_SPEED,
  151. .host_id = VSPI_HOST,
  152. .cs_id = 0,
  153. .cs_io_num = VSPI_PIN_NUM_CS,
  154. .input_delay_ns = 0,
  155. },
  156. };
  157. #elif CONFIG_IDF_TARGET_ESP32S2
  158. flashtest_config_t config_list[] = {
  159. FLASHTEST_CONFIG_COMMON,
  160. /* No runners for esp32s2 for these config yet */
  161. {
  162. .io_mode = TEST_SPI_READ_MODE,
  163. .speed = TEST_SPI_SPEED,
  164. .host_id = FSPI_HOST,
  165. .cs_id = 0,
  166. .cs_io_num = FSPI_PIN_NUM_CS,
  167. .input_delay_ns = 0,
  168. },
  169. {
  170. .io_mode = TEST_SPI_READ_MODE,
  171. .speed = TEST_SPI_SPEED,
  172. .host_id = HSPI_HOST,
  173. .cs_id = 0,
  174. // uses GPIO matrix on esp32s2 regardless of FORCE_GPIO_MATRIX
  175. .cs_io_num = HSPI_PIN_NUM_CS,
  176. .input_delay_ns = 0,
  177. },
  178. };
  179. #elif CONFIG_IDF_TARGET_ESP32S3
  180. flashtest_config_t config_list[] = {
  181. FLASHTEST_CONFIG_COMMON,
  182. /* No runners for esp32s3 for these config yet */
  183. {
  184. .io_mode = TEST_SPI_READ_MODE,
  185. .speed = TEST_SPI_SPEED,
  186. .host_id = FSPI_HOST,
  187. .cs_id = 0,
  188. .cs_io_num = FSPI_PIN_NUM_CS,
  189. .input_delay_ns = 0,
  190. },
  191. };
  192. #elif CONFIG_IDF_TARGET_ESP32C3
  193. flashtest_config_t config_list[] = {
  194. FLASHTEST_CONFIG_COMMON,
  195. /* No runners for esp32c3 for these config yet */
  196. {
  197. .io_mode = TEST_SPI_READ_MODE,
  198. .speed = TEST_SPI_SPEED,
  199. .host_id = FSPI_HOST,
  200. .cs_id = 0,
  201. .cs_io_num = FSPI_PIN_NUM_CS,
  202. .input_delay_ns = 0,
  203. },
  204. };
  205. #endif
  206. static void get_chip_host(esp_flash_t* chip, spi_host_device_t* out_host_id, int* out_cs_id)
  207. {
  208. spi_host_device_t host_id;
  209. int cs_id;
  210. if (chip == NULL) {
  211. host_id = SPI_HOST;
  212. cs_id = 0;
  213. } else {
  214. spi_flash_hal_context_t* host_data = (spi_flash_hal_context_t*)chip->host;
  215. host_id = spi_flash_ll_hw_get_id(host_data->spi);
  216. cs_id = host_data->cs_num;
  217. }
  218. if (out_host_id) {
  219. *out_host_id = host_id;
  220. }
  221. if (out_cs_id) {
  222. *out_cs_id = cs_id;
  223. }
  224. }
  225. static void setup_bus(spi_host_device_t host_id)
  226. {
  227. if (host_id == SPI_HOST) {
  228. ESP_LOGI(TAG, "setup flash on SPI1 CS1...\n");
  229. //no need to initialize the bus, however the CLK may need one more output if it's on the usual place of PSRAM
  230. #ifdef EXTRA_SPI1_CLK_IO
  231. esp_rom_gpio_connect_out_signal(EXTRA_SPI1_CLK_IO, SPICLK_OUT_IDX, 0, 0);
  232. #endif
  233. #if !DISABLED_FOR_TARGETS(ESP32)
  234. #if !CONFIG_ESPTOOLPY_FLASHMODE_QIO && !CONFIG_ESPTOOLPY_FLASHMODE_QOUT
  235. //Initialize the WP and HD pins, which are not automatically initialized on ESP32-S2.
  236. int wp_pin = spi_periph_signal[host_id].spiwp_iomux_pin;
  237. int hd_pin = spi_periph_signal[host_id].spihd_iomux_pin;
  238. gpio_iomux_in(wp_pin, spi_periph_signal[host_id].spiwp_in);
  239. gpio_iomux_out(wp_pin, spi_periph_signal[host_id].func, false);
  240. gpio_iomux_in(hd_pin, spi_periph_signal[host_id].spihd_in);
  241. gpio_iomux_out(hd_pin, spi_periph_signal[host_id].func, false);
  242. #endif //CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
  243. #endif //!DISABLED_FOR_TARGETS(ESP32)
  244. #if !DISABLED_FOR_TARGETS(ESP32)
  245. } else if (host_id == FSPI_HOST) {
  246. ESP_LOGI(TAG, "setup flash on SPI%d (FSPI) CS0...\n", host_id + 1);
  247. spi_bus_config_t fspi_bus_cfg = {
  248. .mosi_io_num = FSPI_PIN_NUM_MOSI,
  249. .miso_io_num = FSPI_PIN_NUM_MISO,
  250. .sclk_io_num = FSPI_PIN_NUM_CLK,
  251. .quadhd_io_num = FSPI_PIN_NUM_HD,
  252. .quadwp_io_num = FSPI_PIN_NUM_WP,
  253. .max_transfer_sz = 64,
  254. };
  255. #ifdef FORCE_GPIO_MATRIX
  256. fspi_bus_cfg.quadhd_io_num = 5;
  257. #endif
  258. esp_err_t ret = spi_bus_initialize(host_id, &fspi_bus_cfg, 0);
  259. TEST_ESP_OK(ret);
  260. #endif
  261. //currently the SPI bus for main flash chip is initialized through GPIO matrix
  262. } else if (host_id == HSPI_HOST) {
  263. ESP_LOGI(TAG, "setup flash on SPI%d (HSPI) CS0...\n", host_id + 1);
  264. spi_bus_config_t hspi_bus_cfg = {
  265. .mosi_io_num = HSPI_PIN_NUM_MOSI,
  266. .miso_io_num = HSPI_PIN_NUM_MISO,
  267. .sclk_io_num = HSPI_PIN_NUM_CLK,
  268. .quadhd_io_num = HSPI_PIN_NUM_HD,
  269. .quadwp_io_num = HSPI_PIN_NUM_WP,
  270. .max_transfer_sz = 64,
  271. };
  272. #if !DISABLED_FOR_TARGETS(ESP32S2)
  273. #ifdef FORCE_GPIO_MATRIX
  274. hspi_bus_cfg.quadhd_io_num = 23;
  275. #endif
  276. #endif
  277. esp_err_t ret = spi_bus_initialize(host_id, &hspi_bus_cfg, 0);
  278. TEST_ESP_OK(ret);
  279. #if !DISABLED_FOR_TARGETS(ESP32)
  280. // HSPI have no multiline mode, use GPIO to pull those pins up
  281. gpio_set_direction(HSPI_PIN_NUM_HD, GPIO_MODE_OUTPUT);
  282. gpio_set_level(HSPI_PIN_NUM_HD, 1);
  283. gpio_set_direction(HSPI_PIN_NUM_WP, GPIO_MODE_OUTPUT);
  284. gpio_set_level(HSPI_PIN_NUM_WP, 1);
  285. #endif
  286. }
  287. #if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  288. else if (host_id == VSPI_HOST) {
  289. ESP_LOGI(TAG, "setup flash on SPI%d (VSPI) CS0...\n", host_id + 1);
  290. spi_bus_config_t vspi_bus_cfg = {
  291. .mosi_io_num = VSPI_PIN_NUM_MOSI,
  292. .miso_io_num = VSPI_PIN_NUM_MISO,
  293. .sclk_io_num = VSPI_PIN_NUM_CLK,
  294. .quadhd_io_num = VSPI_PIN_NUM_HD,
  295. .quadwp_io_num = VSPI_PIN_NUM_WP,
  296. .max_transfer_sz = 64,
  297. };
  298. #ifdef FORCE_GPIO_MATRIX
  299. vspi_bus_cfg.quadhd_io_num = 23;
  300. #endif
  301. esp_err_t ret = spi_bus_initialize(host_id, &vspi_bus_cfg, 0);
  302. TEST_ESP_OK(ret);
  303. }
  304. #endif // disabled for esp32s2
  305. else {
  306. ESP_LOGE(TAG, "invalid bus");
  307. }
  308. }
  309. static void release_bus(int host_id)
  310. {
  311. //SPI1 bus can't be deinitialized
  312. if (host_id == SPI2_HOST || host_id == SPI3_HOST) {
  313. spi_bus_free(host_id);
  314. }
  315. }
  316. static void setup_new_chip(const flashtest_config_t* test_cfg, esp_flash_t** out_chip)
  317. {
  318. //the bus should be initialized before the flash is attached to the bus
  319. if (test_cfg->host_id == -1) {
  320. *out_chip = NULL;
  321. return;
  322. }
  323. setup_bus(test_cfg->host_id);
  324. esp_flash_spi_device_config_t dev_cfg = {
  325. .host_id = test_cfg->host_id,
  326. .io_mode = test_cfg->io_mode,
  327. .speed = test_cfg->speed,
  328. .cs_id = test_cfg->cs_id,
  329. .cs_io_num = test_cfg->cs_io_num,
  330. .input_delay_ns = test_cfg->input_delay_ns,
  331. };
  332. esp_flash_t* init_chip;
  333. esp_err_t err = spi_bus_add_flash_device(&init_chip, &dev_cfg);
  334. TEST_ESP_OK(err);
  335. err = esp_flash_init(init_chip);
  336. TEST_ESP_OK(err);
  337. *out_chip = init_chip;
  338. }
  339. static void teardown_test_chip(esp_flash_t* chip)
  340. {
  341. spi_host_device_t host_id;
  342. get_chip_host(chip, &host_id, NULL);
  343. //happen to work when chip==NULL
  344. spi_bus_remove_flash_device(chip);
  345. release_bus(host_id);
  346. }
  347. static void flash_test_core(flash_test_func_t func, const flashtest_config_t* config)
  348. {
  349. esp_flash_t* chip;
  350. setup_new_chip(config, &chip);
  351. uint32_t size;
  352. esp_err_t err = esp_flash_get_size(chip, &size);
  353. TEST_ESP_OK(err);
  354. ESP_LOGI(TAG, "Flash size: 0x%08X", size);
  355. const esp_partition_t* test_part = get_test_data_partition();
  356. TEST_ASSERT_NOT_EQUAL(NULL, test_part->flash_chip);
  357. esp_partition_t part = *test_part;
  358. part.flash_chip = chip;
  359. ESP_LOGI(TAG, "Testing chip %p, address 0x%08X...", part.flash_chip, part.address);
  360. (*func)(&part);
  361. // For flash with size over 16MB, add one extra round of test for the 32-bit address area
  362. if (size > MAX_ADDR_24BIT) {
  363. part.address = 0x1030000;
  364. part.size = 0x0010000;
  365. ESP_LOGI(TAG, "Testing chip %p, address 0x%08X...", part.flash_chip, part.address);
  366. (*func)(&part);
  367. }
  368. teardown_test_chip(chip);
  369. }
  370. static void flash_test_func(flash_test_func_t func, int test_num)
  371. {
  372. esp_log_level_set("gpio", ESP_LOG_NONE);
  373. for (int i = 0; i < test_num; i++) {
  374. ESP_LOGI(TAG, "Testing config %d/%d", i+1, test_num);
  375. flash_test_core(func, &config_list[i]);
  376. }
  377. ESP_LOGI(TAG, "Completed %d configs", test_num);
  378. }
  379. /* ---------- Test code start ------------*/
  380. static void test_metadata(const esp_partition_t* part)
  381. {
  382. esp_flash_t* chip = part->flash_chip;
  383. uint32_t id, size;
  384. TEST_ESP_OK(esp_flash_read_id(chip, &id));
  385. TEST_ESP_OK(esp_flash_get_size(chip, &size));
  386. printf("Flash ID %08x detected size %d bytes\n", id, size);
  387. }
  388. FLASH_TEST_CASE("SPI flash metadata functions", test_metadata);
  389. FLASH_TEST_CASE_3("SPI flash metadata functions", test_metadata);
  390. static uint32_t erase_test_region(const esp_partition_t *part, int num_sectors)
  391. {
  392. esp_flash_t* chip = part->flash_chip;
  393. uint32_t offs = part->address;
  394. /* chip should be initialised */
  395. TEST_ASSERT(esp_flash_default_chip != NULL
  396. && esp_flash_chip_driver_initialized(esp_flash_default_chip));
  397. TEST_ASSERT(num_sectors * 4096 <= part->size);
  398. bzero(sector_buf, sizeof(sector_buf));
  399. printf("Erase @ 0x%x...\n", offs);
  400. TEST_ASSERT_EQUAL_HEX32(ESP_OK, esp_flash_erase_region(chip, offs, num_sectors * 4096) );
  401. printf("Verify erased...\n");
  402. for (int i = 0; i < num_sectors; i++) {
  403. TEST_ASSERT_EQUAL_HEX32(ESP_OK, esp_flash_read(chip, sector_buf, offs + i * 4096, sizeof(sector_buf)));
  404. printf("Buffer starts 0x%02x 0x%02x 0x%02x 0x%02x\n", sector_buf[0], sector_buf[1], sector_buf[2], sector_buf[3]);
  405. for (int i = 0; i < sizeof(sector_buf); i++) {
  406. TEST_ASSERT_EQUAL_HEX8(0xFF, sector_buf[i]);
  407. }
  408. }
  409. return offs;
  410. }
  411. void test_simple_read_write(const esp_partition_t* part)
  412. {
  413. esp_flash_t* chip = part->flash_chip;
  414. uint32_t offs = erase_test_region(part, 1);
  415. const int test_seed = 778;
  416. srand(test_seed);
  417. for (int i = 0 ; i < sizeof(sector_buf); i++) {
  418. sector_buf[i] = rand();
  419. }
  420. printf("Write %p...\n", (void *)offs);
  421. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, sector_buf, offs, sizeof(sector_buf)) );
  422. bzero(sector_buf, sizeof(sector_buf));
  423. printf("Read back...\n");
  424. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, sector_buf, offs, sizeof(sector_buf)) );
  425. printf("Buffer starts 0x%02x 0x%02x 0x%02x 0x%02x\n", sector_buf[0], sector_buf[1], sector_buf[2], sector_buf[3]);
  426. srand(test_seed);
  427. for (int i = 0; i < sizeof(sector_buf); i++) {
  428. uint8_t data = rand();
  429. TEST_ASSERT_EQUAL_HEX8(data, sector_buf[i]);
  430. }
  431. }
  432. FLASH_TEST_CASE("SPI flash simple read/write", test_simple_read_write);
  433. FLASH_TEST_CASE_3("SPI flash simple read/write", test_simple_read_write);
  434. void test_unaligned_read_write(const esp_partition_t* part)
  435. {
  436. esp_flash_t* chip = part->flash_chip;
  437. uint32_t offs = erase_test_region(part, 2);
  438. const char *msg = "i am a message";
  439. TEST_ASSERT(strlen(msg) + 1 % 4 != 0);
  440. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, msg, offs + 1, strlen(msg) + 1) );
  441. char buf[strlen(msg) + 1];
  442. memset(buf, 0xEE, sizeof(buf));
  443. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, buf, offs + 1, strlen(msg) + 1) );
  444. TEST_ASSERT_EQUAL_STRING_LEN(msg, buf, strlen(msg));
  445. TEST_ASSERT(memcmp(buf, msg, strlen(msg) + 1) == 0);
  446. }
  447. FLASH_TEST_CASE("SPI flash unaligned read/write", test_unaligned_read_write);
  448. FLASH_TEST_CASE_3("SPI flash unaligned read/write", test_unaligned_read_write);
  449. void test_single_read_write(const esp_partition_t* part)
  450. {
  451. esp_flash_t* chip = part->flash_chip;
  452. uint32_t offs = erase_test_region(part, 2);
  453. const int seed = 699;
  454. srand(seed);
  455. for (unsigned v = 0; v < 512; v++) {
  456. uint32_t data = rand();
  457. TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_flash_write(chip, &data, offs + v, 1) );
  458. }
  459. srand(seed);
  460. for (unsigned v = 0; v < 512; v++) {
  461. uint8_t readback;
  462. uint32_t data = rand();
  463. TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_flash_read(chip, &readback, offs + v, 1) );
  464. TEST_ASSERT_EQUAL_HEX8(data, readback);
  465. }
  466. }
  467. FLASH_TEST_CASE("SPI flash single byte reads/writes", test_single_read_write);
  468. FLASH_TEST_CASE_3("SPI flash single byte reads/writes", test_single_read_write);
  469. /* this test is notable because it generates a lot of unaligned reads/writes,
  470. and also reads/writes across both a sector boundary & many page boundaries.
  471. */
  472. void test_three_byte_read_write(const esp_partition_t* part)
  473. {
  474. esp_flash_t* chip = part->flash_chip;
  475. uint32_t offs = erase_test_region(part, 2);
  476. const int seed = 700;
  477. esp_rom_printf("offs:%X\n", offs);
  478. srand(seed);
  479. for (uint32_t v = 0; v < 86; v++) {
  480. uint32_t data = rand();
  481. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, &data, offs + 3 * v, 3) );
  482. }
  483. srand(seed);
  484. for (uint32_t v = 0; v < 1; v++) {
  485. uint32_t readback;
  486. uint32_t data = rand();
  487. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, &readback, offs + 3 * v, 3) );
  488. TEST_ASSERT_EQUAL_HEX32(data & 0xFFFFFF, readback & 0xFFFFFF);
  489. }
  490. }
  491. FLASH_TEST_CASE("SPI flash three byte reads/writes", test_three_byte_read_write);
  492. FLASH_TEST_CASE_3("SPI flash three byte reads/writes", test_three_byte_read_write);
  493. void test_erase_large_region(const esp_partition_t *part)
  494. {
  495. esp_flash_t* chip = part->flash_chip;
  496. /* Write some noise at the start and the end of the region */
  497. const char *ohai = "OHAI";
  498. uint32_t readback;
  499. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, ohai, part->address, 5));
  500. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, ohai, part->address + part->size - 5, 5));
  501. /* sanity check what we just wrote. since the partition may haven't been erased, we only check the part which is written to 0. */
  502. uint32_t written_data = *((const uint32_t *)ohai);
  503. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, &readback, part->address + part->size - 5, 4));
  504. TEST_ASSERT_EQUAL_HEX32(0, readback & (~written_data));
  505. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, &readback, part->address, 4));
  506. TEST_ASSERT_EQUAL_HEX32(0, readback & (~written_data));
  507. /* Erase whole region */
  508. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_erase_region(chip, part->address, part->size));
  509. /* ensure both areas we wrote are now all-FFs */
  510. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, &readback, part->address, 4));
  511. TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFF, readback);
  512. TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, &readback, part->address + part->size - 5, 4));
  513. TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFF, readback);
  514. }
  515. FLASH_TEST_CASE("SPI flash erase large region", test_erase_large_region);
  516. FLASH_TEST_CASE_3("SPI flash erase large region", test_erase_large_region);
  517. static void test_write_protection(const esp_partition_t* part)
  518. {
  519. esp_flash_t* chip = part->flash_chip;
  520. bool wp = true;
  521. esp_err_t ret = ESP_OK;
  522. ret = esp_flash_get_chip_write_protect(chip, &wp);
  523. TEST_ESP_OK(ret);
  524. for (int i = 0; i < 4; i ++) {
  525. bool wp_write = !wp;
  526. ret = esp_flash_set_chip_write_protect(chip, wp_write);
  527. TEST_ESP_OK(ret);
  528. bool wp_read;
  529. ret = esp_flash_get_chip_write_protect(chip, &wp_read);
  530. TEST_ESP_OK(ret);
  531. TEST_ASSERT(wp_read == wp_write);
  532. wp = wp_read;
  533. }
  534. }
  535. FLASH_TEST_CASE("Test esp_flash can enable/disable write protetion", test_write_protection);
  536. FLASH_TEST_CASE_3("Test esp_flash can enable/disable write protetion", test_write_protection);
  537. static const uint8_t large_const_buffer[16400] = {
  538. 203, // first byte
  539. 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  540. 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
  541. [50 ... 99] = 2,
  542. [1600 ... 2000] = 3,
  543. [8000 ... 9000] = 77,
  544. [15000 ... 16398] = 8,
  545. 43 // last byte
  546. };
  547. static void test_write_large_buffer(const esp_partition_t *part, const uint8_t *source, size_t length);
  548. static void write_large_buffer(const esp_partition_t *part, const uint8_t *source, size_t length);
  549. static void read_and_check(const esp_partition_t *part, const uint8_t *source, size_t length);
  550. // Internal functions for testing, from esp_flash_api.c
  551. esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe);
  552. esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe);
  553. esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
  554. esp_err_t spi_flash_chip_mxic_probe(esp_flash_t *chip, uint32_t flash_id);
  555. static bool is_winbond_chip(esp_flash_t* chip)
  556. {
  557. uint32_t flash_id;
  558. esp_err_t ret = esp_flash_read_chip_id(chip, &flash_id);
  559. TEST_ESP_OK(ret);
  560. if ((flash_id >> 16) == 0xEF) {
  561. return true;
  562. } else {
  563. return false;
  564. }
  565. }
  566. static bool is_mxic_chip(esp_flash_t* chip)
  567. {
  568. uint32_t flash_id;
  569. esp_err_t ret = esp_flash_read_chip_id(chip, &flash_id);
  570. TEST_ESP_OK(ret);
  571. return (spi_flash_chip_mxic_probe(chip, flash_id)==ESP_OK);
  572. }
  573. IRAM_ATTR NOINLINE_ATTR static void test_toggle_qe(const esp_partition_t* part)
  574. {
  575. esp_flash_t* chip = part->flash_chip;
  576. bool qe;
  577. if (chip == NULL) {
  578. chip = esp_flash_default_chip;
  579. }
  580. esp_flash_io_mode_t io_mode_before = chip->read_mode;
  581. esp_err_t ret = esp_flash_get_io_mode(chip, &qe);
  582. TEST_ESP_OK(ret);
  583. bool allow_failure = is_winbond_chip(chip) || is_mxic_chip(chip);
  584. for (int i = 0; i < 4; i ++) {
  585. esp_rom_printf(DRAM_STR("write qe: %d->%d\n"), qe, !qe);
  586. qe = !qe;
  587. chip->read_mode = qe? SPI_FLASH_QOUT: SPI_FLASH_SLOWRD;
  588. ret = esp_flash_set_io_mode(chip, qe);
  589. if (allow_failure && !qe && ret == ESP_ERR_FLASH_NO_RESPONSE) {
  590. //allows clear qe failure for Winbond chips
  591. ret = ESP_OK;
  592. }
  593. TEST_ESP_OK(ret);
  594. bool qe_read;
  595. ret = esp_flash_get_io_mode(chip, &qe_read);
  596. TEST_ESP_OK(ret);
  597. ESP_LOGD(TAG, "qe read: %d", qe_read);
  598. if (!qe && qe_read) {
  599. if (allow_failure) {
  600. ESP_LOGW(TAG, "cannot clear QE bit for known permanent QE (Winbond or MXIC) chips.");
  601. } else {
  602. ESP_LOGE(TAG, "cannot clear QE bit, please make sure force clearing QE option is enabled in `spi_flash_common_set_io_mode`, and this chip is not a permanent QE one.");
  603. }
  604. chip->read_mode = io_mode_before;
  605. return;
  606. }
  607. TEST_ASSERT_EQUAL(qe, qe_read);
  608. }
  609. //restore the io_mode after test
  610. chip->read_mode = io_mode_before;
  611. }
  612. // These tests show whether the QE is permanent or not for the chip tested.
  613. // To test the behaviour of a new SPI flash chip, enable force_check flag in generic driver
  614. // `spi_flash_common_set_io_mode` and then run this test.
  615. FLASH_TEST_CASE_IGNORE("Test esp_flash_write can toggle QE bit", test_toggle_qe);
  616. FLASH_TEST_CASE_3_IGNORE("Test esp_flash_write can toggle QE bit", test_toggle_qe);
  617. void test_permutations_part(const flashtest_config_t* config, esp_partition_t* part, void* source_buf, size_t length)
  618. {
  619. if (config->host_id != -1) {
  620. esp_flash_speed_t speed = ESP_FLASH_SPEED_MIN;
  621. while (speed != ESP_FLASH_SPEED_MAX) {
  622. //test io_mode in the inner loop to test QE set/clear function, since
  623. //the io mode will switch frequently.
  624. esp_flash_io_mode_t io_mode = SPI_FLASH_READ_MODE_MIN;
  625. while (io_mode != SPI_FLASH_READ_MODE_MAX) {
  626. if (io_mode > SPI_FLASH_FASTRD &&
  627. !SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(config->host_id)) {
  628. io_mode++;
  629. continue;
  630. }
  631. esp_flash_t* chip;
  632. flashtest_config_t temp_config = *config;
  633. temp_config.io_mode = io_mode;
  634. temp_config.speed = speed;
  635. setup_new_chip(&temp_config, &chip);
  636. ESP_LOGI(TAG, "test flash io mode: %d, speed: %d", io_mode, speed);
  637. part->flash_chip = chip;
  638. read_and_check(part, source_buf, length);
  639. teardown_test_chip(chip);
  640. io_mode++;
  641. }
  642. speed++;
  643. }
  644. } else {
  645. //test main flash
  646. part->flash_chip = NULL;
  647. read_and_check(part, source_buf, length);
  648. }
  649. }
  650. void test_permutations_chip(const flashtest_config_t* config)
  651. {
  652. esp_log_level_set("gpio", ESP_LOG_NONE);
  653. esp_flash_t* chip;
  654. flashtest_config_t temp_config = *config;
  655. // Use the lowest speed to read configs, data and write data to make sure success
  656. temp_config.io_mode = SPI_FLASH_READ_MODE_MIN;
  657. temp_config.speed = ESP_FLASH_SPEED_MIN;
  658. setup_new_chip(&temp_config, &chip);
  659. //Get size to determine whether to test one extra partition
  660. uint32_t size;
  661. esp_err_t err = esp_flash_get_size(chip, &size);
  662. TEST_ESP_OK(err);
  663. ESP_LOGI(TAG, "Flash size: 0x%08X", size);
  664. bool addr_32bit = (size > MAX_ADDR_24BIT);
  665. // Get test partition, and locate temporary partitions according to the default one
  666. const esp_partition_t* test_part = get_test_data_partition();
  667. const int length = sizeof(large_const_buffer);
  668. TEST_ASSERT(test_part->size > length + 2 + SPI_FLASH_SEC_SIZE);
  669. esp_partition_t part[2] = {};
  670. part[0] = *test_part;
  671. part[0].flash_chip = chip;
  672. // For flash with size over 16MB, add one extra round of test for the 32-bit address area
  673. if (addr_32bit) {
  674. part[1] = *test_part;
  675. part[1].flash_chip = chip;
  676. part[1].address = 0x1030000;
  677. part[1].size = 0x0010000;
  678. } else {
  679. part[1].size = 0;
  680. }
  681. // Prepare test data and write to the specified region
  682. uint8_t *source_buf = malloc(length);
  683. TEST_ASSERT_NOT_NULL(source_buf);
  684. srand(778);
  685. for (int i = 0; i < length; i++) {
  686. source_buf[i] = rand();
  687. }
  688. for (int i = 0; i < 2; i++) {
  689. if (part[i].size == 0) continue;
  690. write_large_buffer(&part[i], source_buf, length);
  691. }
  692. teardown_test_chip(chip);
  693. for (int i = 0; i < 2; i++) {
  694. if (part[i].size == 0) continue;
  695. part[i].flash_chip = (esp_flash_t*)-1;
  696. ESP_LOGI(TAG, "Testing address 0x%08X...", part[i].address);
  697. test_permutations_part(config, &part[i], source_buf, length);
  698. }
  699. free(source_buf);
  700. }
  701. TEST_CASE("SPI flash test reading with all speed/mode permutations", "[esp_flash]")
  702. {
  703. test_permutations_chip(&config_list[0]);
  704. }
  705. #ifndef CONFIG_SPIRAM
  706. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
  707. TEST_CASE("SPI flash test reading with all speed/mode permutations, 3 chips", "[esp_flash_3][test_env=UT_T1_ESP_FLASH]")
  708. {
  709. for (int i = 0; i < TEST_CONFIG_NUM; i++) {
  710. test_permutations_chip(&config_list[i]);
  711. }
  712. }
  713. #endif //TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
  714. #endif
  715. static void test_write_large_const_buffer(const esp_partition_t* part)
  716. {
  717. test_write_large_buffer(part, large_const_buffer, sizeof(large_const_buffer));
  718. }
  719. FLASH_TEST_CASE("Test esp_flash_write large const buffer", test_write_large_const_buffer);
  720. FLASH_TEST_CASE_3("Test esp_flash_write large const buffer", test_write_large_const_buffer);
  721. static void test_write_large_ram_buffer(const esp_partition_t* part)
  722. {
  723. // buffer in RAM
  724. uint8_t *source_buf = malloc(sizeof(large_const_buffer));
  725. TEST_ASSERT_NOT_NULL(source_buf);
  726. memcpy(source_buf, large_const_buffer, sizeof(large_const_buffer));
  727. test_write_large_buffer(part, source_buf, sizeof(large_const_buffer));
  728. free(source_buf);
  729. }
  730. FLASH_TEST_CASE("Test esp_flash_write large RAM buffer", test_write_large_ram_buffer);
  731. FLASH_TEST_CASE_3("Test esp_flash_write large RAM buffer", test_write_large_ram_buffer);
  732. static void write_large_buffer(const esp_partition_t *part, const uint8_t *source, size_t length)
  733. {
  734. esp_flash_t* chip = part->flash_chip;
  735. printf("Writing chip %p %p, %d bytes from source %p\n", chip, (void*)part->address, length, source);
  736. ESP_ERROR_CHECK( esp_flash_erase_region(chip, part->address, (length + SPI_FLASH_SEC_SIZE) & ~(SPI_FLASH_SEC_SIZE - 1)) );
  737. // note writing to unaligned address
  738. ESP_ERROR_CHECK( esp_flash_write(chip, source, part->address + 1, length) );
  739. }
  740. static void read_and_check(const esp_partition_t *part, const uint8_t *source, size_t length)
  741. {
  742. esp_flash_t* chip = part->flash_chip;
  743. printf("Checking chip %p 0x%08X, %d bytes\n", chip, part->address, length);
  744. uint8_t *buf = malloc(length);
  745. TEST_ASSERT_NOT_NULL(buf);
  746. ESP_ERROR_CHECK( esp_flash_read(chip, buf, part->address + 1, length) );
  747. TEST_ASSERT_EQUAL_HEX8_ARRAY(source, buf, length);
  748. free(buf);
  749. // check nothing was written at beginning or end
  750. uint8_t ends[8];
  751. ESP_ERROR_CHECK( esp_flash_read(chip, ends, part->address, sizeof(ends)) );
  752. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[0]);
  753. TEST_ASSERT_EQUAL_HEX8(source[0], ends[1]);
  754. ESP_ERROR_CHECK( esp_flash_read(chip, ends, part->address + length, sizeof(ends)) );
  755. TEST_ASSERT_EQUAL_HEX8(source[length - 1], ends[0]);
  756. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[1]);
  757. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[2]);
  758. TEST_ASSERT_EQUAL_HEX8(0xFF, ends[3]);
  759. }
  760. static void test_write_large_buffer(const esp_partition_t* part, const uint8_t *source, size_t length)
  761. {
  762. TEST_ASSERT(part->size > length + 2 + SPI_FLASH_SEC_SIZE);
  763. write_large_buffer(part, source, length);
  764. read_and_check(part, source, length);
  765. }
  766. #if !CONFIG_SPIRAM && !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
  767. /* No runners on C3, TODO ESP32-C3 IDF-2399 */
  768. typedef struct {
  769. uint32_t us_start;
  770. size_t len;
  771. const char* name;
  772. } time_meas_ctx_t;
  773. static void time_measure_start(time_meas_ctx_t* ctx)
  774. {
  775. ctx->us_start = esp_timer_get_time();
  776. ccomp_timer_start();
  777. }
  778. static uint32_t time_measure_end(time_meas_ctx_t* ctx)
  779. {
  780. uint32_t c_time_us = ccomp_timer_stop();
  781. uint32_t time_us = esp_timer_get_time() - ctx->us_start;
  782. ESP_LOGI(TAG, "%s: compensated: %.2lf kB/s, typical: %.2lf kB/s", ctx->name, ctx->len / (c_time_us / 1000.), ctx->len / (time_us/1000.));
  783. return ctx->len * 1000 / (c_time_us / 1000);
  784. }
  785. #define TEST_TIMES 20
  786. #define TEST_SECTORS 4
  787. static uint32_t measure_erase(const esp_partition_t* part)
  788. {
  789. const int total_len = SPI_FLASH_SEC_SIZE * TEST_SECTORS;
  790. time_meas_ctx_t time_ctx = {.name = "erase", .len = total_len};
  791. time_measure_start(&time_ctx);
  792. esp_err_t err = esp_flash_erase_region(part->flash_chip, part->address, total_len);
  793. TEST_ESP_OK(err);
  794. return time_measure_end(&time_ctx);
  795. }
  796. // should called after measure_erase
  797. static uint32_t measure_write(const char* name, const esp_partition_t* part, const uint8_t* data_to_write, int seg_len)
  798. {
  799. const int total_len = SPI_FLASH_SEC_SIZE;
  800. time_meas_ctx_t time_ctx = {.name = name, .len = total_len * TEST_TIMES};
  801. time_measure_start(&time_ctx);
  802. for (int i = 0; i < TEST_TIMES; i ++) {
  803. // Erase one time, but write 100 times the same data
  804. size_t len = total_len;
  805. int offset = 0;
  806. while (len) {
  807. int len_write = MIN(seg_len, len);
  808. esp_err_t err = esp_flash_write(part->flash_chip, data_to_write + offset, part->address + offset, len_write);
  809. TEST_ESP_OK(err);
  810. offset += len_write;
  811. len -= len_write;
  812. }
  813. }
  814. return time_measure_end(&time_ctx);
  815. }
  816. static uint32_t measure_read(const char* name, const esp_partition_t* part, uint8_t* data_read, int seg_len)
  817. {
  818. const int total_len = SPI_FLASH_SEC_SIZE;
  819. time_meas_ctx_t time_ctx = {.name = name, .len = total_len * TEST_TIMES};
  820. time_measure_start(&time_ctx);
  821. for (int i = 0; i < TEST_TIMES; i ++) {
  822. size_t len = total_len;
  823. int offset = 0;
  824. while (len) {
  825. int len_read = MIN(seg_len, len);
  826. esp_err_t err = esp_flash_read(part->flash_chip, data_read + offset, part->address + offset, len_read);
  827. TEST_ESP_OK(err);
  828. offset += len_read;
  829. len -= len_read;
  830. }
  831. }
  832. return time_measure_end(&time_ctx);
  833. }
  834. #define MEAS_WRITE(n) (measure_write("write in "#n"-byte chunks", part, data_to_write, n))
  835. #define MEAS_READ(n) (measure_read("read in "#n"-byte chunks", part, data_read, n))
  836. static void test_flash_read_write_performance(const esp_partition_t *part)
  837. {
  838. esp_flash_t* chip = part->flash_chip;
  839. const int total_len = SPI_FLASH_SEC_SIZE;
  840. uint8_t *data_to_write = heap_caps_malloc(total_len, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  841. uint8_t *data_read = heap_caps_malloc(total_len, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  842. srand(777);
  843. for (int i = 0; i < total_len; i++) {
  844. data_to_write[i] = rand();
  845. }
  846. uint32_t erase_1 = measure_erase(part);
  847. uint32_t speed_WR_4B = MEAS_WRITE(4);
  848. uint32_t speed_RD_4B = MEAS_READ(4);
  849. uint32_t erase_2 = measure_erase(part);
  850. uint32_t speed_WR_2KB = MEAS_WRITE(2048);
  851. uint32_t speed_RD_2KB = MEAS_READ(2048);
  852. TEST_ASSERT_EQUAL_HEX8_ARRAY(data_to_write, data_read, total_len);
  853. #if !CONFIG_SPIRAM && !CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
  854. # define CHECK_DATA(bus, suffix) TEST_PERFORMANCE_CCOMP_GREATER_THAN(FLASH_SPEED_BYTE_PER_SEC_##bus##suffix, "%d", speed_##suffix)
  855. # define CHECK_ERASE(bus, var) TEST_PERFORMANCE_CCOMP_GREATER_THAN(FLASH_SPEED_BYTE_PER_SEC_##bus##ERASE, "%d", var)
  856. #else
  857. # define CHECK_DATA(bus, suffix) ((void)speed_##suffix)
  858. # define CHECK_ERASE(bus, var) ((void)var)
  859. #endif
  860. // Erase time may vary a lot, can increase threshold if this fails with a reasonable speed
  861. #define CHECK_PERFORMANCE(bus) do {\
  862. CHECK_DATA(bus, WR_4B); \
  863. CHECK_DATA(bus, RD_4B); \
  864. CHECK_DATA(bus, WR_2KB); \
  865. CHECK_DATA(bus, RD_2KB); \
  866. CHECK_ERASE(bus, erase_1); \
  867. CHECK_ERASE(bus, erase_2); \
  868. } while (0)
  869. spi_host_device_t host_id;
  870. int cs_id;
  871. get_chip_host(chip, &host_id, &cs_id);
  872. if (host_id != SPI_HOST) {
  873. // Chips on other SPI buses
  874. CHECK_PERFORMANCE(EXT_);
  875. } else if (cs_id == 0) {
  876. // Main flash
  877. CHECK_PERFORMANCE();
  878. } else {
  879. // Other cs pins on SPI1
  880. CHECK_PERFORMANCE(SPI1_);
  881. }
  882. free(data_to_write);
  883. free(data_read);
  884. }
  885. TEST_CASE("Test esp_flash read/write performance", "[esp_flash][test_env=UT_T1_ESP_FLASH]") {flash_test_func(test_flash_read_write_performance, 1);}
  886. #endif // !CONFIG_SPIRAM
  887. FLASH_TEST_CASE_3("Test esp_flash read/write performance"", 3 chips", test_flash_read_write_performance);
  888. #ifdef CONFIG_SPIRAM_USE_MALLOC
  889. /* Utility: Read into a small internal RAM buffer using esp_flash_read() and compare what
  890. we read with 'buffer' */
  891. static void s_test_compare_flash_contents_small_reads(esp_flash_t *chip, const uint8_t *buffer, size_t offs, size_t len)
  892. {
  893. const size_t INTERNAL_BUF_SZ = 1024; // Should fit in internal RAM
  894. uint8_t *ibuf = heap_caps_malloc(INTERNAL_BUF_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
  895. TEST_ASSERT_NOT_NULL(ibuf);
  896. for (int i = 0; i < len; i += INTERNAL_BUF_SZ) {
  897. size_t to_read = MIN(INTERNAL_BUF_SZ, len - i);
  898. ESP_ERROR_CHECK( esp_flash_read(chip, ibuf, offs + i, to_read) );
  899. TEST_ASSERT_EQUAL_HEX8_ARRAY(buffer + i, ibuf, to_read);
  900. }
  901. free(ibuf);
  902. }
  903. static void test_flash_read_large_psram_buffer(const esp_partition_t *part)
  904. {
  905. esp_flash_t* chip = part->flash_chip;
  906. const size_t BUF_SZ = 256 * 1024; // Too large for internal RAM
  907. const size_t TEST_OFFS = 0x1000; // Can be any offset, really
  908. uint8_t *buf = heap_caps_malloc(BUF_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM);
  909. TEST_ASSERT_NOT_NULL(buf);
  910. ESP_ERROR_CHECK( esp_flash_read(chip, buf, TEST_OFFS, BUF_SZ) );
  911. // Read back the same into smaller internal memory buffer and check it all matches
  912. s_test_compare_flash_contents_small_reads(chip, buf, TEST_OFFS, BUF_SZ);
  913. free(buf);
  914. }
  915. FLASH_TEST_CASE("esp_flash_read large PSRAM buffer", test_flash_read_large_psram_buffer);
  916. /* similar to above test, but perform it under memory pressure */
  917. static void test_flash_read_large_psram_buffer_low_internal_mem(const esp_partition_t *part)
  918. {
  919. esp_flash_t* chip = part->flash_chip;
  920. const size_t BUF_SZ = 256 * 1024; // Too large for internal RAM
  921. const size_t REMAINING_INTERNAL = 1024; // Exhaust internal memory until maximum free block is less than this
  922. const size_t TEST_OFFS = 0x8000;
  923. /* Exhaust the available free internal memory */
  924. test_utils_exhaust_memory_rec erec = test_utils_exhaust_memory(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT, REMAINING_INTERNAL);
  925. uint8_t *buf = heap_caps_malloc(BUF_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM);
  926. TEST_ASSERT_NOT_NULL(buf);
  927. /* Calling esp_flash_read() here will need to allocate a small internal buffer,
  928. so check it works. */
  929. ESP_ERROR_CHECK( esp_flash_read(chip, buf, TEST_OFFS, BUF_SZ) );
  930. test_utils_free_exhausted_memory(erec);
  931. // Read back the same into smaller internal memory buffer and check it all matches
  932. s_test_compare_flash_contents_small_reads(chip, buf, TEST_OFFS, BUF_SZ);
  933. free(buf);
  934. }
  935. FLASH_TEST_CASE("esp_flash_read large PSRAM buffer low memory", test_flash_read_large_psram_buffer_low_internal_mem);
  936. #endif