Skip to content

feat(sdcard): SD / microSD card component (SDSPI + SDMMC) with separate init and mount; port every uSD BSP onto it - #800

Merged
finger563 merged 9 commits into
mainfrom
feat/sdcard-component
Sep 18, 2026
Merged

finger563 merged 9 commits into
mainfrom
feat/sdcard-component

Conversation

@finger563

@finger563 finger563 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Summary

New sdcard component (espp::SdCard) that brings up an SD / microSD card over SDSPI (any target) or the SDMMC / SDIO peripheral (ESP32, -S3, -P4), and ports every BSP with a microSD slot onto it.

The one design point: card initialization and FAT mounting are separate steps. initialize() brings up the host (SPI device, or SDMMC slot with an optional on-chip LDO) and probes the card; mount() / unmount() register the FAT volume any number of times while the card stays initialized. card() returns the initialized sdmmc_card_t *, which is exactly what the usb_device MSC function (#798) needs: probe the card with mount_on_initialize = false and hand card() to MscMedium::sd_card, or on a BSP call initialize_sdcard() then sdcard_component()->unmount().

Component

  • Config::interface is a std::variant<SpiConfig, SdmmcConfig>:
    • SpiConfig: host, CS, optional bus ownership (initialize_bus + MOSI/MISO/SCLK/max transfer), frequency, CD/WP pins.
    • SdmmcConfig: slot, 1- or 4-bit width, CLK/CMD/D0–D3 (GPIO-matrix targets; the ESP32 uses its fixed pins), frequency, CD/WP, ldo_channel (ESP32-P4 powers the SD pads from LDO 4).
  • mount_on_initialize, format_if_mount_failed (default off: never wipe an unknown card), max_files, allocation_unit_size, disk_status_check, log_level last.
  • initialize / mount / unmount / format / deinitialize (with and without std::error_code), card_info(), volume_info(), print_info(), is_initialized(), is_mounted().
  • Implemented on the low-level diskio path (sdmmc_card_init + ff_diskio_register_sdmmc + esp_vfs_fat_register + f_mount) instead of esp_vfs_fat_sd*_mount(): IDF's own split init/mount helpers only exist from IDF 6.1, and this keeps the floor at IDF 5.0 (esp_vfs_fat_register signature is version-guarded; driver deps switch to esp_driver_* on 5.4+).
  • Example (components/sdcard/example, esp32s3 in CI; also built for esp32p4 and esp32/SPI): boot counter, file listing, unmount/remount. Menuconfig selects SDMMC or SPI and the pins (defaults are the T-Dongle-S3 / P4 LDO).
  • Docs under storage/sdcard, Doxygen, CI build entry, upload_components.yml entry.

BSP ports (14)

t-deck, t-dongle-s3, m5stack-tab5, m5stack-cardputer, lilygo-t5-47, smartpanlee-sc01-plus, ws-s3-geek, ws-s3-lcd-1-47, xiao-esp32s3-sense, esp32-p4-eth, esp32-p4-function-ev-board, esp32-p4-module-dev-kit, esp32-p4-nano, esp32-p4-wifi6-dev-kit.

Each BSP's initialize_sdcard(SdCardConfig) and sdcard() keep their signatures. The hand-rolled esp_vfs_fat_sd*_mount() code becomes a std::unique_ptr<espp::SdCard>; sdcard() returns card() as before and a new sdcard_component() accessor exposes the object (unmount / remount / format / volume info / MSC hand-off). Tab5's LDO handle member is gone (the component owns it). BSP SdCardConfig structs are unchanged.

Things to know

  • Manager-on BSP examples fail to resolve espp/sdcard until it is published (tab5, esp32-p4-eth / module-dev-kit / nano / wifi6-dev-kit, lilygo-t5-47, xiao-esp32s3-sense): EXTRA_COMPONENT_DIRS does not override a namespaced registry dependency, same as stream_frame in feat(dispatcher): stream_frame codec + Dispatcher multiplexer; OTA rides them #747. They were all verified locally with a temporary override_path (not committed). The manager-off examples and the component example build regardless.
  • Local IDF is v6.1 while CI is v6.0.1; t-deck's untouched audio.cpp fails locally on i2s_chan_config_t::rx_destination, but its sdcard.cpp compiles and CI on main is green for t-deck.
  • format() / format_if_mount_failed use FatFs f_mkfs on the card's own drive number (unlike esp_vfs_fat which formats drive 0).
  • The usb_device README and MSC example README now point at espp::SdCard for the probe-without-mount step.

Test plan

  • components/sdcard/example builds for esp32s3, esp32p4, esp32 (SPI)
  • All 14 BSP examples build (manager-on ones with a temporary local override)
  • clang-format clean, cppcheck reports nothing new
  • Hardware: T-Dongle-S3 BSP example (SDMMC 4-bit, 40 MHz): card probed and mounted
  • Hardware: T-Dongle-S3 as a USB drive through the MSC example's BSP option (initialize_sdcard()unmount()sdcard()): drive appears on the PC, about 1 MB/s
  • Hardware: an SPI-wired board

🤖 Generated with Claude Code

https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU

finger563 and others added 3 commits September 17, 2026 12:36
…te card init and FAT mount

espp::SdCard brings up a card over SDSPI (any target) or the SDMMC / SDIO
peripheral (ESP32, ESP32-S3, ESP32-P4) and keeps card initialization and
FAT mounting as two steps: initialize() probes the card (card() is then a
valid sdmmc_card_t), mount() / unmount() register the FAT volume at
Config::mount_point any number of times. That is what USB mass storage
needs -- espp::UsbDevice's MSC function hands the raw card to a PC, which
must not happen while the firmware has the volume mounted -- and what
ESP-IDF's all-in-one esp_vfs_fat_sd*_mount() cannot offer (its split
variants only arrived in v6.1).

