先感谢下<linux系统移植>这本书的作者,因为基本原理的了解都来自它。
在测试移远的内核时发现居然无法在开机后自动识别SD卡。我这就纳闷了,于是去找原因。
一.先了解SD卡的基本原理
1.了解SD卡的读写、容量、速度、电压等特性
口读写特性:根据读写特性可以将SD卡分为2种,一种是读写卡,生产出来就是空白卡。另一种是只读卡,生产出来就定制了内容。
口支持电压 :根据支持的电压可以将SD卡分为高电压SD卡和双重电压SD卡
口卡容量:这个分类就算了不影响我们的问题分析
口速度:根据速度可以将SD卡分为4类。类0:这种卡兼容所有速度;类2:其速度大于等于2MB/S;类4:其速度大于等于4MB/S;类6:其速度大于等于6MB/S;高容量SD卡支持速度类描述,其性能相当于或超过类2.
2.SD卡功能描述
主机与卡之间通信都是由主机控制的,主机发送的命令有两种,分别为广播命令和地址命令。
口广播命令:该命令是发给所有的卡,有些广播命令需要响应。
口地址命令:这些命令发往具体地址的卡,并且从这些卡生产响应。
SD卡有两种模式
口卡识别模式:主机被复位或者在总线上寻找新卡时,主机处于该状态下。卡在复位以后和收到SEND_RCA命令以前都处于此模式下。
口数据传输模式:卡在它们的RCA(发布卡的地址)第一次发布后进入数据传输模式。主机识别总线上所有的卡后进入数据传输模式。
卡状态 | 操作模式 |
无活动状态 | 无活动 |
空状态 | 卡识别模式 |
准备态 | |
识别态 | |
等待态 | 数据传输模式 |
传输态 | |
发送数据态 | |
接收数据态 | |
编程态 | |
断开态 |
1.操作状态的验证
通过一系列过程后,主机才能识别卡。
口在主机和卡通信前,主机不知道卡支持的电压,卡也不知道是否支持主机当前提供的电压。主机将发布一个复位命令(CMD0),带着它能提供给卡的电压信息。
口为了验证SD卡的接口操作状态,主机发送SEND_IF_COND(CMD8),SD卡通过分析SEND_IF_COND命令参数检测操作状态的有效性,主机通过检测SD分析后的响应来判断电压的有效性。
口如果SD能够在提供的电压下操作,则发回的响应带上提供的电压,且检测模式被设置在命令参数中。如果SD卡不支持主机提供的电压,则不响应且保存在空闲态下。在发现ACMD41命令初始化高容量SD卡前,强制发送CMD8命令。
口强制低电压主机在发送CMD8前发送ACMD41。万一双重电压SD卡没有收到CMD8命令且工作在高压状态,在这种情况下,低电压主机不发送CMD8命令给卡,则收到ACMD41后进入无活动状态。
口SD_SEND_OP_COND(ACMD41)命令是为SD卡主机识别卡或电压不匹配时拒绝卡的机制而设计的。主机发送命令操作数代表代表要求的电压窗口大小。如果SD卡在所给的范围内不能实现数据传输,将放弃下一步的总线操作而进入无活动状态。操作状态寄存器也将被定义。
口主机发出复位命令(CMD0)后,主机将发送CMD8确认电压的有效性再发送ACMD41命令重新初始化SD卡。
卡识别模式的状态可以用下面的状态图表示
卡总线被激活后,主机就开始卡的初始化和识别处理。初始化处理从设置它的操作状态和设置OCR中的HCS比特位命令SD_SEND_OP_COND(ACMD41)开始。HCS比特位被设置为1表示主机支持高容量SD卡。HCS被设置为0表示主机不支持高容易SD卡。
卡的初始化和识别更详细的流程
卡的识别模式结束后,主机时钟fpp(数据传输时钟速率)将保持为Fod(卡识别模式下的时钟),因为有些卡对操作时钟有限制。主机必须发生SEND_CSD(CMD9)来获得卡规格数据寄存器内容,如块大小、卡容量。广播命令SET_DSR(CMD4)配置所有识别卡的驱动阶段。它对DSR寄存器进行编程以适应应用总线布局、总线上的卡数目和数据传输频率。
SD卡数据传输模式下的状态图
二.了解LINUX内核如何处理SD卡的
linux的SD卡驱动程序在driver/mmc目录下,该目录包含card,core,host
host驱动部分:host的驱动部分是针对不同类型主机的驱动
core驱动部分:core驱动部分完成不同协议和规范的实现,如SD卡相关的状态或修改状态、修改寄存器等操作。
card驱动部分:SD卡属于块设备,card驱动部分为了将SD卡驱动成块设备。
有三种检测SD卡的方式:
1.在开机的时候通过CMD发送命令检测TF卡是否存在,这种方式不支持热插拔。
2.通过T卡座来检测,信号DETECTION连接在中断控制器上。在