Skip to content

Commit 767f8ed

Browse files
author
Liu Jinhong
committed
feat(esp_board_manager): Add SDSPI SD card support to esp_board_manager
1 parent a0f2682 commit 767f8ed

File tree

14 files changed

+407
-32
lines changed

14 files changed

+407
-32
lines changed

packages/esp_board_manager/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ When multiple boards with the same name exist across different paths, the ESP Bo
358358
| LCD Display | display_lcd_spi | ST77916/GC9A01 | spi | ✅ Supported | SPI LCD display | [`dev_display_lcd_spi.yaml`](devices/dev_display_lcd_spi/dev_display_lcd_spi.yaml) |
359359
| Touch Screen | lcd_touch_i2c | FT5x06 | i2c | ✅ Supported | I2C touch screen | [`dev_lcd_touch_i2c.yaml`](devices/dev_lcd_touch_i2c/dev_lcd_touch_i2c.yaml) |
360360
| SD Card | fatfs_sdcard | - | sdmmc | ✅ Supported | SD card storage | [`dev_fatfs_sdcard.yaml`](devices/dev_fatfs_sdcard/dev_fatfs_sdcard.yaml) |
361+
| SPI SD Card | fatfs_sdcard_spi | - | spi | ✅ Supported | SD card storage | [`dev_fatfs_sdcard_spi.yaml`](devices/dev_fatfs_sdcard_spi/dev_fatfs_sdcard_spi.yaml) |
361362
| SPIFFS Filesystem | fs_spiffs | - | - | ✅ Supported | SPIFFS filesystem | [`dev_fs_spiffs.yaml`](devices/dev_fs_spiffs/dev_fs_spiffs.yaml) |
362363
| GPIO Control | gpio_ctrl | - | gpio | ✅ Supported | GPIO control device | [`dev_gpio_ctrl.yaml`](devices/dev_gpio_ctrl/dev_gpio_ctrl.yaml) |
363364
| LEDC Control | ledc_ctrl | - | ledc | ✅ Supported | LEDC control device | [`dev_ledc_ctrl.yaml`](devices/dev_ledc_ctrl/dev_ledc_ctrl.yaml) |

packages/esp_board_manager/README_CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ ESP Board Manager 支持通过三个不同的路径位置进行板级配置,
358358
| LCD 显示屏 | display_lcd_spi | ST77916/GC9A01 | spi | ✅ 支持 | SPI LCD 显示屏 | [`dev_display_lcd_spi.yaml`](devices/dev_display_lcd_spi/dev_display_lcd_spi.yaml) |
359359
| 触摸屏 | lcd_touch_i2c | FT5x06 | i2c | ✅ 支持 | I2C 触摸屏 | [`dev_lcd_touch_i2c.yaml`](devices/dev_lcd_touch_i2c/dev_lcd_touch_i2c.yaml) |
360360
| SD 卡 | fatfs_sdcard | - | sdmmc | ✅ 支持 | SD 卡存储 | [`dev_fatfs_sdcard.yaml`](devices/dev_fatfs_sdcard/dev_fatfs_sdcard.yaml) |
361+
| SPI SD 卡 | fatfs_sdcard_spi | - | spi | ✅ 支持 | SD 卡存储 | [`dev_fatfs_sdcard_spi.yaml`](devices/dev_fatfs_sdcard_spi/dev_fatfs_sdcard_spi.yaml) |
361362
| SPIFFS 文件系统 | fs_spiffs | - | - | ✅ 支持 | SPIFFS 文件系统 | [`dev_fs_spiffs.yaml`](devices/dev_fs_spiffs/dev_fs_spiffs.yaml) |
362363
| GPIO 控制 | gpio_ctrl | - | gpio | ✅ 支持 | GPIO 控制设备 | [`dev_gpio_ctrl.yaml`](devices/dev_gpio_ctrl/dev_gpio_ctrl.yaml) |
363364
| LEDC 控制 | ledc_ctrl | - | ledc | ✅ 支持 | LEDC 控制设备 | [`dev_ledc_ctrl.yaml`](devices/dev_ledc_ctrl/dev_ledc_ctrl.yaml) |