- Config::interface is a variant of SpiConfig (host, cs, optionally own
  and free the bus) and SdmmcConfig (slot, 1/4-bit, GPIO-matrix pins,
  clock, optional on-chip LDO channel -- the ESP32-P4 powers its SD pads
  from LDO 4).
- mount / unmount / format use the FatFs diskio + esp_vfs_fat_register
  calls IDF's helper uses internally (version-guarded for v5.0+), so the
  card is never re-probed; format() runs f_mkfs on the card's own drive.
- card_info() / volume_info() / print_info(); std::error_code everywhere.
- Example (SDMMC or SPI, pins via Kconfig; defaults = T-Dongle-S3 slot)
  records a boot counter, lists files, unmounts and remounts. Builds for
  esp32s3, esp32p4 (LDO) and esp32 (SPI).
- README, docs page (storage/sdcard.rst), Doxyfile and CI matrix entries.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…SC docs

- drop the 2-character `SD` manifest tag (the registry requires 3-32
  characters: "Manifest is not valid")
- add components/sdcard to upload_components.yml
- release the SDMMC host the way IDF does when slot init fails
- plain ESP_IDF_VERSION_MAJOR/MINOR tests (cppcheck can't parse
  ESP_IDF_VERSION_VAL) and `= SpiConfig{}` initializers
- point the usb_device README and MSC example README at espp::SdCard for
  the probe-without-mount step

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
Replace the hand-rolled esp_vfs_fat_sd*_mount() code in t-deck, t-dongle-s3,
m5stack-tab5, m5stack-cardputer, lilygo-t5-47, smartpanlee-sc01-plus,
ws-s3-geek, ws-s3-lcd-1-47, xiao-esp32s3-sense, esp32-p4-eth,
esp32-p4-function-ev-board, esp32-p4-module-dev-kit, esp32-p4-nano and
esp32-p4-wifi6-dev-kit with a std::unique_ptr<espp::SdCard>.

