总体控制流:Host 中断 -> 扫描频率 -> SD专属协议握手 -> 加网注册
第一阶段:探测流 (Detect Phase)
- 热插拔触发 (
mmc_rescan) : 大部分 SD 卡槽带有Card Detect (CD)引脚。当物理插入动作发生时,底层主机控制器(如sdhci)产生中断,唤醒系统工作队列host->detect执行mmc_rescan函数。 - 安全初始环境准备 : 在
mmc_rescan中,主机控制器会首先给 SD 卡加电并以较低的频率启动轮询。因为所有的 SD 卡在刚插入时强制要求以规范定义的低速进入。它调用mmc_rescan_try_freq(host, freq),通常以 400KHz 开始盲探。 - SD专属协议试探 (
mmc_attach_sd) : 在mmc_rescan_try_freq内部:- 先发送
CMD0(GO_IDLE_STATE) 让所有卡软复位。 - 跳过 SDIO 探测(如果
CMD5无响应)。 - SD 卡的关键试探 :紧接着发送
CMD8(SEND_IF_COND) 测试电压兼容性(识别 SD 2.0+ 标志)。 - 身份最终确认 :由探测转入实质依附过程,调用
mmc_attach_sd(host)。
- 先发送
第二阶段:上电协商与初始化 (Power Up & Init Phase)
在 SD 卡的体系中,上电不再是一次性的拉高电平就结束了,而是涉及到复杂的 UHS-I 超高速卡 1.8V 降压切换以及调谐(Tuning)。这是 Kernel 5.10 中 SD 驱动最精华的部分。
-
操作条件查询与初始供电 (
mmc_send_app_op_cond/mmc_power_up) : 在mmc_attach_sd起始阶段,系统发送CMD55 + ACMD41(APP_SEND_OP_COND) 命令不断轮询。这不仅仅是检测,同时也在查询卡的可用电压窗口(OCR,Operation Conditions Register)。 只要卡在这个环节宣告 Ready,主机就会依据返回的 OCR 锁定工作电压,通过mmc_power_up(host, ocr)调用底层的寄存器(set_ios)把芯片对应的 VDD 管脚真正上电稳定。 -
核心状态机拉升 (
mmc_sd_init_card): 由于电压稳了,系统真正开始解析 SD 卡,进行一系列经典的协议流动作:CMD2(ALL_SEND_CID):获取这小板子的出厂身份码,比如闪迪还是金士顿、生产年月。CMD3(SEND_RELATIVE_ADDR):SD卡与 eMMC 不同,系统会要求 SD 卡自己汇报一个相对地址 (RCA)。之后所有通信基于此地址进行。CMD9(SEND_CSD):获取卡的核心特征,最主要的是算出这卡到底有多少 GB 容量。CMD7(SELECT_CARD):拿着刚才得到的 RCA 地址,正式选中这张卡。至此,SD 卡从"待机态(Standby)"完全进入了"传输态(Transfer State)"。CMD8(APP_SEND_SCR):读取配置寄存器,获知卡支持的特性配置。
-
UHS-I 电压切换与调谐 (Voltage Switch & Tuning): 如果是高速 SD 卡(如 U1, U3 规格):
- 主机通过
CMD11(VOLTAGE_SWITCH) 提示卡。 - 随即底层控制器把 VCCQ 引脚由 3.3V "热切换" 降维至 1.8V(这是保证高频运转不发热不失真的硬件门槛)。
- 若进入 SDR50 / SDR104 高速模式,还会调用
mmc_execute_tuning()连续发送特制波形来测算当前温度和电路阻抗下的最佳时钟采样延时点。
- 主机通过
第三阶段:注册投轨向 Linux 报到 (Add Card Phase)
当所有的初始化和降压提速动作跑完后,代码流返回到了最上层的业务归口。
- 实体建立 (
mmc_add_card) : 执行err = mmc_add_card(host->card);。在core/bus.c中,把前面各种繁杂步骤获得的信息(CID,容量,速率,只读状态等)打包,以此为蓝本作为一个struct device实体注入到庞大的 Linux 设备树字典中。 - 通报 Block 层 : 随着
device_add的内部广播,一直监视着 MMC 总线的虚拟块设备驱动block.c闻风而动。 - 暴露存储空间 (
mmc_blk_probe) : 由于前面的协商结果毫无瑕疵,块驱动终于放心地执行alloc_disk()并创建/dev/mmcblkX。 紧接着内核的通用分区代码会自动去读这张卡的第 0 扇区(也就是 MBR / GPT 所在处),识别到 FAT32/ext4 等文件系统布局并抛出如/dev/mmcblkXp1等设备接口,最终 udev 层面可借此自动挂载您的 SD 卡卷标至/mnt或/media内。
关键代码追踪锚点总结
如果在 Kernel 5.10 排查 SD 卡挂载失败的问题,可以顺着以下锚点顺藤摸瓜:
- 卡槽没反应 :查中断触发、GPIO配置、或
host.c的mmc_rescan延时队列是否被屏蔽。 - 提示超时或电压不匹配
-EINVAL:在mmc_attach_sd()的ACMD41阶段出问题了,重点看核心板的供电引脚实际电压输出能力与设备树描述是否一致(即 Regulator 稳压器设错了)。 -EILSEQ(信号调谐失败) 或者降速警告 :重点看mmc_sd_init_card()中段的电压切换CMD11和之后的mmc_execute_tuning()过程。- 出现写保护 / 不能读 :查看
slot-gpio.c中对卡槽旁边的物理 WP (Write Protect) 小拨钮管脚映射。