packages/esp_board_manager/boards/esp32_s3_korvo2_v3/board_devices.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ devices:
5959
config:
6060
bus_width: 1 # 1, 4, 8, not used on SPI type
6161
pins:
62-
clk: 15 # GPIO_NUM_15
63-
cmd: 7 # GPIO_NUM_7
64-
d0: 4 # GPIO_NUM_4
65-
62+
clk: 15 # GPIO_NUM_15
63+
cmd: 7 # GPIO_NUM_7
64+
d0: 4 # GPIO_NUM_4
65+
6666
- name: gpio_expander
6767
chip: tca9554
6868
type: gpio_expander

packages/esp_board_manager/boards/lyrat_mini_v1_1/board_devices.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ devices:
99
config:
1010
bus_width: 1 # 1, 4, 8, not used on SPI type
1111
pins:
12-
clk: 15 # GPIO_NUM_15
12+
clk: 15 # GPIO_NUM_15
1313
cmd: 7 # GPIO_NUM_7
14-
d0: 4 # GPIO_NUM_4
14+
d0: 4 # GPIO_NUM_4
1515

packages/esp_board_manager/devices/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ function(get_device_sources sources includes)
5252
list(APPEND srcs "${CMAKE_CURRENT_LIST_DIR}/devices/dev_camera/dev_camera.c")
5353
list(APPEND incs "${CMAKE_CURRENT_LIST_DIR}/devices/dev_camera")
5454
endif()
55+
56+
if(CONFIG_ESP_BOARD_DEV_FATFS_SDCARD_SPI_SUPPORT)
57+
list(APPEND srcs "${CMAKE_CURRENT_LIST_DIR}/devices/dev_fatfs_sdcard_spi/dev_fatfs_sdcard_spi.c")
58+
list(APPEND incs "${CMAKE_CURRENT_LIST_DIR}/devices/dev_fatfs_sdcard_spi")
59+
endif()
5560

5661
# Set output variables in parent scope
5762
set(${sources} ${srcs} PARENT_SCOPE)

packages/esp_board_manager/devices/dev_fatfs_sdcard/dev_fatfs_sdcard.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,33 +77,39 @@ int dev_fatfs_sdcard_init(void *cfg, int cfg_size, void **device_handle)
7777
&mount_config, &handle->card);
7878
if (ret != ESP_OK) {
7979
ESP_LOGE(TAG, "Failed to mount filesystem");
80-
free(handle);
81-
return -1;
80+
goto cleanup;
8281
}
8382

8483
// Save mount point
8584
handle->mount_point = strdup(config->mount_point);
8685
if (handle->mount_point == NULL) {
8786
ESP_LOGE(TAG, "Failed to allocate mount point");
8887
esp_vfs_fat_sdcard_unmount(config->mount_point, handle->card);
89-
free(handle);
90-
return -1;
88+
goto cleanup;
9189
}
9290

9391
ESP_LOGI(TAG, "Filesystem mounted, base path: %s", config->mount_point);
9492
*device_handle = handle;
9593
return 0;
94+
cleanup:
95+
free(handle);
96+
return -1;
9697
}
9798

