SDMMC 驱动
基于 lisa_device 框架的 SDMMC 设备驱动,为 ARCS 平台提供统一的 SD/MMC 存储访问接口。
功能特性
设备支持: 支持 SD/MMC/eMMC 存储卡,自动识别可移除 TF 卡和固定 eMMC 卡
扇区读写: 支持单扇区和多扇区连续读写操作
DMA 优化: 对齐缓冲区直接 DMA 传输,非对齐缓冲区自动使用 wrap buffer 分块传输
参数查询: 获取扇区数量、扇区大小、擦除块大小等磁盘信息
状态管理: 支持探测、状态查询、同步等磁盘管理操作
线程安全: 内部使用互斥锁保护,可在多线程环境中使用
配置选项
在 prj.conf 中启用驱动:
CONFIG_LISA_SDMMC_DEVICE=y # 启用 SDMMC 驱动
可选配置
CONFIG_LISA_SDMMC_INIT_PRIORITY=60 # 设备初始化优先级(默认 60)
CONFIG_LISA_SDMMC_SCAN_TIMEOUT_MS=3000 # 卡扫描超时时间(默认 3000ms)
CONFIG_LISA_SDMMC_ACCESS_BUFFER_ALIGN_SIZE=64 # DMA 缓冲区对齐大小(默认 64 字节)
CONFIG_LISA_SDMMC_ACCESS_WRAP_BUFFER_SIZE=4096 # Wrap 缓冲区大小(默认 4KB)
API 接口
探测与状态接口
int lisa_sdmmc_probe(lisa_device_t *dev);
int lisa_sdmmc_status(lisa_device_t *dev);
探测 SD/MMC 卡并查询磁盘状态。
重要: 必须先调用 lisa_sdmmc_probe() 探测磁盘类型,才能使用下面的功能 API。
数据传输接口
int lisa_sdmmc_read(lisa_device_t *dev, uint8_t *buff, uint32_t sector, uint32_t count);
int lisa_sdmmc_write(lisa_device_t *dev, const uint8_t *buff, uint32_t sector, uint32_t count);
扇区级别的读写操作,支持单扇区和多扇区连续传输。
参数查询接口
int lisa_sdmmc_get_sector_count(lisa_device_t *dev, uint32_t *sector_count);
int lisa_sdmmc_get_sector_size(lisa_device_t *dev, uint32_t *sector_size);
获取磁盘容量信息。
控制接口
int lisa_sdmmc_ioctl(lisa_device_t *dev, uint8_t cmd, void *buff);
int lisa_sdmmc_sync(lisa_device_t *dev);
通用 IOCTL 控制接口和缓存同步接口。
使用示例
基本读写操作
#include "lisa_sdmmc.h"
// 1. 获取磁盘设备
lisa_device_t *sdmmc = lisa_device_get("sdmmc0");
if (!sdmmc) {
return -1;
}
// 2. 探测 SD/MMC 卡
int ret = lisa_sdmmc_probe(sdmmc);
if (ret != LISA_DEVICE_OK) {
return ret;
}
// 3. 检查磁盘状态
if (lisa_sdmmc_status(sdmmc) != LISA_SDMMC_STATUS_OK) {
return -1;
}
// 4. 获取磁盘信息
uint32_t sector_count, sector_size;
lisa_sdmmc_get_sector_count(sdmmc, §or_count);
lisa_sdmmc_get_sector_size(sdmmc, §or_size);
// 5. 读取扇区
uint8_t buffer[512] __attribute__((aligned(64))); // 建议 64 字节对齐
ret = lisa_sdmmc_read(sdmmc, buffer, 0, 1);
if (ret != LISA_DEVICE_OK) {
// 处理错误
}
// 6. 写入扇区
ret = lisa_sdmmc_write(sdmmc, buffer, 0, 1);
if (ret != LISA_DEVICE_OK) {
// 处理错误
}
多扇区操作
// 读取多个连续扇区
#define SECTOR_COUNT 8
uint8_t large_buffer[512 * SECTOR_COUNT] __attribute__((aligned(64)));
// 从扇区 100 开始读取 8 个扇区
ret = lisa_sdmmc_read(sdmmc, large_buffer, 100, SECTOR_COUNT);
if (ret == LISA_DEVICE_OK) {
// 处理读取的数据
}
// 写入多个连续扇区
ret = lisa_sdmmc_write(sdmmc, large_buffer, 100, SECTOR_COUNT);
if (ret == LISA_DEVICE_OK) {
// 写入成功
}
使用 IOCTL 查询磁盘参数
// 获取擦除块大小
uint32_t erase_block_size;
ret = lisa_sdmmc_ioctl(sdmmc, LISA_SDMMC_IOCTL_GET_ERASE_BLOCK_SZ, &erase_block_size);
if (ret == LISA_DEVICE_OK) {
// 使用擦除块大小
}
// 同步缓存到磁盘
ret = lisa_sdmmc_sync(sdmmc);
// 或使用 IOCTL 方式
ret = lisa_sdmmc_ioctl(sdmmc, LISA_SDMMC_IOCTL_CTRL_SYNC, NULL);
硬件配置
引脚复用配置
SDMMC 驱动在初始化时会自动调用板型目录中定义的 lisa_sdmmc_pinmux() 函数,用于配置 SDMMC 设备的引脚复用。
配置位置:
定义:
boards/<板型名>/pinmux.c中实现lisa_sdmmc_pinmux()函数声明:
boards/<板型名>/pinmux.h中声明void lisa_sdmmc_pinmux()调用时机: SDMMC 设备初始化时自动调用
示例 (参考 boards/arcs_evb/pinmux.c):
void lisa_sdmmc_pinmux()
{
// CLK: PA6 功能 15
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 6, CSK_IOMUX_FUNC_ALTER15);
// CMD: PA7 功能 15
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 7, CSK_IOMUX_FUNC_ALTER15);
// DAT0: PA5 功能 15
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 5, CSK_IOMUX_FUNC_ALTER15);
// DAT1: PA4 功能 15
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 4, CSK_IOMUX_FUNC_ALTER15);
// DAT2: PA9 功能 15
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 9, CSK_IOMUX_FUNC_ALTER15);
// DAT3: PA8 功能 15
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 8, CSK_IOMUX_FUNC_ALTER15);
}
注意:
该函数由板型相关代码实现,不同板型的引脚配置可能不同
SDMMC 需要配置 6 个引脚:CLK、CMD、DAT0-DAT3
引脚功能码需参考芯片手册的引脚复用表
IOCTL 命令
命令 |
说明 |
buff 参数 |
|---|---|---|
|
同步缓存到磁盘 |
NULL |
|
获取扇区总数 |
|
|
获取扇区大小 |
|
|
获取擦除块大小 |
|
磁盘状态
状态 |
值 |
说明 |
|---|---|---|
|
0 |
磁盘就绪 |
|
1 |
磁盘未初始化 |
|
2 |
磁盘忙 |
|
3 |
无存储介质 |
注意事项
初始化顺序: 必须先调用
lisa_sdmmc_probe()探测磁盘类型,才能进行读写操作状态检查: 读写前应调用
lisa_sdmmc_status()确认磁盘状态为LISA_SDMMC_STATUS_OK缓冲区对齐: 为获得最佳性能,建议使用 64 字节对齐的缓冲区(
__attribute__((aligned(64))))。非对齐缓冲区会自动使用 wrap buffer 分块传输,性能略有下降扇区大小: 标准扇区大小为 512 字节,建议使用
lisa_sdmmc_get_sector_size()动态获取扇区范围: 写入前应确认扇区号在有效范围内(0 到 sector_count-1),避免数据损坏
文件系统兼容: 如果使用文件系统(如 FAT32),避免直接操作文件系统占用的扇区
线程安全: 驱动内部使用互斥锁保护,可在多线程环境下安全使用
错误处理: 所有 API 返回
LISA_DEVICE_OK(0) 表示成功,负值表示错误,应检查返回值卡检测: 对于可移除 TF 卡,移除后需重新调用
lisa_sdmmc_probe()重新初始化数据同步: 重要数据写入后建议调用
lisa_sdmmc_sync()确保数据已刷新到存储介质