25 |
25 |
26 SDCARD_State *sdcard_state; ///< SD card status |
26 SDCARD_State *sdcard_state; ///< SD card status |
27 JSON_log *json_log; ///< JSON log array |
27 JSON_log *json_log; ///< JSON log array |
28 EventGroupHandle_t xEventGroupSDcard; ///< SD card events. |
28 EventGroupHandle_t xEventGroupSDcard; ///< SD card events. |
29 |
29 |
|
30 int card_handle = -1; |
30 static const char *TAG = "task_sdcard"; |
31 static const char *TAG = "task_sdcard"; |
31 static sdmmc_card_t* s_card = NULL; |
32 static sdmmc_card_t* card = NULL; |
32 static uint8_t s_pdrv = 0; |
33 static uint8_t s_pdrv = 0; |
33 static char * s_base_path = NULL; |
34 //static char * s_base_path = NULL; |
34 static uint8_t pdrv = FF_DRV_NOT_USED; |
35 static uint8_t pdrv = FF_DRV_NOT_USED; |
35 |
36 |
36 |
37 |
37 #define SDCARD_HOST_SLOT VSPI_HOST ///< HSPI_HOST is used by the TFT |
38 #define SDCARD_HOST_SLOT VSPI_HOST ///< HSPI_HOST is used by the TFT |
38 #define SDCARD_PIN_NUM_MISO 2 ///< MISO pin |
39 #define SDCARD_PIN_NUM_MISO 2 ///< MISO pin |
212 } |
213 } |
213 } |
214 } |
214 |
215 |
215 |
216 |
216 |
217 |
|
218 static esp_err_t mount_prepare_mem(const char *base_path, BYTE *out_pdrv, char **out_dup_path, sdmmc_card_t** out_card) |
|
219 { |
|
220 esp_err_t err = ESP_OK; |
|
221 char* dup_path = NULL; |
|
222 |
|
223 // connect SDMMC driver to FATFS |
|
224 BYTE pdrv = FF_DRV_NOT_USED; |
|
225 if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == FF_DRV_NOT_USED) { |
|
226 ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); |
|
227 return ESP_ERR_NO_MEM; |
|
228 |
|
229 } |
|
230 |
|
231 // not using ff_memalloc here, as allocation in internal RAM is preferred |
|
232 card = (sdmmc_card_t*)malloc(sizeof(sdmmc_card_t)); |
|
233 if (card == NULL) { |
|
234 ESP_LOGD(TAG, "could not locate new sdmmc_card_t"); |
|
235 err = ESP_ERR_NO_MEM; |
|
236 goto cleanup; |
|
237 } |
|
238 |
|
239 dup_path = strdup(base_path); |
|
240 if (!dup_path){ |
|
241 ESP_LOGD(TAG, "could not copy base_path"); |
|
242 err = ESP_ERR_NO_MEM; |
|
243 goto cleanup; |
|
244 } |
|
245 |
|
246 *out_card = card; |
|
247 *out_pdrv = pdrv; |
|
248 *out_dup_path = dup_path; |
|
249 return ESP_OK; |
|
250 cleanup: |
|
251 free(card); |
|
252 card = NULL; |
|
253 free(dup_path); |
|
254 return err; |
|
255 } |
|
256 |
|
257 |
|
258 |
217 static esp_err_t my_init_sdspi_host(int slot, const void *slot_config, int *out_slot) |
259 static esp_err_t my_init_sdspi_host(int slot, const void *slot_config, int *out_slot) |
218 { |
260 { |
219 esp_err_t err = sdspi_host_init_device((const sdspi_device_config_t*)slot_config, out_slot); |
261 esp_err_t err = sdspi_host_init_device((const sdspi_device_config_t*)slot_config, out_slot); |
220 if (err != ESP_OK) { |
262 if (err != ESP_OK) { |
221 ESP_LOGE(TAG, "Failed to attach sdspi device onto an SPI bus (rc=0x%x), please initialize the \ |
263 ESP_LOGE(TAG, "Failed to attach sdspi device onto an SPI bus (rc=0x%x), please initialize the \ |
225 } |
267 } |
226 |
268 |
227 |
269 |
228 |
270 |
229 /** |
271 /** |
230 * @brief This is a local modified version of the esp_vfs_fat_sdmmc_mount() function in |
272 * @brief This is a local modified version of the esp_vfs_fat_sdspi_mount() function in |
231 * the FreeRTOS components library. It is here so we can better handle errors |
273 * the FreeRTOS components library. It is here so we can better handle errors |
232 * for our application. |
274 * for our application. |
233 * @param base_path The mount path |
275 * @param base_path The mount path |
234 * @param host_config SPI host configuration |
276 * @param host_config SPI host configuration |
235 * @param slot_config Slot configuration |
277 * @param slot_config Slot configuration |
236 * @return Error condition. |
278 * @return Error condition. |
237 */ |
279 */ |
238 esp_err_t my_vfs_fat_sdmmc_init(const char* base_path, const sdmmc_host_t* host_config, const void* slot_config, int *card_handle) |
280 esp_err_t my_vfs_fat_sdspi_init(const char* base_path, const sdmmc_host_t* host_config, const void* slot_config) |
239 { |
281 { |
240 if (s_card != NULL) { |
282 esp_err_t err; |
|
283 char* dup_path = NULL; |
|
284 |
|
285 if (card != NULL) { |
|
286 ESP_LOGE(TAG, "card not NULL"); |
241 return ESP_ERR_INVALID_STATE; |
287 return ESP_ERR_INVALID_STATE; |
242 } |
288 } |
243 |
289 |
244 // connect SDMMC driver to FATFS |
290 err = mount_prepare_mem(base_path, &pdrv, &dup_path, &card); |
245 pdrv = FF_DRV_NOT_USED; |
291 if (err != ESP_OK) { |
246 if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == FF_DRV_NOT_USED) { |
292 ESP_LOGE(TAG, "mount_prepare failed"); |
247 ESP_LOGE(TAG, "the maximum count of volumes is already mounted"); |
293 return err; |
248 return ESP_ERR_NO_MEM; |
294 } |
249 } |
295 |
250 |
296 //the init() function is usually empty, doesn't require any deinit to revert it |
251 s_base_path = strdup(base_path); |
|
252 if (!s_base_path) { |
|
253 ESP_LOGE(TAG, "could not copy base_path"); |
|
254 return ESP_ERR_NO_MEM; |
|
255 } |
|
256 esp_err_t err = ESP_OK; |
|
257 s_card = malloc(sizeof(sdmmc_card_t)); |
|
258 if (s_card == NULL) { |
|
259 err = ESP_ERR_NO_MEM; |
|
260 goto fail; |
|
261 } |
|
262 |
|
263 err = (*host_config->init)(); |
297 err = (*host_config->init)(); |
264 if (err != ESP_OK) { |
298 if (err != ESP_OK) { |
265 ESP_LOGE(TAG, "host init returned rc=0x%x", err); |
299 ESP_LOGE(TAG, "host init returned rc=0x%x", err); |
266 goto fail; |
300 goto fail; |
267 } |
301 } |
268 |
302 |
269 // configure SD host |
303 // configure SD host |
270 err = my_init_sdspi_host(host_config->slot, slot_config, &card_handle); |
304 err = my_init_sdspi_host(host_config->slot, slot_config, &card_handle); |
271 if (err != ESP_OK) { |
305 if (err != ESP_OK) { |
272 ESP_LOGE(TAG, "init_sdspi_host() rc=0x%x", err); |
306 ESP_LOGE(TAG, "my_init_sdspi_host() rc=0x%x", err); |
273 goto fail; |
307 goto fail; |
274 } |
308 } |
275 return ESP_OK; |
309 return ESP_OK; |
276 |
310 |
277 fail: |
311 fail: |
278 host_config->deinit(); |
312 host_config->deinit(); |
279 free(s_card); |
313 free(card); |
280 s_card = NULL; |
314 card = NULL; |
281 return err; |
315 return err; |
282 } |
316 } |
283 |
317 |
284 |
318 |
285 |
319 |
290 * @param slot_config Slot configuration |
324 * @param slot_config Slot configuration |
291 * @param mount_config Mount configuration |
325 * @param mount_config Mount configuration |
292 * @param[out] out_card Card information |
326 * @param[out] out_card Card information |
293 * @return Error condition |
327 * @return Error condition |
294 */ |
328 */ |
295 esp_err_t my_esp_vfs_fat_sdmmc_mount(const char* base_path, |
329 esp_err_t my_esp_vfs_fat_sdspi_mount(const char* base_path, |
296 const sdmmc_host_t* host_config, |
330 const sdmmc_host_t* host_config_input, |
297 const void* slot_config, |
331 const sdspi_device_config_t* slot_config, |
298 const esp_vfs_fat_mount_config_t* mount_config, |
332 const esp_vfs_fat_mount_config_t* mount_config, |
299 sdmmc_card_t** out_card, |
333 sdmmc_card_t** out_card) |
300 int card_handle) |
334 { |
301 { |
335 const sdmmc_host_t* host_config = host_config_input; |
302 FATFS* fs = NULL; |
336 FATFS* fs = NULL; |
303 esp_err_t err = ESP_OK; |
337 esp_err_t err = ESP_OK; |
304 |
338 |
305 if (s_card == NULL) { |
339 if (card == NULL) { |
|
340 ESP_LOGE(TAG, "card not NULL"); |
306 return ESP_ERR_INVALID_STATE; |
341 return ESP_ERR_INVALID_STATE; |
307 } |
342 } |
308 |
343 |
|
344 /* |
|
345 * The `slot` argument inside host_config should be replaced by the SD SPI handled returned |
|
346 * above. But the input pointer is const, so create a new variable. |
|
347 */ |
|
348 sdmmc_host_t new_config; |
|
349 if (card_handle != host_config->slot) { |
|
350 new_config = *host_config_input; |
|
351 host_config = &new_config; |
|
352 new_config.slot = card_handle; |
|
353 } |
|
354 |
309 // probe and initialize card |
355 // probe and initialize card |
310 err = sdmmc_card_init(host_config, s_card); |
356 err = sdmmc_card_init(host_config, card); |
311 if (err != ESP_OK) { |
357 if (err != ESP_OK) { |
312 if (err != ESP_ERR_INVALID_RESPONSE) { // No card present, do not log |
358 if (err != ESP_ERR_INVALID_RESPONSE) { // No card present, do not log |
313 ESP_LOGI(TAG, "sdmmc_card_init failed 0x(%x)", err); |
359 ESP_LOGI(TAG, "sdmmc_card_init failed 0x(%x)", err); |
314 } |
360 } |
315 goto fail; |
361 goto fail; |
316 } |
362 } |
|
363 |
317 if (out_card != NULL) { |
364 if (out_card != NULL) { |
318 *out_card = s_card; |
365 *out_card = card; |
319 } |
366 } |
320 |
367 |
321 ff_diskio_register_sdmmc(pdrv, s_card); |
368 /* |
|
369 * mount to vfs fat |
|
370 */ |
|
371 ff_diskio_register_sdmmc(pdrv, card); |
322 s_pdrv = pdrv; |
372 s_pdrv = pdrv; |
323 ESP_LOGD(TAG, "using pdrv=%i", pdrv); |
373 ESP_LOGD(TAG, "using pdrv=%i", pdrv); |
324 char drv[3] = {(char)('0' + pdrv), ':', 0}; |
374 char drv[3] = {(char)('0' + pdrv), ':', 0}; |
325 |
375 |
326 // connect FATFS to VFS |
376 // connect FATFS to VFS |
354 |
404 |
355 /** |
405 /** |
356 * @brief Unmount a mounted SD card, |
406 * @brief Unmount a mounted SD card, |
357 * @return Error condition |
407 * @return Error condition |
358 */ |
408 */ |
359 esp_err_t my_esp_vfs_fat_sdmmc_unmount(void) |
409 esp_err_t my_esp_vfs_fat_sdspi_unmount(void) |
360 { |
410 { |
361 if (s_card == NULL) { |
411 if (card == NULL) { |
362 return ESP_ERR_INVALID_STATE; |
412 return ESP_ERR_INVALID_STATE; |
363 } |
413 } |
364 // unmount |
414 // unmount |
365 char drv[3] = {(char)('0' + s_pdrv), ':', 0}; |
415 char drv[3] = {(char)('0' + s_pdrv), ':', 0}; |
366 f_mount(0, drv, 0); |
416 f_mount(0, drv, 0); |
440 slot_config.host_id = host.slot; |
489 slot_config.host_id = host.slot; |
441 |
490 |
442 /* |
491 /* |
443 * No errors from the sdspi_transaction driver. |
492 * No errors from the sdspi_transaction driver. |
444 */ |
493 */ |
445 esp_log_level_set("sdspi_transaction", ESP_LOG_NONE); |
494 // esp_log_level_set("sdspi_transaction", ESP_LOG_NONE); |
446 |
495 |
447 /* |
496 /* |
448 * Options for mounting the filesystem. |
497 * Options for mounting the filesystem. |
449 * If format_if_mount_failed is set to true, SD card will be partitioned and |
498 * If format_if_mount_failed is set to true, SD card will be partitioned and |
450 * formatted in case when mounting fails. |
499 * formatted in case when mounting fails. |
453 .format_if_mount_failed = false, |
502 .format_if_mount_failed = false, |
454 .max_files = 5, |
503 .max_files = 5, |
455 .allocation_unit_size = 16 * 1024 |
504 .allocation_unit_size = 16 * 1024 |
456 }; |
505 }; |
457 |
506 |
458 ret = my_vfs_fat_sdmmc_init("/sdcard", &host, &slot_config, &card_handle); |
507 ret = my_vfs_fat_sdspi_init("/sdcard", &host, &slot_config); |
459 if (ret == ESP_OK) { |
508 if (ret == ESP_OK) { |
460 ESP_LOGI(TAG, "SPI card interface ready"); |
509 ESP_LOGI(TAG, "SPI card interface ready"); |
461 sdcard_state->host_ok = true; |
510 sdcard_state->host_ok = true; |
462 } else { |
511 } else { |
463 ESP_LOGE(TAG, "SPI card interface failed, abort task"); |
512 ESP_LOGE(TAG, "SPI card interface failed, abort task"); |
474 |
523 |
475 if (sdcard_state->card_present == false) { |
524 if (sdcard_state->card_present == false) { |
476 /* |
525 /* |
477 * If the card is not mounted, try it. |
526 * If the card is not mounted, try it. |
478 */ |
527 */ |
479 ret = my_esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card, card_handle); |
528 ret = my_esp_vfs_fat_sdspi_mount("/sdcard", &host, &slot_config, &mount_config, &card); |
480 if (ret == ESP_OK) { |
529 if (ret == ESP_OK) { |
481 ESP_LOGI(TAG, "SD card mounted on /sdcard"); |
530 ESP_LOGI(TAG, "SD card mounted on /sdcard"); |
482 sdcard_state->card_present = true; |
531 sdcard_state->card_present = true; |
483 |
532 |
484 DIR* dir = opendir("/sdcard/w/log"); |
533 DIR* dir = opendir("/sdcard/w/log"); |
494 * Check if the mounted card is still in the slot. |
543 * Check if the mounted card is still in the slot. |
495 */ |
544 */ |
496 DIR* dir = opendir("/sdcard/w/log"); |
545 DIR* dir = opendir("/sdcard/w/log"); |
497 if (dir == NULL) { |
546 if (dir == NULL) { |
498 ESP_LOGI(TAG, "SD card missing, unmount"); |
547 ESP_LOGI(TAG, "SD card missing, unmount"); |
499 my_esp_vfs_fat_sdmmc_unmount(); |
548 my_esp_vfs_fat_sdspi_unmount(); |
500 sdcard_state->card_present = false; |
549 sdcard_state->card_present = false; |
501 esp_log_level_set("sdmmc_sd", ESP_LOG_NONE); |
550 esp_log_level_set("sdmmc_sd", ESP_LOG_NONE); |
502 } else { |
551 } else { |
503 closedir(dir); |
552 closedir(dir); |
504 } |
553 } |