initialize_sdcard(SdCardConfig) and sdcard() keep their signatures; a new
sdcard_component() accessor exposes the component (unmount / remount /
format / volume info / MSC hand-off). Tab5 no longer keeps its own LDO
handle. Manager-on examples list components/sdcard in EXTRA_COMPONENT_DIRS
and the BSP manifests depend on espp/sdcard.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
Copilot AI lite review requested due to automatic review settings September 18, 2026 01:10
@github-actions

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Introduces a new sdcard component (espp::SdCard) that supports SD / microSD over SDSPI or SDMMC with split initialize vs mount/unmount, and migrates multiple BSPs and docs to use it (including guidance for USB MSC hand-off).

Changes:

  • Added components/sdcard component + example (Kconfig, docs, CI integration).
  • Ported several BSP SD card bring-up paths to espp::SdCard and exposed sdcard_component() accessors.
  • Updated documentation (storage docs + USB MSC docs) to describe the split init/mount model and MSC usage.

Reviewed changes

Copilot reviewed 82 out of 82 changed files in this pull request and generated no comments.

Show a summary per file
File Description
doc/en/storage/sdcard_example.md Adds storage docs page including the component example README.
doc/en/storage/sdcard.rst New SD card documentation page describing the new component and its init/mount split.
doc/en/storage/index.rst Adds sdcard to the storage docs toctree.
doc/Doxyfile Adds sdcard header and example source to Doxygen inputs.
.github/workflows/upload_components.yml Publishes the new sdcard component.
.github/workflows/build.yml Adds CI build for components/sdcard/example.
components/sdcard/src/sdcard.cpp Implements the espp::SdCard component (init host, probe, mount/unmount, format).
components/sdcard/include/sdcard.hpp Public API for espp::SdCard (SPI/SDMMC config + split lifecycle).
components/sdcard/idf_component.yml Component manager manifest for espp/sdcard.
components/sdcard/CMakeLists.txt IDF-version-dependent driver dependencies + component registration.
components/sdcard/README.md Component README describing configuration and MSC sharing.
components/sdcard/example/CMakeLists.txt Top-level example project CMake.
components/sdcard/example/sdkconfig.defaults Example defaults (target, FATFS LFN/label, stack).
components/sdcard/example/README.md Example README showing init/mount split and MSC hand-off.
components/sdcard/example/main/CMakeLists.txt Example “main” component registration.
components/sdcard/example/main/Kconfig.projbuild Menuconfig options for SDMMC vs SPI and pins.
components/sdcard/example/main/sdcard_example.cpp Example app demonstrating mount/unmount and basic file I/O.
components/usb_device/msc_example/README.md Updates MSC example docs to reference espp::SdCard and BSP accessors.
components/usb_device/README.md Updates MSC docs snippet to show using sdcard.card() and probe-without-mount.
components/xiao-esp32s3-sense/src/xiao-esp32s3-sense.cpp Ports Xiao ESP32-S3 Sense SD init to espp::SdCard (SPI).
components/xiao-esp32s3-sense/include/xiao-esp32s3-sense.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/xiao-esp32s3-sense/idf_component.yml Adds espp/sdcard dependency.
components/xiao-esp32s3-sense/CMakeLists.txt Adds sdcard to REQUIRES.
components/xiao-esp32s3-sense/example/CMakeLists.txt Adds local components/sdcard to example build.
components/ws-s3-lcd-1-47/src/sdcard.cpp Ports WS-S3-LCD-1.47 SD init to espp::SdCard (SDMMC).
components/ws-s3-lcd-1-47/include/ws-s3-lcd-1-47.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/ws-s3-lcd-1-47/idf_component.yml Adds espp/sdcard dependency.
components/ws-s3-lcd-1-47/CMakeLists.txt Adds sdcard to REQUIRES.
components/ws-s3-geek/src/sdcard.cpp Ports WS-S3-Geek SD init to espp::SdCard (SPI).
components/ws-s3-geek/include/ws-s3-geek.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/ws-s3-geek/idf_component.yml Adds espp/sdcard dependency.
components/ws-s3-geek/CMakeLists.txt Adds sdcard to REQUIRES.
components/t-dongle-s3/src/sdcard.cpp Ports T-Dongle-S3 SD init to espp::SdCard (SDMMC).
components/t-dongle-s3/include/t-dongle-s3.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/t-dongle-s3/idf_component.yml Adds espp/sdcard dependency.
components/t-dongle-s3/CMakeLists.txt Adds sdcard to REQUIRES.
components/t-deck/src/sdcard.cpp Ports T-Deck SD init to espp::SdCard (SPI on shared bus).
components/t-deck/include/t-deck.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/t-deck/idf_component.yml Adds espp/sdcard dependency.
components/t-deck/CMakeLists.txt Adds sdcard to REQUIRES.
components/smartpanlee-sc01-plus/src/smartpanlee-sc01-plus.cpp Ports SmartPanlee SC01 Plus SD init to espp::SdCard (SPI) and uses volume_info().
components/smartpanlee-sc01-plus/include/smartpanlee-sc01-plus.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/smartpanlee-sc01-plus/idf_component.yml Adds espp/sdcard dependency.
components/smartpanlee-sc01-plus/CMakeLists.txt Adds sdcard to REQUIRES.
components/m5stack-tab5/src/sdcard.cpp Ports Tab5 SD init to espp::SdCard (SDMMC with LDO) and uses volume_info().
components/m5stack-tab5/include/m5stack-tab5.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/m5stack-tab5/idf_component.yml Adds espp/sdcard dependency.
components/m5stack-tab5/CMakeLists.txt Adds sdcard to REQUIRES.
components/m5stack-tab5/example/CMakeLists.txt Adds local components/sdcard to example build.
components/m5stack-cardputer/src/sdcard.cpp Ports Cardputer SD init to espp::SdCard (SPI on shared bus).
components/m5stack-cardputer/include/m5stack-cardputer.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/m5stack-cardputer/idf_component.yml Adds espp/sdcard dependency.
components/m5stack-cardputer/CMakeLists.txt Adds sdcard to REQUIRES.
components/lilygo-t5-47/src/sdcard.cpp Ports LilyGo T5-4.7 SD init to espp::SdCard (SPI on shared bus).
components/lilygo-t5-47/include/lilygo-t5-47.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/lilygo-t5-47/idf_component.yml Adds espp/sdcard dependency.
components/lilygo-t5-47/CMakeLists.txt Adds sdcard to REQUIRES.
components/lilygo-t5-47/example/CMakeLists.txt Adds local components/sdcard to example build.
components/esp32-p4-wifi6-dev-kit/src/sdcard.cpp Ports P4 WiFi6 Dev Kit SD init to espp::SdCard (SDMMC with LDO) and uses volume_info().
components/esp32-p4-wifi6-dev-kit/include/esp32-p4-wifi6-dev-kit.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/esp32-p4-wifi6-dev-kit/idf_component.yml Adds espp/sdcard dependency.
components/esp32-p4-wifi6-dev-kit/CMakeLists.txt Adds sdcard to component REQUIRES list.
components/esp32-p4-wifi6-dev-kit/example/CMakeLists.txt Adds local components/sdcard to example build.
components/esp32-p4-nano/src/sdcard.cpp Ports P4 Nano SD init to espp::SdCard (SDMMC with LDO) and uses volume_info().
components/esp32-p4-nano/include/esp32-p4-nano.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/esp32-p4-nano/idf_component.yml Adds espp/sdcard dependency.
components/esp32-p4-nano/CMakeLists.txt Adds sdcard to component REQUIRES list.
components/esp32-p4-nano/example/CMakeLists.txt Adds local components/sdcard to example build.
components/esp32-p4-module-dev-kit/src/sdcard.cpp Ports P4 Module Dev Kit SD init to espp::SdCard (SDMMC with LDO) and uses volume_info().
components/esp32-p4-module-dev-kit/include/esp32-p4-module-dev-kit.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/esp32-p4-module-dev-kit/idf_component.yml Adds espp/sdcard dependency.
components/esp32-p4-module-dev-kit/CMakeLists.txt Adds sdcard to component REQUIRES list.
components/esp32-p4-module-dev-kit/example/CMakeLists.txt Adds local components/sdcard to example build.
components/esp32-p4-function-ev-board/src/sdcard.cpp Ports P4 Function EV Board SD init to espp::SdCard (SDMMC with LDO) and uses volume_info().
components/esp32-p4-function-ev-board/include/esp32-p4-function-ev-board.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/esp32-p4-function-ev-board/idf_component.yml Adds espp/sdcard dependency.
components/esp32-p4-function-ev-board/CMakeLists.txt Adds sdcard to component REQUIRES list.
components/esp32-p4-eth/src/sdcard.cpp Ports P4 ETH SD init to espp::SdCard (SDMMC with LDO) and uses volume_info().
components/esp32-p4-eth/include/esp32-p4-eth.hpp Switches SD handle to std::unique_ptr<SdCard> and adds sdcard_component().
components/esp32-p4-eth/idf_component.yml Adds espp/sdcard dependency.
components/esp32-p4-eth/CMakeLists.txt Adds sdcard to component REQUIRES list.
components/esp32-p4-eth/example/CMakeLists.txt Adds local components/sdcard to example build.
Suppressed comments (5)

