2. MMC驱动核心数据结构
在ARM架构下,MMC(MultiMediaCard)块设备驱动的核心由四个关键数据结构支撑:struct mmc_host(主机控制器)、struct mmc_card(卡设备)、struct mmc_request(请求)和struct mmc_command(命令)。理解这些结构的字段含义与相互关系,是进行参数配置与性能调优的基础。
学习提示: 这四个结构体构成了MMC子系统的“四层模型”——主机层、卡管理层、请求层、命令层。调优时,80%的参数修改集中在
mmc_host 和 mmc_request 中。
2.1 struct mmc_host:主机控制器抽象
struct mmc_host 代表一个MMC/SD/SDIO主机控制器实例,是驱动与硬件交互的桥梁。其关键字段按功能分为三类:硬件能力、运行时状态、调优参数。
| 字段名 | 类型 | 功能描述 | 调优关注点 |
|---|---|---|---|
f_min / f_max |
unsigned int | 主机支持的时钟频率范围(Hz) | 决定传输速率上限,ARM平台通常f_max=50MHz(HS模式)或200MHz(UHS-II) |
caps / caps2 |
unsigned int | 主机能力位掩码(如MMC_CAP_4_BIT_DATA、MMC_CAP_UHS) | 开启4位/8位总线、DDR模式、UHS-I等能力 |
ocr_avail |
u32 | 可用操作电压范围(如3.3V、1.8V) | 低电压模式(1.8V)可降低功耗但需硬件支持 |
max_blk_count / max_blk_size |
unsigned int | 单次请求最大块数(通常65535)和块大小(512字节) | 增大块数可提升顺序读写吞吐 |
max_req_size |
unsigned int | 单次请求最大数据字节数 | 受DMA引擎限制,ARM平台常见1MB~4MB |
pm_caps |
unsigned int | 电源管理能力(如MMC_PM_KEEP_POWER) | 休眠唤醒策略影响响应延迟 |
ARM平台实战: 在i.MX8M或RK3588平台上,
caps 字段必须设置 MMC_CAP_8_BIT_DATA | MMC_CAP_UHS_SDR104 才能发挥eMMC 5.1的HS400性能。若未配置,驱动会降级至4位SD模式,吞吐量下降60%。
2.2 struct mmc_card:卡设备描述
struct mmc_card 描述一个已初始化的MMC/SD卡或eMMC设备。它包含卡的标识信息、几何参数和运行时状态。
| 字段名 | 类型 | 说明 | 典型值/作用 |
|---|---|---|---|
host |
struct mmc_host * | 指向所属主机控制器 | 双向关联,用于回调 |
rca |
unsigned int | 相对卡地址(Relative Card Address) | CMD3分配,用于后续命令寻址 |
type |
enum mmc_card_type | 卡类型(MMC、SD、SDIO等) | 决定协议分支 |
csd / cid / ext_csd |
struct mmc_* | 卡描述寄存器、识别寄存器、扩展寄存器 | ext_csd[DEVICE_LIFE_TIME] 可监控eMMC寿命 |
erase_size |
unsigned int | 擦除块大小(扇区数) | eMMC典型值512KB~8MB,影响TRIM性能 |
pref_erase |
unsigned int | 首选擦除大小 | 文件系统对齐时使用 |
quirks |
u32 | 卡特定兼容性修正位 | 如MMC_QUIRK_BROKEN_IRQ_POLL |
避坑指南:
ext_csd 中的 DEVICE_LIFE_TIME_EST_TYP 和 PRE_EOL_INFO 字段是判断eMMC健康状态的关键。在ARM嵌入式设备中,建议每1000小时读取一次,提前预警存储介质老化。
2.3 struct mmc_request:请求封装
struct mmc_request 封装一次完整的MMC总线事务,包含一个或多个命令以及可选的数据传输。它是块设备层与MMC核心层之间的传输单元。
| 字段名 | 类型 | 说明 | 性能影响 |
|---|---|---|---|
cmd |
struct mmc_command * | 主命令(如CMD18读多块) | 决定操作类型 |
sbc |
struct mmc_command * | 设置块计数命令(CMD23) | 开启CMD23可减少总线开销 |
stop |
struct mmc_command * | 停止传输命令(CMD12) | 多块传输结束必须 |
data |
struct mmc_data * | 数据传输描述符(sg表、块数、方向) | sg表长度影响DMA效率 |
done |
void (*)(struct mmc_request *) | 请求完成回调函数 | 回调延迟影响IO栈响应 |
cap_cmd_during_tfr |
bool | 是否支持传输中执行命令 | CMD42(安全写)可并发 |
性能调优关键:
sbc(CMD23)的使用是MMC高性能的关键。当 mmc_request 包含 sbc 时,驱动会发送“预置块计数”命令,避免多块传输后发送CMD12,减少约20%的命令开销。在顺序读写场景下,务必确保 MMC_CAP_CMD23 能力位已设置。
2.4 struct mmc_command:命令细节
struct mmc_command 描述一条具体的MMC总线命令,包括命令索引、参数、响应类型和超时设置。它是MMC协议的最小执行单元。
| 字段名 | 类型 | 说明 | 典型值/注意事项 |
|---|---|---|---|
opcode |
u32 | 命令索引(0~63) | 如CMD0=GO_IDLE_STATE, CMD6=SWITCH |
arg |
u32 | 命令参数(32位) | 如CMD6的arg决定访问模式和寄存器 |
resp[4] |
u32 | 响应数据(最多128位) | R1/R2/R3/R4/R5类型不同 |
flags |
u32 | 命令属性(方向、响应类型、CRC使能等) | 使用 MMC_CMD_AC / MMC_CMD_ADTC 等宏 |
error |
int | 命令执行错误码 | 0=成功,-ETIMEDOUT=超时,-EILSEQ=CRC错误 |
retries |
unsigned int | 命令重试次数 | 默认3次,调优时可改为5次以增强稳定性 |
busy_timeout |
unsigned int | 忙等待超时(ms) | 擦除类命令需设置较大值(如500ms) |
mrq |
struct mmc_request * | 指向所属请求 | 用于回调时获取上下文 |
调试要点: 当遇到“mmc0: Timeout waiting for hardware interrupt”错误时,首先检查
busy_timeout 是否设置过小。对于eMMC的擦除/TRIM操作,建议设置为1000ms以上。同时检查 error 字段的返回值,-110表示超时,-84表示CRC校验失败(通常需要重新调优)。
2.5 四结构体协作关系总结
四个核心数据结构在MMC驱动中的协作关系可以概括为:mmc_host 管理硬件资源,mmc_card 描述卡设备属性,mmc_request 组织一次完整事务,mmc_command 执行具体协议命令。块设备层通过 mmc_blk_data 将bio请求转换为 mmc_request,最终由主机控制器驱动完成物理传输。
调优总结:
- 吞吐量优先: 增大
mmc_host.max_blk_count和max_req_size,开启MMC_CAP_CMD23和MMC_CAP_8_BIT_DATA。 - 延迟优先: 减小
mmc_request的数据块数,使用MMC_CAP_SDIO_IRQ实现中断驱动。 - 稳定性优先: 增大
mmc_command.retries至5次,设置合理的busy_timeout,并定期检查mmc_card.ext_csd健康状态。