test_fatfs_sdmmc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <time.h>
  18. #include <sys/time.h>
  19. #include <sys/unistd.h>
  20. #include "unity.h"
  21. #include "esp_log.h"
  22. #include "esp_system.h"
  23. #include "esp_vfs.h"
  24. #include "esp_vfs_fat.h"
  25. #include "freertos/FreeRTOS.h"
  26. #include "freertos/task.h"
  27. #include "driver/sdmmc_defs.h"
  28. #include "sdmmc_cmd.h"
  29. #include "ff.h"
  30. #include "test_fatfs_common.h"
  31. #include "soc/soc_caps.h"
  32. #define SDSPI_MOSI_PIN 15
  33. #define SDSPI_MISO_PIN 2
  34. #define SDSPI_CS_PIN 13
  35. #define SDSPI_CLK_PIN 14
  36. #define SDSPI_HOST_ID HSPI_HOST
  37. #ifdef SOC_SDMMC_HOST_SUPPORTED
  38. #include "driver/sdmmc_host.h"
  39. static void test_setup(void)
  40. {
  41. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  42. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  43. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  44. .format_if_mount_failed = true,
  45. .max_files = 5,
  46. .allocation_unit_size = 16 * 1024
  47. };
  48. TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL));
  49. }
  50. static void test_teardown(void)
  51. {
  52. TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount());
  53. }
  54. static const char* test_filename = "/sdcard/hello.txt";
  55. TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][sd][ignore]")
  56. {
  57. size_t heap_size;
  58. HEAP_SIZE_CAPTURE(heap_size);
  59. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  60. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  61. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  62. .format_if_mount_failed = false,
  63. .max_files = 5
  64. };
  65. for (int i = 0; i < 3; ++i) {
  66. printf("Initializing card, attempt %d\n", i);
  67. esp_err_t err = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL);
  68. printf("err=%d\n", err);
  69. TEST_ESP_ERR(ESP_ERR_TIMEOUT, err);
  70. }
  71. HEAP_SIZE_CHECK(heap_size, 0);
  72. }
  73. TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE]")
  74. {
  75. test_setup();
  76. test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str);
  77. test_teardown();
  78. }
  79. TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]")
  80. {
  81. test_setup();
  82. test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str);
  83. test_fatfs_read_file(test_filename);
  84. test_teardown();
  85. }
  86. TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE]")
  87. {
  88. test_setup();
  89. test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str);
  90. test_fatfs_pread_file(test_filename);
  91. test_teardown();
  92. }
  93. TEST_CASE("(SD) pwrite() works well", "[fatfs][test_env=UT_T1_SDMODE]")
  94. {
  95. test_setup();
  96. test_fatfs_pwrite_file(test_filename);
  97. test_teardown();
  98. }
  99. TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE]")
  100. {
  101. test_setup();
  102. test_fatfs_overwrite_append(test_filename);
  103. test_teardown();
  104. }
  105. TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]")
  106. {
  107. test_setup();
  108. test_fatfs_lseek("/sdcard/seek.txt");
  109. test_teardown();
  110. }
  111. TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE]")
  112. {
  113. test_setup();
  114. test_fatfs_truncate_file("/sdcard/truncate.txt");
  115. test_teardown();
  116. }
  117. TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE]")
  118. {
  119. test_setup();
  120. test_fatfs_stat("/sdcard/stat.txt", "/sdcard");
  121. test_teardown();
  122. }
  123. TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE]")
  124. {
  125. test_setup();
  126. test_fatfs_utime("/sdcard/utime.txt", "/sdcard");
  127. test_teardown();
  128. }
  129. TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]")
  130. {
  131. test_setup();
  132. test_fatfs_unlink("/sdcard/unlink.txt");
  133. test_teardown();
  134. }
  135. TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE]")
  136. {
  137. test_setup();
  138. test_fatfs_link_rename("/sdcard/link");
  139. test_teardown();
  140. }
  141. TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE]")
  142. {
  143. test_setup();
  144. test_fatfs_mkdir_rmdir("/sdcard/dir");
  145. test_teardown();
  146. }
  147. TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE]")
  148. {
  149. test_setup();
  150. test_fatfs_can_opendir("/sdcard");
  151. test_teardown();
  152. }
  153. TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE]")
  154. {
  155. test_setup();
  156. test_fatfs_opendir_readdir_rewinddir("/sdcard/dir");
  157. test_teardown();
  158. }
  159. TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE]")
  160. {
  161. test_setup();
  162. test_fatfs_concurrent("/sdcard/f");
  163. test_teardown();
  164. }
  165. static void sdmmc_speed_test(void *buf, size_t buf_size, size_t file_size, bool write);
  166. TEST_CASE("(SD) write/read speed test", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]")
  167. {
  168. size_t heap_size;
  169. HEAP_SIZE_CAPTURE(heap_size);
  170. const size_t buf_size = 16 * 1024;
  171. uint32_t* buf = (uint32_t*) calloc(1, buf_size);
  172. esp_fill_random(buf, buf_size);
  173. const size_t file_size = 1 * 1024 * 1024;
  174. sdmmc_speed_test(buf, 4 * 1024, file_size, true);
  175. sdmmc_speed_test(buf, 8 * 1024, file_size, true);
  176. sdmmc_speed_test(buf, 16 * 1024, file_size, true);
  177. sdmmc_speed_test(buf, 4 * 1024, file_size, false);
  178. sdmmc_speed_test(buf, 8 * 1024, file_size, false);
  179. sdmmc_speed_test(buf, 16 * 1024, file_size, false);
  180. free(buf);
  181. HEAP_SIZE_CHECK(heap_size, 0);
  182. }
  183. static void sdmmc_speed_test(void *buf, size_t buf_size, size_t file_size, bool write)
  184. {
  185. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  186. host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
  187. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  188. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  189. .format_if_mount_failed = write,
  190. .max_files = 5,
  191. .allocation_unit_size = 64 * 1024
  192. };
  193. TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL));
  194. test_fatfs_rw_speed("/sdcard/4mb.bin", buf, buf_size, file_size, write);
  195. TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount());
  196. }
  197. TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE]")
  198. {
  199. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  200. .format_if_mount_failed = true,
  201. .max_files = 5
  202. };
  203. const char* filename_sd = "/sdcard/sd.txt";
  204. const char* filename_wl = "/spiflash/wl.txt";
  205. const char* str_sd = "this is sd\n";
  206. const char* str_wl = "this is spiflash\n";
  207. /* Erase flash before the firs use */
  208. const esp_partition_t *test_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "flash_test");
  209. esp_partition_erase_range(test_partition, 0, test_partition->size);
  210. printf("Partition erased: addr- 0x%08x, size- 0x%08x\n", test_partition->address, test_partition->size);
  211. /* Mount FATFS in SD can WL at the same time. Create a file on each FS */
  212. wl_handle_t wl_handle = WL_INVALID_HANDLE;
  213. test_setup();
  214. TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &wl_handle));
  215. unlink(filename_sd);
  216. unlink(filename_wl);
  217. test_fatfs_create_file_with_text(filename_sd, str_sd);
  218. test_fatfs_create_file_with_text(filename_wl, str_wl);
  219. TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", wl_handle));
  220. test_teardown();
  221. /* Check that the file "sd.txt" was created on FS in SD, and has the right data */
  222. test_setup();
  223. TEST_ASSERT_NULL(fopen(filename_wl, "r"));
  224. FILE* f = fopen(filename_sd, "r");
  225. TEST_ASSERT_NOT_NULL(f);
  226. char buf[64];
  227. TEST_ASSERT_NOT_NULL(fgets(buf, sizeof(buf) - 1, f));
  228. TEST_ASSERT_EQUAL(0, strcmp(buf, str_sd));
  229. fclose(f);
  230. test_teardown();
  231. /* Check that the file "wl.txt" was created on FS in WL, and has the right data */
  232. TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &wl_handle));
  233. TEST_ASSERT_NULL(fopen(filename_sd, "r"));
  234. f = fopen(filename_wl, "r");
  235. TEST_ASSERT_NOT_NULL(f);
  236. TEST_ASSERT_NOT_NULL(fgets(buf, sizeof(buf) - 1, f));
  237. TEST_ASSERT_EQUAL(0, strcmp(buf, str_wl));
  238. fclose(f);
  239. TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", wl_handle));
  240. }
  241. /*
  242. * In FatFs menuconfig, set CONFIG_FATFS_API_ENCODING to UTF-8 and set the
  243. * Codepage to CP936 (Simplified Chinese) in order to run the following tests.
  244. * Ensure that the text editor is UTF-8 compatible when compiling these tests.
  245. */
  246. #if defined(CONFIG_FATFS_API_ENCODING_UTF_8) && (CONFIG_FATFS_CODEPAGE == 936)
  247. static const char* test_filename_utf_8 = "/sdcard/测试文件.txt";
  248. TEST_CASE("(SD) can read file using UTF-8 encoded strings", "[fatfs][sd][test_env=UT_T1_SDMODE]")
  249. {
  250. test_setup();
  251. test_fatfs_create_file_with_text(test_filename_utf_8, fatfs_test_hello_str_utf);
  252. test_fatfs_read_file_utf_8(test_filename_utf_8);
  253. test_teardown();
  254. }
  255. TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected using UTF-8 encoded strings", "[fatfs][ignore]")
  256. {
  257. test_setup();
  258. test_fatfs_opendir_readdir_rewinddir_utf_8("/sdcard/目录");
  259. test_teardown();
  260. }
  261. #endif // CONFIG_FATFS_API_ENCODING_UTF_8 && CONFIG_FATFS_CODEPAGE == 936
  262. #endif //SDMMC HOST SUPPORTED
  263. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
  264. //no runners
  265. static void sdspi_speed_test(void *buf, size_t buf_size, size_t file_size, bool write);
  266. TEST_CASE("(SDSPI) write/read speed test", "[fatfs][sd][test_env=UT_T1_SPIMODE][timeout=60]")
  267. {
  268. size_t heap_size;
  269. HEAP_SIZE_CAPTURE(heap_size);
  270. const size_t buf_size = 16 * 1024;
  271. uint32_t* buf = (uint32_t*) calloc(1, buf_size);
  272. esp_fill_random(buf, buf_size);
  273. const size_t file_size = 1 * 1024 * 1024;
  274. spi_bus_config_t bus_cfg = {
  275. .mosi_io_num = SDSPI_MOSI_PIN,
  276. .miso_io_num = SDSPI_MISO_PIN,
  277. .sclk_io_num = SDSPI_CLK_PIN,
  278. .quadwp_io_num = -1,
  279. .quadhd_io_num = -1,
  280. .max_transfer_sz = 4000,
  281. };
  282. esp_err_t err = spi_bus_initialize(SDSPI_HOST_ID, &bus_cfg, 1);
  283. TEST_ESP_OK(err);
  284. sdspi_speed_test(buf, 4 * 1024, file_size, true);
  285. sdspi_speed_test(buf, 8 * 1024, file_size, true);
  286. sdspi_speed_test(buf, 16 * 1024, file_size, true);
  287. sdspi_speed_test(buf, 4 * 1024, file_size, false);
  288. sdspi_speed_test(buf, 8 * 1024, file_size, false);
  289. sdspi_speed_test(buf, 16 * 1024, file_size, false);
  290. free(buf);
  291. spi_bus_free(SDSPI_HOST_ID);
  292. HEAP_SIZE_CHECK(heap_size, 0);
  293. }
  294. static void sdspi_speed_test(void *buf, size_t buf_size, size_t file_size, bool write)
  295. {
  296. const char path[] = "/sdcard";
  297. sdmmc_card_t *card;
  298. card = NULL;
  299. sdspi_device_config_t device_cfg = {
  300. .gpio_cs = SDSPI_CS_PIN,
  301. .host_id = SDSPI_HOST_ID,
  302. .gpio_cd = SDSPI_SLOT_NO_CD,
  303. .gpio_wp = SDSPI_SLOT_NO_WP,
  304. .gpio_int = SDSPI_SLOT_NO_INT,
  305. };
  306. sdmmc_host_t host = SDSPI_HOST_DEFAULT();
  307. host.slot = SDSPI_HOST_ID;
  308. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  309. .format_if_mount_failed = write,
  310. .max_files = 5,
  311. .allocation_unit_size = 64 * 1024
  312. };
  313. TEST_ESP_OK(esp_vfs_fat_sdspi_mount(path, &host, &device_cfg, &mount_config, &card));
  314. test_fatfs_rw_speed("/sdcard/4mb.bin", buf, buf_size, file_size, write);
  315. TEST_ESP_OK(esp_vfs_fat_sdcard_unmount(path, card));
  316. }
  317. #endif