components/sdcard/src/sdcard.cpp:1

  • If host_.init() succeeds but sdspi_host_init_device() fails, the SDSPI host is not deinitialized (only the SPI bus is freed). This can leak driver state/resources and make subsequent attempts fail. Track whether host_.init() ran successfully and call call_host_deinit(host_) on this failure path before freeing the bus / returning.
    components/sdcard/src/sdcard.cpp:1
  • ff_diskio_register_sdmmc() returns an esp_err_t, but the result is currently ignored. If registration fails, subsequent VFS registration / f_mount() will operate on an unregistered drive and can fail in confusing ways (and may skip proper cleanup). Check the return value, log the ESP-IDF error name, and abort/cleanup early when it is not ESP_OK.
    components/sdcard/src/sdcard.cpp:1
  • FR_INT_ERR indicates an internal FatFs error, not 'no filesystem'. Treating it as 'no filesystem' can trigger an unnecessary (and destructive) format when format_if_mount_failed is enabled. Suggestion: only enter the format path for FR_NO_FILESYSTEM (and possibly FR_INVALID_DRIVE depending on your supported cases) and handle FR_INT_ERR by returning an io_error with a clear log message instead.
    components/sdcard/src/sdcard.cpp:1
  • This relies on an implicit invariant that bus_initialized_ can only be true when config_.interface holds SpiConfig. If that invariant is ever broken (e.g., future refactor or config mutation), std::get<SpiConfig> will throw. To make this more robust, consider storing the SPI host used for the bus in its own member when initializing (e.g. spi_bus_host_), or use std::get_if<SpiConfig> here and only free when it matches.
    components/sdcard/example/main/Kconfig.projbuild:1
  • The Kconfig range 1 4 allows values 2 and 3, but the implementation rejects anything other than 1 or 4 (SdmmcConfig::bus_width must be 1 or 4). To prevent invalid configurations at build time, consider changing this to a choice (1-bit vs 4-bit) and mapping the choice to bus_width, or otherwise constraining the config so only 1 or 4 can be selected.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Publication ordering, invalid menu values, and stale BSP mount-status reporting must be corrected.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 82/82 changed files
  • Comments generated: 12
  • Review effort level: Balanced

