84590ec0a4
Current implementation has drive numbers and paths hardcoded to support only one FATFS drive. Arduino has it's own SPI driver to allow compatibility and flexibility. With the MR it is possible to have up to ```_VOLUMES``` drives connected (SPI, SDMMC and others) at the same time and accessed through VFS
135 lines
3.9 KiB
C
135 lines
3.9 KiB
C
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <stdlib.h>
|
|
#include "esp_log.h"
|
|
#include "esp_vfs.h"
|
|
#include "esp_vfs_fat.h"
|
|
#include "driver/sdmmc_host.h"
|
|
#include "sdmmc_cmd.h"
|
|
#include "diskio.h"
|
|
|
|
static const char* TAG = "vfs_fat_sdmmc";
|
|
static sdmmc_card_t* s_card = NULL;
|
|
static uint8_t s_pdrv = 0;
|
|
|
|
esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
|
|
const sdmmc_host_t* host_config,
|
|
const sdmmc_slot_config_t* slot_config,
|
|
const esp_vfs_fat_sdmmc_mount_config_t* mount_config,
|
|
sdmmc_card_t** out_card)
|
|
{
|
|
const size_t workbuf_size = 4096;
|
|
void* workbuf = NULL;
|
|
|
|
if (s_card != NULL) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
// enable SDMMC
|
|
sdmmc_host_init();
|
|
|
|
// enable card slot
|
|
sdmmc_host_init_slot(host_config->slot, slot_config);
|
|
s_card = malloc(sizeof(sdmmc_card_t));
|
|
if (s_card == NULL) {
|
|
return ESP_ERR_NO_MEM;
|
|
}
|
|
|
|
// probe and initialize card
|
|
esp_err_t err = sdmmc_card_init(host_config, s_card);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGD(TAG, "sdmmc_card_init failed 0x(%x)", err);
|
|
goto fail;
|
|
}
|
|
if (out_card != NULL) {
|
|
*out_card = s_card;
|
|
}
|
|
|
|
// connect SDMMC driver to FATFS
|
|
BYTE pdrv = ff_disk_getpdrv();
|
|
if (pdrv == 0xFF) {
|
|
ESP_LOGD(TAG, "the maximum count of volumes is already mounted");
|
|
goto fail;
|
|
}
|
|
ff_diskio_register_sdmmc(pdrv, s_card);
|
|
s_pdrv = pdrv;
|
|
char drv[3] = {(char)('0' + pdrv), ':', 0};
|
|
|
|
// connect FATFS to VFS
|
|
FATFS* fs;
|
|
err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs);
|
|
if (err == ESP_ERR_INVALID_STATE) {
|
|
// it's okay, already registered with VFS
|
|
} else if (err != ESP_OK) {
|
|
ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", err);
|
|
goto fail;
|
|
}
|
|
|
|
// Try to mount partition
|
|
FRESULT res = f_mount(fs, drv, 1);
|
|
if (res != FR_OK) {
|
|
err = ESP_FAIL;
|
|
ESP_LOGW(TAG, "failed to mount card (%d)", res);
|
|
if (!(res == FR_NO_FILESYSTEM && mount_config->format_if_mount_failed)) {
|
|
goto fail;
|
|
}
|
|
ESP_LOGW(TAG, "partitioning card");
|
|
DWORD plist[] = {100, 0, 0, 0};
|
|
workbuf = malloc(workbuf_size);
|
|
res = f_fdisk(s_pdrv, plist, workbuf);
|
|
if (res != FR_OK) {
|
|
err = ESP_FAIL;
|
|
ESP_LOGD(TAG, "f_fdisk failed (%d)", res);
|
|
goto fail;
|
|
}
|
|
ESP_LOGW(TAG, "formatting card");
|
|
res = f_mkfs("", FM_ANY, s_card->csd.sector_size, workbuf, workbuf_size);
|
|
if (res != FR_OK) {
|
|
err = ESP_FAIL;
|
|
ESP_LOGD(TAG, "f_mkfs failed (%d)", res);
|
|
goto fail;
|
|
}
|
|
free(workbuf);
|
|
ESP_LOGW(TAG, "mounting again");
|
|
res = f_mount(fs, drv, 0);
|
|
if (res != FR_OK) {
|
|
err = ESP_FAIL;
|
|
ESP_LOGD(TAG, "f_mount failed after formatting (%d)", res);
|
|
goto fail;
|
|
}
|
|
}
|
|
return ESP_OK;
|
|
|
|
fail:
|
|
free(workbuf);
|
|
esp_vfs_fat_unregister_ctx(base_path);
|
|
free(s_card);
|
|
s_card = NULL;
|
|
return err;
|
|
}
|
|
|
|
esp_err_t esp_vfs_fat_sdmmc_unmount()
|
|
{
|
|
if (s_card == NULL) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
// unmount
|
|
char drv[3] = {(char)('0' + s_pdrv), ':', 0};
|
|
f_mount(0, drv, 0);
|
|
// release SD driver
|
|
free(s_card);
|
|
s_card = NULL;
|
|
sdmmc_host_deinit();
|
|
return esp_vfs_fat_unregister();
|
|
}
|