# How RPi_Pico_WAV_Player Handles exFAT SD Cards: FatFs Implementation Guide

> Discover how RPi_Pico_WAV_Player implements FatFs to support exFAT SD cards. Learn about automatic file system detection & bug workarounds for seamless operation. Get the guide here.

- Repository: [Elehobica/rpi_pico_wav_player](https://github.com/elehobica/rpi_pico_wav_player)
- Tags: deep-dive
- Published: 2026-03-01

---

**The RPi_Pico_WAV_Player uses the FatFs library (v0.90) to mount and detect exFAT volumes, automatically identifying the file system type during initialization and implementing a specific workaround for the FatFs parent directory navigation bug on exFAT cards.**

The RPi_Pico_WAV_Player is an open-source audio player for the Raspberry Pi Pico that relies on the FatFs library to manage SD card file systems. Understanding how it handles exFAT-formatted cards requires examining the initialization sequence in the file menu driver and the UI layer's navigation workarounds.

## FatFs Library Integration and SD Card Mounting

The player initializes SD card access through the `file_menu_init()` function in [`lib/file_menu/file_menu_FatFs.c`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/file_menu/file_menu_FatFs.c). This function configures the SPI interface for the micro-SD slot and attempts to mount the volume using FatFs's `f_mount()` function.

The initialization sequence performs the following steps:

1. **Configures the SPI hardware** with `pico_fatfs_spi_config_t`, setting the SPI instance, clock speed (40 MHz), and pin assignments.
2. **Attempts to mount** the volume with `f_mount(&fs, "", 1)`, retrying up to five times if the initial attempt fails.
3. **Detects the file system type** by reading `fs.fs_type` after successful mounting.

```cpp
// lib/file_menu/file_menu_FatFs.c – mount and detect FS type
FRESULT file_menu_init(uint8_t* fs_type) {
    pico_fatfs_spi_config_t config = {
        spi0, CLK_SLOW_DEFAULT, 40 * MHZ,
        PIN_SPI0_MISO_DEFAULT, PIN_SPI0_CS_DEFAULT,
        PIN_SPI0_SCK_DEFAULT, PIN_SPI0_MOSI_DEFAULT,
        true   // use internal pull-up
    };
    pico_fatfs_set_config(&config);
    for (int i = 0; i < 5; i++) {
        fr = f_mount(&fs, "", 1);                 // <- mount attempt
        if (fr == FR_OK) {
            *fs_type = fs.fs_type;                // <-- detected FS (FAT12/16/32/EXFAT)
            break;
        }
        pico_fatfs_reboot_spi();                  // retry on failure
    }
    return fr;
}

```

## Detecting exFAT File System Type

After successful mounting, the player determines whether the card uses exFAT, FAT32, FAT16, or FAT12 by examining the `fs_type` field of the FatFs object. The UI layer in [`src/UIMode.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/UIMode.cpp) maps these numeric constants to human-readable strings for display on the LCD console.

The mapping array defined in the UI layer translates the detected type:

```cpp
const char* fs_type_str[5] = {"NOT_MOUNTED","FAT12","FAT16","FAT32","EXFAT"};
printf("SD Card File System = %s\r\n", fs_type_str[vars->fs_type]);

```

This detection occurs in `UIOpeningMode::entry`, which calls `file_menu_init` and stores the returned `fs_type` in the global state variables.

## The exFAT Parent Directory Bug Workaround

FatFs version 0.90 contains a known bug when navigating the parent directory (`".."`) on exFAT volumes. The RPi_Pico_WAV_Player implements a specific workaround in [`src/UIMode.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/UIMode.cpp) to handle this edge case.

When the user attempts to navigate up a directory level and `vars->fs_type == FS_EXFAT`, the UI layer executes a directory stack rebuilding routine:

1. **Temporarily stores** the current navigation stack in a temporary stack.
2. **Closes** the current directory with `file_menu_close_dir()`.
3. **Re-opens** the root directory with `file_menu_open_dir("/")`.
4. **Replays** the stored directory stack to rebuild the path, excluding the final directory (the one being exited).

```cpp
if (vars->fs_type == FS_EXFAT) {        // <-- EXFAT detection
    // Work-around for FatFs bug with ".." on exFAT
    // Re-open the root and replay the directory-stack
    std::stack<stack_data_t> temp_stack;
    while (dir_stack.size() > 0) {
        item = dir_stack.top();
        dir_stack.pop();
        temp_stack.push(item);
    }
    file_menu_close_dir();
    file_menu_open_dir("/");          // root
    while (temp_stack.size() > 1) {   // rebuild intermediate dirs
        item = temp_stack.top(); temp_stack.pop();
        file_menu_sort_entry(item.head+item.column, item.head+item.column+1);
        file_menu_ch_dir(item.head+item.column);
        dir_stack.push(item);
    }
    item = temp_stack.top(); temp_stack.pop();
    dir_stack.push(item);
}

```

This workaround ensures reliable navigation on exFAT-formatted cards without requiring modifications to the underlying FatFs library.

## Practical Implementation Examples

### Mounting and Detecting the File System Type

When implementing SD card initialization in your own projects based on this player, use the `file_menu_init` function to handle both mounting and file system detection:

```cpp
uint8_t fs_type;
FRESULT res = file_menu_init(&fs_type);
if (res != FR_OK) {
    lcd->setMsg("No SD Card Found!", true);
    return;
}
const char* names[] = {"NOT_MOUNTED","FAT12","FAT16","FAT32","EXFAT"};
printf("Mounted SD card, FS = %s\n", names[fs_type]);

```

### Opening Directories on exFAT Volumes

After successful mounting, open the root directory to begin navigation. The FatFs abstraction layer handles exFAT transparently for most operations:

```cpp
if (file_menu_open_dir("/") != FR_OK) {
    lcd->setMsg("SD Card Read Error!", true);
    return;
}
uint16_t total = file_menu_get_num();   // includes ".." entry
printf("Entries in root = %u\n", total);

```

### Handling Directory Navigation with exFAT Awareness

When changing directories, the UI layer automatically applies the exFAT workaround when necessary. Application code should use the standard `file_menu_ch_dir` interface:

```cpp
// Assume the user selected entry 'entryIdx'
if (file_menu_is_dir(entryIdx)) {
    // The internal EXFAT workaround is automatically invoked
    // when the UI later asks to navigate up (..).
    file_menu_ch_dir(entryIdx);
}

```

## Summary

- **The RPi_Pico_WAV_Player uses FatFs v0.90** to handle SD card access, supporting FAT12, FAT16, FAT32, and exFAT file systems.
- **File system detection occurs during mounting** via `file_menu_init()` in [`lib/file_menu/file_menu_FatFs.c`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/file_menu/file_menu_FatFs.c), which reads the `fs.fs_type` field and returns it to the UI layer.
- **exFAT volumes require special handling** for parent directory navigation due to a known FatFs bug with the `".."` entry.
- **The workaround in [`src/UIMode.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/UIMode.cpp)** rebuilds the directory stack by closing the current directory, reopening the root, and replaying the navigation history when `vars->fs_type == FS_EXFAT`.

## Frequently Asked Questions

### Does RPi_Pico_WAV_Player support exFAT formatted SD cards?

Yes, the player fully supports exFAT through the FatFs library. When an SD card is mounted, the `file_menu_init()` function detects the file system type and stores it in `vars->fs_type`. The UI displays "EXFAT" when this value equals `FS_EXFAT`, confirming successful recognition of exFAT volumes.

### What is the FatFs exFAT parent directory bug?

FatFs version 0.90 contains a bug where navigating to the parent directory using the `".."` entry fails on exFAT volumes. This occurs because the library incorrectly handles directory entry lookups for the parent link in exFAT's directory structure. The RPi_Pico_WAV_Player works around this by completely rebuilding the directory path from root rather than relying on the standard parent directory entry.

### How does the player detect which file system is mounted?

Detection happens in [`lib/file_menu/file_menu_FatFs.c`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/file_menu/file_menu_FatFs.c) immediately after the `f_mount()` call succeeds. The function reads the `fs.fs_type` member of the FatFs object, which contains a numeric constant representing FAT12, FAT16, FAT32, or EXFAT. This value is copied to the caller via the `fs_type` pointer parameter and later used by the UI in [`src/UIMode.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/UIMode.cpp) to display the file system name and apply exFAT-specific logic.

### Where is the exFAT workaround implemented in the source code?

The workaround resides in [`src/UIMode.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/UIMode.cpp) within the directory navigation logic. When the user attempts to move up a directory level and `vars->fs_type == FS_EXFAT`, the code executes a stack rebuilding routine. It temporarily stores the current directory path, closes the open directory, reopens the root directory with `file_menu_open_dir("/")`, and then replays the stored navigation stack to reconstruct the path without using the problematic `".."` entry.