Comment thread .github/workflows/upload_components.yml Outdated
Comment thread components/esp32-p4-eth/include/esp32-p4-eth.hpp Outdated
Comment thread components/esp32-p4-module-dev-kit/include/esp32-p4-module-dev-kit.hpp Outdated
Comment thread components/esp32-p4-nano/include/esp32-p4-nano.hpp Outdated
Comment thread components/sdcard/example/main/Kconfig.projbuild Outdated
Comment thread components/smartpanlee-sc01-plus/src/smartpanlee-sc01-plus.cpp Outdated
Comment thread .github/workflows/build.yml Outdated
Comment thread doc/Doxyfile Outdated
Comment thread doc/Doxyfile Outdated
- upload_components.yml: list sdcard ahead of the BSPs that depend on it
  (first-time publish ordering), with a note like ethernet / stream_frame
- build.yml + Doxyfile: alphabetize the sdcard entries after rx8130ce
- example Kconfig: SDMMC bus width is a 1-bit / 4-bit choice instead of an
  int range that also allowed 2 and 3
- esp32-p4-* / m5stack-tab5 / smartpanlee-sc01-plus: is_sd_card_available()
  reports the component's current mount state instead of a sticky
  initialized flag (false after sdcard_component()->unmount())

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Three mount-failure paths leave FatFs referencing freed filesystem state.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