9899
int dev_fatfs_sdcard_deinit(void *device_handle)
99100
{
100101
if (device_handle == NULL) {
102+
ESP_LOGE(TAG, "Invalid parameters");
101103
return -1;
102104
}
103105

104106
dev_fatfs_sdcard_handle_t *handle = (dev_fatfs_sdcard_handle_t *)device_handle;
105-
esp_vfs_fat_sdcard_unmount(handle->mount_point, handle->card);
106-
free(handle->mount_point);
107+
if (handle->mount_point && handle->mount_point[0] && handle->card) {
108+
esp_vfs_fat_sdcard_unmount(handle->mount_point, handle->card);
109+
} else {
110+
ESP_LOGW(TAG, "Mount point or card handle is NULL, skipping unmount");
111+
}
112+
free((char *)handle->mount_point);
107113
free(handle);
108114
return 0;
109115
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
3+
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
4+
*
5+
* See LICENSE file for details.
6+
*/
7+
8+
#include <string.h>
9+
#include "esp_log.h"
10+
#include "esp_vfs_fat.h"
11+
#include "periph_spi.h"
12+
#include "dev_fatfs_sdcard_spi.h"
13+
14+
static const char *TAG = "DEV_FATFS_SDCARD_SPI";
15+
16+
int dev_fatfs_sdcard_spi_init(void *cfg, int cfg_size, void **device_handle)
17+
{
18+
if (cfg == NULL || device_handle == NULL) {
19+
ESP_LOGE(TAG, "Invalid parameters");
20+
return -1;
21+
}
22+
if (cfg_size != sizeof(dev_fatfs_sdcard_spi_config_t)) {
23+
ESP_LOGE(TAG, "Invalid config size");
24+
return -1;
25+
}
26+
27+
const dev_fatfs_sdcard_spi_config_t *config = (const dev_fatfs_sdcard_spi_config_t *)cfg;
28+
periph_spi_handle_t *spi_handle = NULL;
29+
if (config->spi_bus_name && config->spi_bus_name[0]) {
30+
int ret = esp_board_periph_get_handle(config->spi_bus_name, (void **)&spi_handle);
31+
if (ret != 0) {
32+
ESP_LOGE(TAG, "Failed to get SPI peripheral handle: %d", ret);
33+
return -1;
34+
}
35+
} else {
36+
ESP_LOGE(TAG, "Invalid SPI bus name");
37+
return -1;
38+
}
39+
40+
esp_err_t ret = 0;
41+
dev_fatfs_sdcard_spi_handle_t *handle = (dev_fatfs_sdcard_spi_handle_t *)calloc(1, sizeof(dev_fatfs_sdcard_spi_handle_t));
42+
if (handle == NULL) {
43+
ESP_LOGE(TAG, "Failed to allocate memory");
44+
return -1;
45+
}
46+
47+
// Use SDSPI host
48+
handle->host = (sdmmc_host_t)SDSPI_HOST_DEFAULT();
49+
handle->host.max_freq_khz = config->frequency;
50+
handle->host.slot = spi_handle->spi_port;
51+
52+
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
53+
slot_config.gpio_cs = config->cs_gpio_num;
54+
slot_config.host_id = handle->host.slot;
55+
esp_vfs_fat_mount_config_t mount_config = {
56+
.format_if_mount_failed = config->vfs_config.format_if_mount_failed,
57+
.max_files = config->vfs_config.max_files,
58+
.allocation_unit_size = config->vfs_config.allocation_unit_size,
59+
};
60+
61+
ESP_LOGD(TAG, "host: flags=0x%" PRIx32 ", slot=%d, max_freq_khz=%d, io_voltage=%.1f, command_timeout_ms=%d",
62+
handle->host.flags, handle->host.slot, handle->host.max_freq_khz, handle->host.io_voltage, handle->host.command_timeout_ms);
63+
ESP_LOGI(TAG, "slot_config: host_id=%d, gpio_cs=%d", slot_config.host_id, slot_config.gpio_cs);
64+
ESP_LOGD(TAG, "mount_config: format_if_mount_failed=%d, max_files=%d, allocation_unit_size=%d",
65+
mount_config.format_if_mount_failed, mount_config.max_files, mount_config.allocation_unit_size);
66+
67+
ESP_LOGI(TAG, "Mounting filesystem");
68+
ret = esp_vfs_fat_sdspi_mount(config->mount_point, &handle->host, &slot_config, &mount_config, &handle->card);
69+
if (ret != ESP_OK) {
70+
ESP_LOGE(TAG, "Failed to mount filesystem");
71+
goto cleanup;
72+
}
73+
74+
// Save mount point
75+
handle->mount_point = strdup(config->mount_point);
76+
if (handle->mount_point == NULL) {
77+
ESP_LOGE(TAG, "Failed to allocate mount point");
78+
esp_vfs_fat_sdcard_unmount(config->mount_point, handle->card);
79+
goto cleanup;
80+
}
81+
82+
ESP_LOGI(TAG, "Filesystem mounted, base path: %s", config->mount_point);
83+
*device_handle = handle;
84+
85+
sdmmc_card_print_info(stdout, (sdmmc_card_t *)*device_handle);
86+
return 0;
87+
cleanup:
88+
free(handle);
89+
return -1;
90+
}
91+
92+
int dev_fatfs_sdcard_spi_deinit(void *device_handle)
93+
{
94+
if (device_handle == NULL) {
95+
ESP_LOGE(TAG, "Invalid parameters");
96+
return -1;
97+
}
98+
99+
dev_fatfs_sdcard_spi_handle_t *handle = (dev_fatfs_sdcard_spi_handle_t *)device_handle;
100+
if (handle->mount_point && handle->mount_point[0] && handle->card) {
101+
esp_vfs_fat_sdcard_unmount(handle->mount_point, handle->card);
102+
} else {
103+
ESP_LOGW(TAG, "Mount point or card handle is NULL, skipping unmount");
104+
}
105+
free((char *)handle->mount_point);
106+
free(handle);
107+
return 0;
108+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO., LTD
3+
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
4+
*
5+
* See LICENSE file for details.
6+
*/
7+
8+
#pragma once
9+
10+
#include "sdmmc_cmd.h"
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif /* __cplusplus */
15+
16+
/**
17+
* @brief SPI SD card handle structure
18+
* This structure contains the handle for the SPI SD card device, including the card, host, and mount point
19+
*/
20+
typedef struct {
21+
sdmmc_card_t *card; /*!< SPI SD card card handle */
22+
sdmmc_host_t host; /*!< SPI SD card host handle */
23+
const char *mount_point; /*!< Mount point path */
24+
} dev_fatfs_sdcard_spi_handle_t;
25+
26+
/**
27+
* @brief SPI SD card VFS (Virtual File System) configuration structure
28+
*/
29+
typedef struct {
30+
bool format_if_mount_failed; /*!< Format the card if mount fails */
31+
uint16_t max_files; /*!< Maximum number of files that can be open simultaneously */
32+
uint16_t allocation_unit_size; /*!< Allocation unit size in bytes */
33+
} dev_sdcard_spi_vfs_config_t;
34+
35+
/**
36+
* @brief SPI SD card configuration structure
37+
*
38+
* This structure contains the configuration parameters needed to initialize
39+
* an SPI SD card device, including the name, mount point, frequency, VFS configuration,
40+
* and sub-type-specific configuration.
41+
*/
42+
typedef struct {
43+
const char *name;
44+
const char *mount_point; /*!< Mount point path */
45+
uint32_t frequency; /*!< SPI SD card clock frequency in Hz */
46+
dev_sdcard_spi_vfs_config_t vfs_config; /*!< VFS configuration */
47+
int cs_gpio_num; /*!< Chip select GPIO number */
48+
const char *spi_bus_name; /*!< SPI bus name */
49+
} dev_fatfs_sdcard_spi_config_t;
50+
51+
/**
52+
* @brief Initialize SPI SD card device
53+
*
54+
* This function initializes an SPI SD card device using the provided configuration structure.
55+
* It mounts the SPI SD card to the specified mount point and sets up the VFS interface.
56+
*
57+
* @param[in] cfg Pointer to the SPI SD card configuration structure
58+
* @param[in] cfg_size Size of the configuration structure
59+
* @param[out] device_handle Pointer to a variable to receive the dev_fatfs_sdcard_spi_handle_t handle
60+
*
61+
* @return
62+
* - 0 On success
63+
* - Negative value On failure
64+
*/
65+
int dev_fatfs_sdcard_spi_init(void *cfg, int cfg_size, void **device_handle);
66+
67+
/**
68+
* @brief Deinitialize SPI SD card device
69+
*
70+
* This function deinitializes the SPI SD card device and unmounts it from the VFS.
71+
* It should be called when the device is no longer needed.
72+
*
73+
* @param[in] device_handle Pointer to the device handle to be deinitialized
74+
*
75+
* @return
76+
* - 0 On success
77+
* - Negative value On failure
78+
*/
79+
int dev_fatfs_sdcard_spi_deinit(void *device_handle);
80+
81+
#ifdef __cplusplus
82+
}
83+
#endif /* __cplusplus */

0 commit comments

Comments
 (0)