VFS path conflict issue between TinyUSB MSC and SDMMC

dhugoexe
Posts: 3
Joined: Fri May 23, 2025 8:10 am

VFS path conflict issue between TinyUSB MSC and SDMMC

Postby dhugoexe » Tue Jun 24, 2025 8:13 am

Hi everyone,

Try to register two instances in VFS:
* SDMMC (`esp_vfs_fat_sdmmc_mount_config_t`)
* Custom TinyUSB MSC FAT instance (`esp_vfs_fat_conf_t`) with diskio functions implementations (with `tuh_msc_read10` and `tuh_msc_write10`)

In order to have two mounting points: `/sdcard` and `/usb`

Actually, with the following code, I can mount both of them, but after mounting USB, there is a conflict in paths: the `/sdcard` path gives me files from `/usb`, but the USB one gives me the correct files.

```c
void bsp_mount_sdcard(void)
{
esp_err_t ret;
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_SD_FORMAT_IF_MOUNT_FAILED
.format_if_mount_failed = true,
#else
.format_if_mount_failed = false,
#endif
.max_files = 5,
.allocation_unit_size = 16 * 1024};
const char mount_point[] = SDCARD_BASE_PATH;
ESP_LOGI(TAG, "Initializing SD card");
ESP_LOGI(TAG, "Using SDMMC peripheral");

sdmmc_host_t host = SDMMC_HOST_DEFAULT();
host.max_freq_khz = SDMMC_FREQ_DEFAULT;
host.slot = SDMMC_HOST_SLOT_0;

sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = 4,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;

ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
return;
}
host.pwr_ctrl_handle = pwr_ctrl_handle;

sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = 4;
slot_config.clk = BSP_SD_CLK;
slot_config.cmd = BSP_SD_CMD;
slot_config.d0 = BSP_SD_D0;
slot_config.d1 = BSP_SD_D1;
slot_config.d2 = BSP_SD_D2;
slot_config.d3 = BSP_SD_D3;
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;

ESP_LOGD(TAG, "Mounting sdcard to filesystem");
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);

if (ret != ESP_OK)
{
if (ret == ESP_FAIL){
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set the SD_FORMAT_IF_MOUNT_FAILED menuconfig option.");
}
else{
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.",
esp_err_to_name(ret));
}
return;
}
ESP_LOGD(TAG, "Sdcard mouted to Filesystem");

sdmmc_card_print_info(stdout, card);
}
```

```c
void mount_task(void *param)
{
mount_info_t mount_info;

while (1)
{
if (xQueueReceive(mount_queue, &mount_info, portMAX_DELAY) == pdTRUE)
{
if (isUsbMscMounted)
{
ESP_LOGW("MOUNT_TASK", "USB MSC already mounted, skipping");
// notification
continue;
}
ESP_LOGD("MOUNT_TASK", "Starting mount process for device %d", mount_info.dev_addr);

printf("%.8s %.16s rev %.4s\r\n",
mount_info.vendor_id,
mount_info.product_id,
mount_info.product_rev);

printf("Disk Size: %" PRIu32 " MB\r\n",
mount_info.block_count / ((1024 * 1024) / mount_info.block_size));
printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n",
mount_info.block_count, mount_info.block_size);

uint8_t const drive_num = mount_info.dev_addr - 1;
char drive_path[8];
snprintf(drive_path, sizeof(drive_path), "%d:", drive_num);

ESP_LOGD("MOUNT_TASK", "Mounting dev_addr %d as drive %d (%s)",
mount_info.dev_addr, drive_num, drive_path);

FATFS *fs = &fatfs[drive_num];

esp_vfs_fat_conf_t config = {
.base_path = USB_DIR,
.fat_drive = drive_path,
.max_files = 5};

esp_err_t err = esp_vfs_fat_register_cfg(&config, &fs);
if (err != ESP_OK)
{
ESP_LOGE("MOUNT_TASK", "Failed to register VFS: %s", esp_err_to_name(err));
continue;
}
ESP_LOGD("MOUNT_TASK", "VFS registered successfully");

usb_diskio_impl.init = &usb_disk_initialize;
usb_diskio_impl.status = &usb_disk_status;
usb_diskio_impl.read = &usb_disk_read;
usb_diskio_impl.write = &usb_disk_write;
usb_diskio_impl.ioctl = &usb_disk_ioctl;

ff_diskio_register(drive_num, &usb_diskio_impl);
ESP_LOGD("MOUNT_TASK", "FFDISKIO registered for drive %d", drive_num);

ESP_LOGD("MOUNT_TASK", "Attempting to mount filesystem...");
FRESULT mount_result = f_mount(fs, drive_path, 1);
if (mount_result != FR_OK)
{
ESP_LOGE("MOUNT_TASK", "f_mount failed: %d", mount_result);

ff_diskio_register(drive_num, NULL);
esp_vfs_fat_unregister_path(ROX_USB_DIR);
continue;
}

isUsbMscMounted = true;

}
}
vTaskDelay(pdMS_TO_TICKS(2000));
}
```

Config information:
* Maximum Number of Virtual Filesystems: 8
* Host FS: Maximum number of the host filesystem mount points: 8
* ESP-IDF v5.4.0
* ESP32-P4 (Waveshare DevKit)

igi540
Espressif staff
Espressif staff
Posts: 7
Joined: Thu Jan 23, 2025 1:00 pm

Re: VFS path conflict issue between TinyUSB MSC and SDMMC

Postby igi540 » Thu Jun 26, 2025 11:01 am

Hi dhugoexe,
You're encountering a VFS conflict where both /sdcard and /usb end up pointing to the same underlying FATFS drive, likely due to overlapping or reused drive numbers (e.g., 0:).
When you mount the USB disk, it's likely using the same drive letter (0:) as the SD card, which causes /sdcard to unexpectedly point to the USB contents.
Assign distinct FATFS drive letters (0:, 1:) to each mount point.

Example Fix
For SD card (uses esp_vfs_fat_sdmmc_mount, which auto assigns 0: internally):

Code: Select all

esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
For USB MSC, manually assign drive 1::

Code: Select all

uint8_t usb_drive = 1;  // Ensure this is different from SD's drive
char usb_fat_drive[3];
snprintf(usb_fat_drive, sizeof(usb_fat_drive), "%u:", usb_drive);

esp_vfs_fat_conf_t usb_cfg = {
    .base_path = "/usb",
    .fat_drive = usb_fat_drive,
    .max_files = 5
};

FATFS *usb_fs;
esp_err_t err = esp_vfs_fat_register_cfg(&usb_cfg, &usb_fs);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "Failed to register USB VFS: %s", esp_err_to_name(err));
    return;
}

ff_diskio_register(usb_drive, &usb_diskio_impl);

FRESULT fres = f_mount(usb_fs, usb_fat_drive, 1);
if (fres != FR_OK) {
    ESP_LOGE(TAG, "Failed to mount USB drive: %d", fres);
    esp_vfs_fat_unregister_path("/usb");
    ff_diskio_register(usb_drive, NULL);
    return;
}
If you need to remount the USB drive:

Code: Select all

f_mount(NULL, usb_fat_drive, 1);
esp_vfs_fat_unregister_path("/usb");
ff_diskio_register(usb_drive, NULL);
SD uses 0: (default by esp_vfs_fat_sdmmc_mount)

USB should use 1: or higher

Match fat_drive string (e.g., "1:") to what ff_diskio_register() and f_mount() expect

Who is online

Users browsing this forum: Barkrowler, Bytespider, Google [Bot], Perplexity-User, PerplexityBot, PetalBot and 2 guests