components/sdcard/src/sdcard.cpp:323

  • When formatting fails after the initial f_mount, the FATFS object remains registered with FatFs. Unregistering the VFS then frees that object while the drive table still references it. Detach the failed mount before releasing the VFS and diskio, matching ESP-IDF's cleanup order.
    components/sdcard/src/sdcard.cpp:332
  • This general mount-failure path also frees the VFS FATFS while it is still registered in FatFs's drive table. Call f_mount(nullptr, drive, 0) first; otherwise a later access to that logical drive can dereference freed state.
  • Files reviewed: 82/82 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread components/sdcard/src/sdcard.cpp Outdated
…s or the T-Dongle-S3 BSP)

menuconfig "MSC Example Configuration" picks the medium: the flash FAT
partition (default), an SD card probed with espp::SdCard on configurable
SDMMC pins (defaults: T-Dongle-S3 slot, optional P4 LDO channel), or the
T-Dongle-S3 BSP's card via initialize_sdcard() + sdcard_component()->unmount()
+ sdcard() -- the hand-off pattern for every espp BSP with a uSD slot. SD
cards are never formatted by the example. The BSP and its components are
always compiled (manager-off dirs listed explicitly) so the choice lives in
menuconfig; the BSP is only instantiated when selected.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
@finger563

Copy link
Copy Markdown
Contributor Author

Added db9cb0a: the usb_device MSC example now picks its medium in menuconfig (MSC Example Configuration → Medium exposed as the USB drive): the flash partition (default), an SD card probed with espp::SdCard on configurable SDMMC pins (defaults = T-Dongle-S3 slot), or the T-Dongle-S3 BSP's card via initialize_sdcard()sdcard_component()->unmount()sdcard(). All three variants build (manager off, esp32s3). SD cards are never formatted by the example.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU

finger563 and others added 4 commits September 18, 2026 10:01
…nyusb submodule

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…off dirs

A stray working-tree edit slipped into ab15905 and replaced the tinyusb entry
with a second esp_tinyusb one, so manager-off builds failed to resolve
'tinyusb'.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…ount failure

f_mount(fs, drive, 1) registers fs in FatFs's drive table even when the
volume fails to mount, so every mount_locked() failure path now calls
f_mount(nullptr, drive, 0) before esp_vfs_fat_unregister_path() and
ff_diskio_unregister(), matching ESP-IDF's own cleanup order.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…ent card validity while unmounted

Self-review follow-ups on #800:
- format_locked() used ff_memalloc(), which FatFs only declares when
  CONFIG_FATFS_LFN_HEAP is set (every build so far had it), and which may
  prefer PSRAM. Use heap_caps_malloc(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
  like IDF; verified with CONFIG_FATFS_LFN_NONE.
- every BSP's sdcard() note said the card needs a valid mount point; it now
  says the card stays valid while the volume is unmounted (MSC hand-off).
- MscMedium::sd_card doc points at espp::SdCard::card().

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
@finger563
finger563 merged commit 01f2776 into main Sep 18, 2026
161 of 165 checks passed
@finger563
finger563 deleted the feat/sdcard-component branch September 18, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants