main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. /* This example code is in the Public Domain (or CC0 licensed, at your option.)
  7. Unless required by applicable law or agreed to in writing, this
  8. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  9. CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. // This example uses SDMMC or SDSPI peripheral to communicate with SD card.
  12. #include <stdio.h>
  13. #include <stdbool.h>
  14. #include <sys/time.h>
  15. #include "esp_log.h"
  16. #include "esp_check.h"
  17. #include "esp_partition.h"
  18. #include "esp_vfs_fat.h"
  19. #include "esp_spiffs.h"
  20. #include "soc/soc_caps.h"
  21. #if SOC_SDMMC_HOST_SUPPORTED
  22. #include "driver/sdmmc_host.h"
  23. #endif
  24. #include "driver/sdspi_host.h"
  25. #include "driver/sdmmc_defs.h"
  26. #include "sdmmc_cmd.h"
  27. #include "wear_levelling.h"
  28. #include "sdkconfig.h"
  29. #include "tests.h"
  30. static const char *TAG = "example";
  31. static const char *flash_partition_label = "storage";
  32. wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
  33. sdmmc_host_t host_g;
  34. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  35. sdmmc_slot_config_t slot_config_g;
  36. #else // CONFIG_EXAMPLE_USE_SDMMC
  37. sdspi_device_config_t slot_config_g;
  38. #endif // CONFIG_EXAMPLE_USE_SDSPI
  39. #ifdef CONFIG_EXAMPLE_SD_FREQ_PROBING
  40. #define EXAMPLE_SD_FREQ SDMMC_FREQ_PROBING
  41. #elif CONFIG_EXAMPLE_SD_FREQ_DEFAULT
  42. #define EXAMPLE_SD_FREQ SDMMC_FREQ_DEFAULT
  43. #elif CONFIG_EXAMPLE_SD_FREQ_HIGHSPEED
  44. #define EXAMPLE_SD_FREQ SDMMC_FREQ_HIGHSPEED
  45. #elif CONFIG_EXAMPLE_SD_FREQ_CUSTOM
  46. #define EXAMPLE_SD_FREQ CONFIG_EXAMPLE_SD_FREQ_CUSTOM_VAL
  47. #else
  48. #define EXAMPLE_SD_FREQ SDMMC_FREQ_DEFAULT
  49. #endif
  50. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  51. void init_sd_config(sdmmc_host_t *out_host, sdmmc_slot_config_t *out_slot_config, int freq_khz);
  52. #else // CONFIG_EXAMPLE_USE_SDMMC
  53. void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_config, int freq_khz);
  54. #endif // CONFIG_EXAMPLE_USE_SDSPI
  55. void test_spiflash_raw(void);
  56. void test_spiflash_fatfs(void);
  57. void test_spiflash_spiffs(void);
  58. void test_sd_raw(void);
  59. void test_sd_fatfs(void);
  60. void app_main(void)
  61. {
  62. #ifdef CONFIG_EXAMPLE_TEST_SPIFLASH
  63. ESP_LOGI(TAG, "Internal flash test");
  64. /* SPI flash - raw access */
  65. #ifdef CONFIG_EXAMPLE_TEST_SPIFLASH_RAW
  66. test_spiflash_raw();
  67. #endif // CONFIG_EXAMPLE_TEST_SPIFLASH_RAW
  68. /* SPI flash - FATFS */
  69. #ifdef CONFIG_EXAMPLE_TEST_SPIFLASH_FATFS
  70. test_spiflash_fatfs();
  71. #endif // CONFIG_EXAMPLE_TEST_SPIFLASH_FATFS
  72. /* SPI flash - SPIFFS */
  73. #ifdef CONFIG_EXAMPLE_TEST_SPIFLASH_SPIFFS
  74. test_spiflash_spiffs();
  75. #endif // CONFIG_EXAMPLE_TEST_SPIFLASH_SPIFFS
  76. #endif // CONFIG_EXAMPLE_TEST_SPIFLASH
  77. #ifdef CONFIG_EXAMPLE_TEST_SD_CARD
  78. ESP_LOGI(TAG, "SD card test");
  79. ESP_LOGI(TAG, "Initializing SD card");
  80. init_sd_config(&host_g, &slot_config_g, EXAMPLE_SD_FREQ);
  81. /* SD card - raw access */
  82. #ifdef CONFIG_EXAMPLE_TEST_SD_CARD_RAW
  83. test_sd_raw();
  84. #endif // CONFIG_EXAMPLE_TEST_SD_CARD_RAW
  85. /* SD card - FATFS */
  86. #ifdef CONFIG_EXAMPLE_TEST_SD_CARD_FATFS
  87. test_sd_fatfs();
  88. #endif // CONFIG_EXAMPLE_TEST_SD_CARD_FATFS
  89. #endif // CONFIG_EXAMPLE_TEST_SD_CARD
  90. }
  91. void test_spiflash_raw(void)
  92. {
  93. esp_err_t ret = ESP_OK;
  94. ESP_LOGI(TAG, "Mountig WL layer...");
  95. const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
  96. ESP_PARTITION_SUBTYPE_DATA_UNDEFINED, flash_partition_label);
  97. if (data_partition == NULL) {
  98. ESP_LOGE(TAG, "Could not find partition \"%s\"", flash_partition_label);
  99. ESP_ERROR_CHECK(ESP_ERR_NOT_FOUND);
  100. }
  101. ret = wl_mount(data_partition, &s_wl_handle);
  102. if (ret != ESP_OK) {
  103. ESP_LOGE(TAG, "Failed to mount wear levelling layer, ret = %i", ret);
  104. ESP_ERROR_CHECK(ret);
  105. }
  106. ESP_LOGI(TAG, "WL layer mounted");
  107. spiflash_speed_test_raw_run();
  108. ret = wl_unmount(s_wl_handle);
  109. ESP_ERROR_CHECK(ret);
  110. ESP_LOGI(TAG, "WL layer unmounted");
  111. }
  112. void test_spiflash_fatfs(void)
  113. {
  114. esp_err_t ret = ESP_OK;
  115. ESP_LOGI(TAG, "Mounting FATFS partition...");
  116. esp_vfs_fat_sdmmc_mount_config_t mount_config_spiflash = {
  117. .format_if_mount_failed = true,
  118. .max_files = 5,
  119. .allocation_unit_size = 16 * 1024};
  120. ret = esp_vfs_fat_spiflash_mount_rw_wl(FLASH_BASE_PATH, flash_partition_label, &mount_config_spiflash, &s_wl_handle);
  121. if (ret == ESP_OK) {
  122. ESP_LOGI(TAG, "FATFS mounted to %s", FLASH_BASE_PATH);
  123. } else {
  124. ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(ret));
  125. ESP_ERROR_CHECK(ret);
  126. }
  127. spiflash_speed_test_fs_run();
  128. // Unregister FATFS and unmount storage partition
  129. ret = esp_vfs_fat_spiflash_unmount_rw_wl(FLASH_BASE_PATH, s_wl_handle);
  130. ESP_ERROR_CHECK(ret);
  131. ESP_LOGI(TAG, "FATFS partition unmounted");
  132. }
  133. void test_spiflash_spiffs(void)
  134. {
  135. esp_err_t ret = ESP_OK;
  136. ESP_LOGI(TAG, "Mounting SPIFFS partition...");
  137. esp_vfs_spiffs_conf_t conf = {
  138. .base_path = FLASH_BASE_PATH,
  139. .partition_label = flash_partition_label,
  140. .max_files = 5,
  141. .format_if_mount_failed = true};
  142. // Use settings defined above to initialize and mount SPIFFS filesystem.
  143. // Note: esp_vfs_spiffs_register is an all-in-one convenience function.
  144. ret = esp_vfs_spiffs_register(&conf);
  145. if (ret == ESP_OK) {
  146. ESP_LOGI(TAG, "SPIFFS mounted to %s", FLASH_BASE_PATH);
  147. } else {
  148. if (ret == ESP_FAIL) {
  149. ESP_LOGE(TAG, "Failed to mount or format filesystem");
  150. } else if (ret == ESP_ERR_NOT_FOUND) {
  151. ESP_LOGE(TAG, "Failed to find SPIFFS partition");
  152. } else {
  153. ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
  154. }
  155. ESP_ERROR_CHECK(ret);
  156. }
  157. spiflash_speed_test_fs_run();
  158. // Unregister SPIFFS and unmount storage partition
  159. ret = esp_vfs_spiffs_unregister(conf.partition_label);
  160. ESP_ERROR_CHECK(ret);
  161. ESP_LOGI(TAG, "SPIFFS partition unmounted");
  162. }
  163. void test_sd_raw(void)
  164. {
  165. esp_err_t ret = ESP_OK;
  166. sdmmc_card_t *card;
  167. ESP_LOGI(TAG, "Mounting SD card - raw access");
  168. card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
  169. if (card == NULL) {
  170. ESP_LOGE(TAG, "Failed to allocate sdmmc_card_t structure");
  171. ESP_ERROR_CHECK(ESP_ERR_NO_MEM);
  172. }
  173. // Initialize the interface
  174. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  175. ret = sdmmc_host_init();
  176. ESP_ERROR_CHECK(ret);
  177. ret = sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config_g);
  178. ESP_ERROR_CHECK(ret);
  179. #elif CONFIG_EXAMPLE_USE_SDSPI // CONFIG_EXAMPLE_USE_SDMMC
  180. int card_handle = -1;
  181. ret = sdspi_host_init_device((const sdspi_device_config_t *)&slot_config_g, &card_handle);
  182. ESP_ERROR_CHECK(ret);
  183. #endif // CONFIG_EXAMPLE_USE_SDSPI
  184. ret = sdmmc_card_init(&host_g, card);
  185. if (ret != ESP_OK) {
  186. ESP_LOGE(TAG, "Failed to initialize SD card (%s)", esp_err_to_name(ret));
  187. ESP_LOGE(TAG, "If you were using SDMMC and switched to SPI reinsert the SD card or power cycle the board");
  188. free(card);
  189. ESP_ERROR_CHECK(ret);
  190. }
  191. ESP_LOGI(TAG, "SD card mounted - raw access");
  192. sdmmc_card_print_info(stdout, card);
  193. sdcard_speed_test_raw_run(card);
  194. // Unmount SD card
  195. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  196. sdmmc_host_deinit();
  197. #else // CONFIG_EXAMPLE_USE_SDMMC
  198. sdspi_host_deinit();
  199. #endif // CONFIG_EXAMPLE_USE_SDSPI
  200. free(card);
  201. ESP_LOGI(TAG, "SD card unmounted - raw access");
  202. }
  203. void test_sd_fatfs(void)
  204. {
  205. esp_err_t ret = ESP_OK;
  206. sdmmc_card_t *card;
  207. ESP_LOGI(TAG, "Mounting SD card - FATFS");
  208. esp_vfs_fat_sdmmc_mount_config_t mount_config_sdcard = {
  209. .format_if_mount_failed = true,
  210. .max_files = 5,
  211. .allocation_unit_size = 16 * 1024};
  212. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  213. ret = esp_vfs_fat_sdmmc_mount(SD_BASE_PATH, &host_g, &slot_config_g, &mount_config_sdcard, &card);
  214. #else // CONFIG_EXAMPLE_USE_SDMMC
  215. ret = esp_vfs_fat_sdspi_mount(SD_BASE_PATH, &host_g, &slot_config_g, &mount_config_sdcard, &card);
  216. #endif // CONFIG_EXAMPLE_USE_SDSPI
  217. if (ret != ESP_OK) {
  218. ESP_LOGE(TAG, "Failed to initialize the card (%s). "
  219. "Make sure SD card lines have pull-up resistors in place.",
  220. esp_err_to_name(ret));
  221. ESP_ERROR_CHECK(ret);
  222. }
  223. sdmmc_card_print_info(stdout, card);
  224. ESP_LOGI(TAG, "SD card mounted - FATFS");
  225. sdcard_speed_test_fatfs_run();
  226. // Unmount SD card
  227. esp_vfs_fat_sdcard_unmount(SD_BASE_PATH, card);
  228. ESP_LOGI(TAG, "SD card unmounted - FATFS");
  229. }
  230. #ifdef CONFIG_EXAMPLE_TEST_SD_CARD
  231. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  232. void init_sd_config(sdmmc_host_t *out_host, sdmmc_slot_config_t *out_slot_config, int freq_khz) {
  233. #else // CONFIG_EXAMPLE_USE_SDMMC
  234. void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_config, int freq_khz) {
  235. #endif // CONFIG_EXAMPLE_USE_SDSPI
  236. // By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
  237. // For setting a specific frequency, use host.max_freq_khz
  238. // (range 400kHz - 40MHz for SDMMC, 400kHz - 20MHz for SDSPI)
  239. // Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
  240. #ifdef CONFIG_EXAMPLE_USE_SDMMC
  241. ESP_LOGI(TAG, "Using SDMMC peripheral");
  242. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  243. host.max_freq_khz = freq_khz;
  244. // This initializes the slot without card detect (CD) and write protect (WP) signals.
  245. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
  246. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  247. // Set bus width to use:
  248. #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
  249. slot_config.width = 4;
  250. #else
  251. slot_config.width = 1;
  252. #endif
  253. // On chips where the GPIOs used for SD card can be configured, set them in
  254. // the slot_config structure:
  255. #ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  256. slot_config.clk = CONFIG_EXAMPLE_PIN_CLK;
  257. slot_config.cmd = CONFIG_EXAMPLE_PIN_CMD;
  258. slot_config.d0 = CONFIG_EXAMPLE_PIN_D0;
  259. #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
  260. slot_config.d1 = CONFIG_EXAMPLE_PIN_D1;
  261. slot_config.d2 = CONFIG_EXAMPLE_PIN_D2;
  262. slot_config.d3 = CONFIG_EXAMPLE_PIN_D3;
  263. #endif // CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
  264. #endif // CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  265. // Enable internal pullups on enabled pins. The internal pullups
  266. // are insufficient however, please make sure 10k external pullups are
  267. // connected on the bus. This is for debug / example purpose only.
  268. slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
  269. #else // CONFIG_EXAMPLE_USE_SDMMC
  270. ESP_LOGI(TAG, "Using SPI peripheral");
  271. sdmmc_host_t host = SDSPI_HOST_DEFAULT();
  272. host.max_freq_khz = freq_khz;
  273. spi_bus_config_t bus_cfg = {
  274. .mosi_io_num = CONFIG_EXAMPLE_PIN_MOSI,
  275. .miso_io_num = CONFIG_EXAMPLE_PIN_MISO,
  276. .sclk_io_num = CONFIG_EXAMPLE_PIN_CLK,
  277. .quadwp_io_num = -1,
  278. .quadhd_io_num = -1,
  279. .max_transfer_sz = 4000,
  280. };
  281. esp_err_t ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
  282. ESP_ERROR_CHECK(ret);
  283. // This initializes the slot without card detect (CD) and write protect (WP) signals.
  284. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
  285. sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
  286. slot_config.gpio_cs = CONFIG_EXAMPLE_PIN_CS;
  287. slot_config.host_id = host.slot;
  288. #endif // CONFIG_EXAMPLE_USE_SDSPI
  289. *out_host = host;
  290. *out_slot_config = slot_config;
  291. }
  292. #endif // CONFIG_EXAMPLE_TEST_SD_CARD