|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The SD card on SDMMC slot 0: mount, unmount, holds, and the look at a card that does not mount. More...
#include "storage.h"#include "storage_priv.h"#include <stdatomic.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "board_pins.h"#include "ff.h"#include "diskio_impl.h"#include "diskio_sdmmc.h"#include "driver/sdmmc_host.h"#include "esp_check.h"#include "esp_log.h"#include "esp_vfs_fat.h"#include "freertos/FreeRTOS.h"#include "freertos/semphr.h"#include "sd_pwr_ctrl_by_on_chip_ldo.h"#include "sdmmc_cmd.h"Data Structures | |
| struct | [struct].s |
| Driver state of the UART: the claimed machines and the pins. More... | |
Macros | |
| #define | STORAGE_IDF_MOUNT_TAG "vfs_fat_sdmmc" |
| #define | STORAGE_IDF_DISKIO_TAG "diskio_sdmmc" |
| #define | STORAGE_IDF_CMD_TAG "sdmmc_cmd" |
Functions | |
| static bool | lock_ready (void) |
| static void | lock (void) |
| static void | unlock (void) |
| static void | set_state (card_state_t state) |
| static void | publish (void) |
| static void | name_set (const char *name) |
| static void | read_name (void) |
| static const char * | volume_format (void) |
| static int | probe_fatfs (const sdmmc_host_t *host, const sdmmc_slot_config_t *slot, esp_err_t *why) |
| What FatFs says of the card esp_vfs_fat_sdmmc_mount() just gave up on. | |
| static void | mount_failed (esp_err_t err, const sdmmc_host_t *host, const sdmmc_slot_config_t *slot) |
| A mount that failed after the card started: which kind of card it is, said once in the log and kept for the screens. | |
| static bool | fat_usage (uint64_t *total, uint64_t *freebytes) |
| static esp_err_t | mount_locked (void) |
| Mount whatever the slot holds, under s.lock, with nothing mounted. | |
| static void | unmount_locked (void) |
| Let the volume go, under s.lock, with nothing holding it. | |
| static void | drop_locked (card_state_t state) |
| static void | lose_locked (int fr, const char *how) |
| static int | probe_locked (void) |
| static bool | removal_shaped (int fr) |
| esp_err_t | storage_init (void) |
| Switch the card's supply on and mount the card at /sdcard. | |
| card_state_t | storage_check (void) |
| bool | storage_hold (void) |
| bool | storage_hold_mount (unsigned mount) |
| void | storage_release (void) |
| FILE * | storage_fopen (const char *path, const char *mode) |
| int | storage_fclose (FILE *f) |
| void | storage_deinit (void) |
| Unmount and switch the card's supply off. Safe to call when nothing was mounted. Clears storage_status() and storage_card_state(). The end of the card's use: nothing may still be open, and no hold is waited for. | |
| unsigned | storage_mount_count (void) |
| bool | storage_mounted (void) |
| void | storage_card_name (char *out, size_t n) |
| const char * | storage_status (void) |
| What went wrong, in a few words for the console and the start-up line: "no card", "no FAT volume", "FatFs <n>", "LDO <error>" or ESP-IDF's error name. "" when all is well. At most 47 characters. | |
| card_state_t | storage_card_state (void) |
| uint64_t | storage_total_bytes (void) |
| uint64_t | storage_free_bytes (void) |
| static bool | read_failed_locked (int fr, const char *how) |
| const char * | storage_drive (void) |
| bool | storage_read_end (int fr, const char *how, bool may_mount) |
Variables | |
| static const char * | TAG = "storage" |
| static struct | s |
| static portMUX_TYPE | s_name_mux = portMUX_INITIALIZER_UNLOCKED |
The SD card on SDMMC slot 0: mount, unmount, holds, and the look at a card that does not mount.
The SDMMC host is shared with the ESP32-C6's SDIO link on slot 1 (wifi_radio.c). Each slot's start and card start set the host's clock divider, which both slots share, and send the clock update commands outside ESP-IDF's request mutex (sdmmc_host_set_card_clk(), sdmmc_host.c 301-351). So a mount here can make a C6 transfer under way fail, and esp_hosted's start of slot 1 (at the first Wi-Fi start, and at each C6 reset it makes) can make a card read or write under way fail. Neither is measured. test_storage holds the slot count against test/host/storage_stub/storage_fake.c, which counts slots as ESP-IDF does; the shared clock divider is not modelled there.
SPDX-License-Identifier: MIT
|
static |
A mount that failed after the card started: which kind of card it is, said once in the log and kept for the screens.
| err | The mount's error. |
| host | The host as the mount had it. |
| slot | The slot as the mount had it. |
|
static |
Mount whatever the slot holds, under s.lock, with nothing mounted.
|
static |
What FatFs says of the card esp_vfs_fat_sdmmc_mount() just gave up on.
That mount answers ESP_FAIL for every FatFs refusal alike, and only after the card has started (its own start-up errors come back as they are): no FAT volume on the card, a read error and an internal error are one code to its caller. So the card is started again here, the way the mount starts it, and handed to FatFs alone, without the VFS (virtual file system) path: f_mount()'s own answer, e.g. FR_NO_FILESYSTEM (13) for a card that holds NTFS, a GPT or nothing. The volume is let go before returning; a mount is still storage_init()'s alone.
Only on that failure, so a card that mounts costs nothing more. The work area is on the heap for the call: FATFS holds a sector, 4096 bytes with the panel's CONFIG_FATFS_SECTOR_4096.
| host | The host as the mount had it, SDMMC slot 0. |
| slot | The slot's pins and width as the mount had them. |
| why | Set to the error that kept FatFs from being asked, or ESP_OK. |
why set when FatFs could not be asked: no device, a card that no longer starts, no memory. | void storage_card_name | ( | char * | out, |
| size_t | n ) |
The card's name, into out of n bytes (40 hold every name): its volume label, or the product name in its CID (card identification register) when it has no label. Read once per mount. "" when nothing is mounted. A copy, so that a mount on another task cannot change it under the caller.
| card_state_t storage_card_state | ( | void | ) |
What the slot holds as the last mount or look found it, or CARD_STATE_MOUNTED while a volume is mounted. CARD_STATE_NONE before the first try, after storage_deinit() and for a card found gone. CARD_STATE_UNREADABLE for a card that mounted, answers and fails a read. Lock-free: the control task and every frame may ask.
| card_state_t storage_check | ( | void | ) |
What the slot holds now, at an event that reads the card: LOGS opening, RESCAN, a page of LOGS, a file opened in LOGS, a run's or a servo test's start, the servo programmer looking for its card. Not once a frame.
A mounted volume is asked whether its card still answers: one SEND_STATUS (CMD13) command through FatFs. A card that does not is taken out or swapped; the volume is let go and the slot mounted again, so the volume label, the list and the run alerts are the card's in the slot now. Held (storage_hold()), the volume is let go at the last release instead, and reads as no card until the next call. An empty slot or one whose card did not mount is tried again. ESP-IDF's E lines for a card that is not there are quiet for the call; the outcome is one I or W line of its own.
| const char * storage_drive | ( | void | ) |
The FatFs drive of the mounted volume, "0:", or "" with none. Read under a hold (storage_hold()), which keeps it from changing.
| int storage_fclose | ( | FILE * | f | ) |
fclose() of a storage_fopen() file, and its hold given back. The close is made also on a card found gone: FatFs refuses it without card traffic, and the handle and its descriptor are freed.
| FILE * storage_fopen | ( | const char * | path, |
| const char * | mode ) |
fopen() under a hold that the file keeps until storage_fclose(); NULL, with no hold kept, when nothing is mounted or the open fails.
| bool storage_hold | ( | void | ) |
Keep the mounted volume from being let go: around every path call (fopen(), stat(), mkdir(), unlink(), rename(), opendir()) and for as long as a file or folder stays open. Counted; every true is matched by one storage_release().
| bool storage_hold_mount | ( | unsigned | mount | ) |
storage_hold() of the volume of mount mount (storage_mount_count()) only: false once another volume is mounted, so a name read from one card is not opened or deleted on the next.
| esp_err_t storage_init | ( | void | ) |
Switch the card's supply on and mount the card at /sdcard.
Never formats. A card that starts and does not mount is looked at once more, so storage_card_state() can tell a card with no FAT (File Allocation Table) volume from one that fails another way. The first call makes the lock every other call takes: the start-up's, on app_main, before any task that reaches the card exists.
| unsigned storage_mount_count | ( | void | ) |
The mounts that worked since the start: another number after a storage_check() is another volume, the same card's or a new one's. Lock-free.
| bool storage_mounted | ( | void | ) |
A volume is mounted and its card was not found gone. Lock-free.
| bool storage_read_end | ( | int | fr, |
| const char * | how, | ||
| bool | may_mount ) |
The end of a read made under storage_hold(): the hold given back, and the read's FatFs answer fr (0 for one that worked) weighed. A failure that says the card is gone lets the volume go (storage_walk() says how); how names the read in the log line. With may_mount, a volume let go with nothing else holding it is mounted again once.
| void storage_release | ( | void | ) |
The end of a storage_hold() that answered true. The last release of a volume whose card was found gone lets the volume go.
| const char * storage_status | ( | void | ) |
What went wrong, in a few words for the console and the start-up line: "no card", "no FAT volume", "FatFs <n>", "LDO <error>" or ESP-IDF's error name. "" when all is well. At most 47 characters.
| uint64_t storage_total_bytes | ( | void | ) |
Card size and free space in bytes; 0 when nothing is mounted.
|
static |
Let the volume go, under s.lock, with nothing holding it.
No card traffic: f_mount(NULL) forgets the volume without writing, and the slot is let go. The SDMMC host stays up: the radio's slot 1 shares it.