sd_card_example_main.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* SD card and FAT filesystem example.
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/unistd.h>
  10. #include <sys/stat.h>
  11. #include "esp_err.h"
  12. #include "esp_log.h"
  13. #include "esp_vfs_fat.h"
  14. #include "driver/sdspi_host.h"
  15. #include "driver/spi_common.h"
  16. #include "sdmmc_cmd.h"
  17. #include "sdkconfig.h"
  18. #ifdef CONFIG_IDF_TARGET_ESP32
  19. #include "driver/sdmmc_host.h"
  20. #endif
  21. static const char *TAG = "example";
  22. #define MOUNT_POINT "/sdcard"
  23. // This example can use SDMMC and SPI peripherals to communicate with SD card.
  24. // By default, SDMMC peripheral is used.
  25. // To enable SPI mode, uncomment the following line:
  26. // #define USE_SPI_MODE
  27. // ESP32-S2 doesn't have an SD Host peripheral, always use SPI:
  28. #ifdef CONFIG_IDF_TARGET_ESP32S2
  29. #ifndef USE_SPI_MODE
  30. #define USE_SPI_MODE
  31. #endif // USE_SPI_MODE
  32. // on ESP32-S2, DMA channel must be the same as host id
  33. #define SPI_DMA_CHAN host.slot
  34. #endif //CONFIG_IDF_TARGET_ESP32S2
  35. // DMA channel to be used by the SPI peripheral
  36. #ifndef SPI_DMA_CHAN
  37. #define SPI_DMA_CHAN 1
  38. #endif //SPI_DMA_CHAN
  39. // When testing SD and SPI modes, keep in mind that once the card has been
  40. // initialized in SPI mode, it can not be reinitialized in SD mode without
  41. // toggling power to the card.
  42. #ifdef USE_SPI_MODE
  43. // Pin mapping when using SPI mode.
  44. // With this mapping, SD card can be used both in SPI and 1-line SD mode.
  45. // Note that a pull-up on CS line is required in SD mode.
  46. #define PIN_NUM_MISO 2
  47. #define PIN_NUM_MOSI 15
  48. #define PIN_NUM_CLK 14
  49. #define PIN_NUM_CS 13
  50. #endif //USE_SPI_MODE
  51. void app_main(void)
  52. {
  53. esp_err_t ret;
  54. // Options for mounting the filesystem.
  55. // If format_if_mount_failed is set to true, SD card will be partitioned and
  56. // formatted in case when mounting fails.
  57. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  58. #ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
  59. .format_if_mount_failed = true,
  60. #else
  61. .format_if_mount_failed = false,
  62. #endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
  63. .max_files = 5,
  64. .allocation_unit_size = 16 * 1024
  65. };
  66. sdmmc_card_t* card;
  67. const char mount_point[] = MOUNT_POINT;
  68. ESP_LOGI(TAG, "Initializing SD card");
  69. // Use settings defined above to initialize SD card and mount FAT filesystem.
  70. // Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
  71. // Please check its source code and implement error recovery when developing
  72. // production applications.
  73. #ifndef USE_SPI_MODE
  74. ESP_LOGI(TAG, "Using SDMMC peripheral");
  75. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  76. // This initializes the slot without card detect (CD) and write protect (WP) signals.
  77. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
  78. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  79. // To use 1-line SD mode, uncomment the following line:
  80. // slot_config.width = 1;
  81. // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
  82. // Internal pull-ups are not sufficient. However, enabling internal pull-ups
  83. // does make a difference some boards, so we do that here.
  84. gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
  85. gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
  86. gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only
  87. gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only
  88. gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
  89. ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
  90. #else
  91. ESP_LOGI(TAG, "Using SPI peripheral");
  92. sdmmc_host_t host = SDSPI_HOST_DEFAULT();
  93. spi_bus_config_t bus_cfg = {
  94. .mosi_io_num = PIN_NUM_MOSI,
  95. .miso_io_num = PIN_NUM_MISO,
  96. .sclk_io_num = PIN_NUM_CLK,
  97. .quadwp_io_num = -1,
  98. .quadhd_io_num = -1,
  99. .max_transfer_sz = 4000,
  100. };
  101. ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CHAN);
  102. if (ret != ESP_OK) {
  103. ESP_LOGE(TAG, "Failed to initialize bus.");
  104. return;
  105. }
  106. // This initializes the slot without card detect (CD) and write protect (WP) signals.
  107. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
  108. sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
  109. slot_config.gpio_cs = PIN_NUM_CS;
  110. slot_config.host_id = host.slot;
  111. ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
  112. #endif //USE_SPI_MODE
  113. if (ret != ESP_OK) {
  114. if (ret == ESP_FAIL) {
  115. ESP_LOGE(TAG, "Failed to mount filesystem. "
  116. "If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
  117. } else {
  118. ESP_LOGE(TAG, "Failed to initialize the card (%s). "
  119. "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
  120. }
  121. return;
  122. }
  123. // Card has been initialized, print its properties
  124. sdmmc_card_print_info(stdout, card);
  125. // Use POSIX and C standard library functions to work with files.
  126. // First create a file.
  127. ESP_LOGI(TAG, "Opening file");
  128. FILE* f = fopen(MOUNT_POINT"/hello.txt", "w");
  129. if (f == NULL) {
  130. ESP_LOGE(TAG, "Failed to open file for writing");
  131. return;
  132. }
  133. fprintf(f, "Hello %s!\n", card->cid.name);
  134. fclose(f);
  135. ESP_LOGI(TAG, "File written");
  136. // Check if destination file exists before renaming
  137. struct stat st;
  138. if (stat(MOUNT_POINT"/foo.txt", &st) == 0) {
  139. // Delete it if it exists
  140. unlink(MOUNT_POINT"/foo.txt");
  141. }
  142. // Rename original file
  143. ESP_LOGI(TAG, "Renaming file");
  144. if (rename(MOUNT_POINT"/hello.txt", MOUNT_POINT"/foo.txt") != 0) {
  145. ESP_LOGE(TAG, "Rename failed");
  146. return;
  147. }
  148. // Open renamed file for reading
  149. ESP_LOGI(TAG, "Reading file");
  150. f = fopen(MOUNT_POINT"/foo.txt", "r");
  151. if (f == NULL) {
  152. ESP_LOGE(TAG, "Failed to open file for reading");
  153. return;
  154. }
  155. char line[64];
  156. fgets(line, sizeof(line), f);
  157. fclose(f);
  158. // strip newline
  159. char* pos = strchr(line, '\n');
  160. if (pos) {
  161. *pos = '\0';
  162. }
  163. ESP_LOGI(TAG, "Read from file: '%s'", line);
  164. // All done, unmount partition and disable SDMMC or SPI peripheral
  165. esp_vfs_fat_sdcard_unmount(mount_point, card);
  166. ESP_LOGI(TAG, "Card unmounted");
  167. #ifdef USE_SPI_MODE
  168. //deinitialize the bus after all devices are removed
  169. spi_bus_free(host.slot);
  170. #endif
  171. }