drfhaust/sd-card

1.0.0

Latest
uploaded 3 hours ago
SD Card driver for ESP-IDF supporting SDIO and SPI modes with hot-plug detection

readme

# SD Card Component for ESP-IDF

Simple SD card driver supporting both SDIO and SPI modes with hot-plug detection.

## Features

- **SDIO mode**: 4-bit and 1-bit modes
- **SPI mode**: For boards without SDIO, supports external SPI bus
- **Hot-plug detection**: Optional card detect GPIO with callbacks
- **Space monitoring**: Track total/free/used space
- **Simple file API**: Arduino-style wrappers that auto-prepend mount point
- **Error tracking**: Automatic status changes after repeated failures

## Installation

```bash
idf.py add-dependency "drfhaust/sd-card"
```

## Quick Start

### SDIO Mode (Default)

```c
#include "sd_card.h"

void app_main(void)
{
    // Use defaults (SDIO 4-bit mode)
    if (sd_card_init(NULL) == ESP_OK) {
        // Write a file
        FILE *f = sd_fopen("test.txt", "w");
        if (f) {
            fprintf(f, "Hello SD Card!\n");
            sd_fclose(f);
        }
    }
}
```

### SPI Mode

```c
#include "sd_card.h"

void app_main(void)
{
    sd_card_config_t cfg = SD_CARD_SPI_DEFAULT();
    cfg.spi_mosi = 23;
    cfg.spi_miso = 19;
    cfg.spi_clk = 18;
    cfg.spi_cs = 5;

    sd_card_init(&cfg);
}
```

### SPI Mode with External Bus

If you already have an SPI bus configured (e.g., sharing with other devices):

```c
#include "sd_card.h"

void app_main(void)
{
    // Your existing SPI bus init
    spi_bus_config_t bus_cfg = { /* ... */ };
    spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO);

    // Use external SPI bus for SD card
    sd_card_config_t cfg = SD_CARD_SPI_EXTERNAL(SPI2_HOST, GPIO_NUM_5);
    sd_card_init(&cfg);
}
```

### Hot-Plug Detection (Optional)

Hot-plug detection requires `detect_gpio` to be configured. If not set (-1), the card is assumed to be always present.

```c
#include "sd_card.h"

void on_status_change(sd_card_status_t status, void *ctx)
{
    switch (status) {
        case SD_STATUS_AVAILABLE:
            printf("Card ready!\n");
            break;
        case SD_STATUS_NO_CARD:
            printf("Card removed\n");
            break;
        case SD_STATUS_ERROR:
            printf("Card error!\n");
            break;
    }
}

void app_main(void)
{
    sd_card_config_t cfg = SD_CARD_SDIO_DEFAULT();
    cfg.detect_gpio = GPIO_NUM_4;      // Enable hot-plug detection
    cfg.detect_active_low = true;      // LOW = card inserted

    sd_card_on_status_change(on_status_change, NULL);
    sd_card_init(&cfg);

    // Only poll if hot-plug detection is available
    if (sd_card_hotplug_available()) {
        while (1) {
            sd_card_check();  // Handles mount/unmount automatically
            vTaskDelay(pdMS_TO_TICKS(1000));
        }
    }
}
```

## Configuration

### SDIO Configuration

| Field | Description | Default |
|-------|-------------|---------|
| `sdio_clk` | CLK pin | 12 |
| `sdio_cmd` | CMD pin | 11 |
| `sdio_d0` | D0 pin | 13 |
| `sdio_d1` | D1 pin (-1 for 1-bit) | 14 |
| `sdio_d2` | D2 pin (-1 for 1-bit) | 9 |
| `sdio_d3` | D3 pin (-1 for 1-bit) | 10 |

### SPI Configuration

| Field | Description | Default |
|-------|-------------|---------|
| `spi_mosi` | MOSI pin | 23 |
| `spi_miso` | MISO pin | 19 |
| `spi_clk` | CLK pin | 18 |
| `spi_cs` | CS pin | 5 |
| `spi_host` | SPI host (-1 = create new) | -1 |

### Common Options

| Field | Description | Default |
|-------|-------------|---------|
| `detect_gpio` | Card detect pin (-1 = none) | -1 |
| `detect_active_low` | TRUE = LOW when inserted | true |
| `mount_point` | VFS mount path | "/sdcard" |
| `max_files` | Max open files | 5 |
| `freq_khz` | Bus frequency (0 = default) | 0 |

## API Reference

### Initialization

```c
esp_err_t sd_card_init(const sd_card_config_t *config);  // NULL = SDIO defaults
void sd_card_deinit(void);
```

### Status

```c
sd_card_status_t sd_card_get_status(void);  // Current status
bool sd_card_is_available(void);            // Ready for use?
bool sd_card_is_inserted(void);             // Physically inserted?
void sd_card_get_info(sd_card_info_t *info); // Full info
const char *sd_card_get_mount_point(void);  // Get mount path
```

### Hot-Plug (Optional)

```c
bool sd_card_hotplug_available(void); // Check if detect_gpio is configured
bool sd_card_check(void);             // Poll for changes (no-op if no detect pin)
void sd_card_on_status_change(sd_card_callback_t cb, void *ctx);
```

### File Operations

All paths are relative to mount point (auto-prepended):

```c
FILE *sd_fopen(const char *filename, const char *mode);
int sd_fclose(FILE *f);
size_t sd_fwrite(const void *ptr, size_t size, size_t count, FILE *f);
size_t sd_fread(void *ptr, size_t size, size_t count, FILE *f);
int sd_fflush(FILE *f);
int sd_fseek(FILE *f, long offset, int whence);
long sd_ftell(FILE *f);
int sd_remove(const char *filename);
bool sd_exists(const char *filename);
long sd_file_size(const char *filename);
esp_err_t sd_mkdir(const char *path);
```

### Error Tracking

```c
void sd_card_report_fail(void);     // Report failure (3 = error state)
void sd_card_report_success(void);  // Reset failure counter
esp_err_t sd_card_test_write(void); // Test write capability
```

## Status Codes

| Status | Description |
|--------|-------------|
| `SD_STATUS_NO_CARD` | No card detected |
| `SD_STATUS_AVAILABLE` | Card mounted and ready |
| `SD_STATUS_MOUNT_FAIL` | Card detected but mount failed |
| `SD_STATUS_WRITE_FAIL` | Mounted but write test failed |
| `SD_STATUS_ERROR` | Too many consecutive failures |

## License

MIT License - Olaifa Oluwadara Daniel

Links

Maintainer

  • Olaifa Oluwadara Daniel <akolaifa4@gmail.com>

License: MIT

To add this component to your project, run:

idf.py add-dependency "drfhaust/sd-card^1.0.0"

download archive

Stats

  • Archive size
    Archive size ~ 42.51 KB
  • Downloaded in total
    Downloaded in total 0 times
  • Downloaded this version
    This version: 0 times

Badge

drfhaust/sd-card version: 1.0.0
|