详解sd协议以及裸机和u-boot中的sd卡驱动(1)

本文为该系列的第一篇。

1. 引入

1.1 使用场景

对于sd卡的使用,相信大家都已经很是熟悉:

  1. 无文件系统

    首先调用初始化函数,然后便可以调用读写函数进行读写扇区的操作,但是更多的使用场景是在文件系统之上。

  2. 有文件系统

  • pc端,以windows为例:

    将sd卡(或通过usb读卡器)插在电脑的插槽里面,然后出现一个sd卡的盘符,点进去便可以访问里面的文件;

  • 开发板:

    将sd卡插在开发板的插槽里面,进入linux根文件系统的shell,执行mount命令挂载在某个目录下,然后进入该目录,便可以访问里面的文件;

1.2 背后原理

那么上述使用过程背后的实现原理是什么呢?为了更形象的讲解,我画了如下的一幅图:

attachments-2020-07-YjGj1SXN5f11cd6269fbe.png

以在开发板中使用为例(不使用DMA):

  • 当我们插上sd卡后,sd卡便通过导线与s3c2440芯片引出的对应管脚相连,而这些引出的管脚最终会接到芯片内部的sd控制器上,

  • 当我们需要读sd卡时,

    1. cpu读写sd控制器内部的寄存器,以此来控制其发出各种信号,主要包括读取的地址、大小等;

    2. sd控制器发出的信号通过导线传输到sd卡内部;

    3. sd卡接收到信号,从中解析出要读取的地址以及大小等,并以此读取其内部存储单元,接着将读取到的数据通过相同的路径传回到cpu内部的寄存器;

    4. cpu将获取到的数据通过sdram控制器写入到sdram中,完成此次读操作。

  • 当我们需要写sd卡时,

    1. cpu通过sdram控制器读取sdram中存储的需要写入到sd卡中的数据;

    2. cpu读写sd控制器内部的寄存器,以此来控制其发出各种信号,主要包括写入的地址、数据等;

    3. sd控制器发出的信号通过导线传输到sd卡内部;

    4. sd卡接收到信号,从中解析出要写入的地址以及数据等,并将数据写入该地址对应的内部存储单元。

1.3 提出问题

针对上述过程,我们重点关注以下几个问题:

  1. sd控制器与sd卡之间如何通过信号来进行数据交换?

  2. cpu如何控制sd控制器来发出各种信号?

1.4 回答

1. 对于上述问题1的回答,便是sd协议所规定的内容,具体在第2章进行说明。

2. 对于上述问题2的回答,便是sd驱动的内容,具体在第3章进行说明。

2. sd协议

注:本章关于协议的内容,主要参考自sd协议书以及网络,在此感谢这些不知名的分享者(^_^)

现在我们来回答问题1:sd控制器与sd卡之间如何通过信号来进行数据交换?

答案就是:sd协议

  1. 首先,通信的第一步需要有源、目的以及媒介,所以,sd协议规定了:

    • sd控制器与sd卡之间相连接的物理线路

    • sd卡的引脚

    • sd卡内部的寄存器,用来保存sd卡本身的一些信息

  2. 接着,我们知道,物理线路上传输的肯定是一串二进制的比特流,而要想利用这些比特流进行通信,就必须要对这些比特流进行一定的组织,并且通信双方都应该遵守,为此,sd协议规定了:

    • 这些比特流被分为三种基本的单位,包括命令、响应以及数据,每种基本单位都有固定的格式

  3. 然后,基本单位以及其格式有了,sd协议在此基础上,又将命令和响应按照功能定义了多个种类,比如:

    • 复位命令CMD0、单块读命令CMD17等等

    • 不同类型的响应

  4. 最后,sd协议利用这些不同功能的命令以及响应,定义了一个具体的通信流程。

对于以上各部分更具体的描述,请看下文。

2.1 物理层面

2.1.1 sd卡引脚定义

我们这里说的sd卡包括:

  • 标准尺寸的sd卡

  • micro sd卡

具体引脚定义如下图所示:

attachments-2020-07-ycOel2EW5f11cd8fea196.jpg

2.1.2 sd卡内部寄存器定义

SD卡有六个寄存器OCR、CID、CSD、RCA、DSR以及SCR,其中前四个保存卡的特定信息,后两个用来对卡进行配置。

  • OCR寄存器保存有卡支持的工作电压,支持的话相应的位置1,否则为0,具体内容如下:

attachments-2020-07-aDHm4gDx5f11cdb85cbe9.jpg

  • CID寄存器保存有卡的身份信息,具体内容如下:

attachments-2020-07-fpASchgT5f11cdc12c1d4.jpg

  • CSD寄存器保存有如何访问卡的信息,具体内容如下:

attachments-2020-07-jQrfWAx55f11cdd27c0b0.jpgattachments-2020-07-76QQl5hE5f11cde06a182.jpg

  • RCA寄存器保存有卡的地址信息

  • DSR寄存器用于配置卡,默认值为0x404

  • SCR寄存器保存卡的特定信息,具体内容如下:

attachments-2020-07-TYjgTO8x5f11cded337b9.jpg

2.2 信号格式

2.2.1 分类

sd卡与host端通信的基本单位包括:

  • 命令:在CMD线上传输的用于启动一个操作的比特流,由主机发往从机,可以是点对点也可以是广播的;

  • 响应:在CMD线上传输的用于响应命令的比特流,由从机发往主机;

  • 数据:在DAT线上传输的用于传输数据的比特流,双向传输;

注:

  1. 比特流:简单来说,软件层面表现为包含任意个0或1的2进制串,硬件层面表现为任意个高低电平;

  2. 广播命令:给所有卡都发送,某些命令需要响应;

  3. 点对点命令:给指定地址的卡发送,需要响应;

2.2.2 命令

2.2.2.1 命令格式

总共48位,首先是1个起始位0,接着是1个方向位(主机发送位1),6个命令位( 0-63 ),32位参数(有些命令需要),7位CRC校验,1个停止位,具体如下图所示:

attachments-2020-07-ehVVbWpb5f11ce155003d.jpg

2.2.2.2 命令分类

卡命令根据不同的类型分成了不同的Class,见下表,其中Class0,2,4,5,8是每个卡都必须支持的命令,不同的卡所支持的命令保存在CSD中

attachments-2020-07-AI0xIsPn5f11ce264d620.jpg

attachments-2020-07-3yIPtkLE5f11ce2db0971.jpg

2.2.2.3 命令详细描述
  • 基本命令Class0

attachments-2020-07-ki8FO9mN5f11ce615c370.jpgattachments-2020-07-lnTBIrgf5f11ce6a71ced.jpg

  • 读命令Class2

attachments-2020-07-YjO3PR2G5f11ce7860ee2.jpg

  • 写命令Class4

attachments-2020-07-3y3IpIsf5f11ce7fde261.jpg

  • 擦除命令Class5

attachments-2020-07-ZycdIo3w5f11ce873db89.jpg

  • 应用特定命令Class8

attachments-2020-07-LCVteNRj5f11ce8f3619a.jpg

  • 下表中的所有命令使用前都应先跟一个APP_CMD(CMD55)命令

attachments-2020-07-zYKXPZQ45f11ce956241a.jpg

2.2.3 响应

总共有如下四种类型的响应:

  • R1:长度位48位,注意每个块传输完成后有一个BUSY位

attachments-2020-07-f56VodGC5f11cea5b2dc7.jpg

  • R1b:与R1类似,只是将BUSY位加入响应中

  • R2(CID CSD寄存器):长度为136位,CID为CMD2和CMD10的响应,CSD为CMD9的响应

attachments-2020-07-EUqXQ9Ht5f11ceacd9826.jpg

  • R3(OCR寄存器):长度位48位,作为ACMD41的响应

attachments-2020-07-frnQ0ixX5f11ceb36cbac.jpg

  • R6(RCA地址响应):长度为48位

attachments-2020-07-nDjjfp2X5f11ceba66016.jpg

2.2.4 数据

具体格式如下:

attachments-2020-07-KlMEeEvb5f11cecc5b0f0.jpg

2.3 通信流程

2.3.1 工作模式

  1. 卡识别模式

    主机上电复位后即处于此模式,它会在总线上等待卡。卡复位后也处于此模式,直到SEND_RCA(CMD3)命令到来。

  2. 数据传输模式

    卡收到SEND_RCA(CMD3)命令后即进入此模式,主机识别到卡后也进入此模式

具体模式以及状态分类如下表所示:

attachments-2020-07-igBxH75g5f11cedb9357b.jpg

2.3.2 卡识别模式

此模式下主机复位总线所有的卡, 之后验证工作电压,询问卡的地址,并且这个模式下所有数据的传输都是只通过CMD线来完成

  1. 卡的复位

    当卡上电或收到GO_IDLE_STATE (CMD0)命令后,卡即进入Idle State状态,此时卡将其RCA设为0,相关寄存器设为传输稳定的最优模式

  2. 工作电压验证

    • 每个卡的最高和最低工作电压存储在OCR,只有当电压匹配时,CID和CSD的数据才能正常传输给主机

    • SD_SEND_OP_COND (ACMD41)命令用来判断卡的工作电压是否符合,如果不符合的话,卡应该放弃总线操作,进入Inactive State状态。在发送SD_SEND_OP_COND (ACMD41)命令前记得要首先发送APP_CMD (CMD55)

    • ACMD41命令响应中的BUSY位也用于卡表示其还没准备好,主机此时应重发ACMD41命令,直到卡准备好

    • 主机在这个阶段的ACMD41中不允许改变工作电压,如果确实想改变的话,应该先发送CMD0,然后再发送改变后的ACMD41

    • GO_INACTIVE_STATE (CMD15)命令用于使指定地址的卡进入Inactive State模式

  3. 卡识别过程

    ALL_SEND_CID (CMD2)命令用于获取卡的CID信息,如果卡处于Ready State,它就会在CMD线上传送它的CID信息,然后进入Identification State模式,紧接着发送CMD3 (SEND_RELATIVE_ADDR)命令,用于设置卡新的地址,卡收到新的地址后进入Stand-by State模式

具体状态转换如下图:

attachments-2020-07-unimJRa05f11ceedaab7e.jpg

2.3.3 数据传输模式

具体状态转换图如下:

attachments-2020-07-rGYbcJSN5f11cef4a830d.jpg

说明:

  1. 进入数据传输模式后,主机先不停的发送SEND_CSD (CMD9)命令获取卡的CSD信息

  2. SET_DSR (CMD4)用于设置卡的DSR寄存器,包括数据总线宽度、总线上卡的数目、总线频率,当设置成功后,卡的工作频率也随之改变,此步操作是可选的

  3. CMD7命令用于使指定地址的卡进入传输模式,任何指定时刻只能有一个卡处于传输模式,传输模式下所有的数据传输都是点对点的, 并且所有有地址的命令都需要有响应.

  4. 总线宽度选择命令

    ACMD6命令用于选择总线宽度,此命令只有在Transfer State有效,应在CMD7命令后使用

  5. 块读命令

    • 块是数据传输的最小单位,在CSD (READ_BL_LEN)中定义,SD卡为固定的512B,每个块传输的后面都跟着一个CRC校验。

    • CMD17(READ_SINGLE_BLOCK)用于传输单个块,传输完之后,卡进入Transfer State。

    • CMD18 (READ_MULTIPLE_BLOCK)用于多个块的传输,直到收到一个CMD12命令

  6. 块写命令

    • 与块读命令类似, 每个块传输的后面都跟着一个CRC校验.卡写数据时会进行CRC校验,另外,多块写比重复的单块写更能提高效率

    • 如果CSD中的WRITE_BLK_MISALIGN没设置, 并且发送的数据不是块对齐的, 卡会设置状态寄存器中的ADDRESS_ERROR位,并且进入Receive-data-State状态等待停止命令.此时写操作也会停止, 并且卡会设置其的WP_VIOLATION位.

    • 如果写缓冲满的话, 卡会停止接受WRITE_BLOCK命令. 此时主机应发送SEND_STATUS (CMD13)命令, 卡返回数据的READY_FOR_DATA位标志卡是否准备好接受新的数据.

    • 在多块写操作中通过事先发送ACMD23命令可提高写速度. ACMD23用于定义接下来要写数据的块的数目. 每次多块写操作后, 这个值又被设为默认的1.

    • ACMD22会使卡返回写成功的块数目.

  7. 擦除命令

    擦除命令的顺序是:ERASE_WR_BLK_START(CMD32),ERASE_WR_BLK_END(CMD33),ERASE (CMD38)

    • 如果上述命令接收到出错信息, 卡会设置状态寄存器中的ERASE_SEQ_ERROR 位并且重新等待新的命令时序

    • 如果接收到时序错误命令, 卡会设置其ERASE_RESET位并且重新等待新的命令时序

其他:

  • 所有读命令都可以由CMD12命令停止,之后卡进入Transfer State. 读命令包括单块读(CMD17), 多块读(CMD18), 发送写保护(CMD30), 发送scr(ACMD51)和读模式一般命令(CMD56).

  • 所有写命令都可以由CMD12命令停止. 写命令包括单块读(CMD24), 多块读(CMD25), 写CID(CMD26), 写CSD(CMD27),锁和解锁命令(CMD42)和写模式一般命令(CMD56).

  • 参数设置命令在卡被编程时是不允许发送的, 这些命令包括设置块长度(CMD16), 擦除块起始(CMD32)和擦除块结束(CMD33).

  • 用CMD7使另一个卡进入Transfer State不会终止当前卡的编程和擦除, 当前卡会进入Disconnect State并且释放DAT线.

  • Disconnect State模式的卡可通过CMD7重新被选中,此时卡进入Programming State并且使能busy信号.

  • 写保护管理,有如下三种机制:

    • 写保护物理开关

    • 卡内部写保护:通过设置CSD中的WP_GRP_ENABLE位和WP_GRP_SIZE位, SET_WRITE_PROT和CLR_WRITE_PROT命令用来设置和清除保护机制

    • 密码保护

  • 发表于 2020-07-18 00:18
  • 阅读 ( 50 )
  • 分类:经验分享

0 条评论&回复

请先 登录 后评论
渐进
渐进

12 篇文章

作家榜 »

  1. 百问网-周老师 18 文章
  2. st_ashang 14 文章
  3. 渐进 12 文章
  4. zxq 11 文章
  5. helloworld 8 文章
  6. 谢工 5 文章
  7. Litchi_Zheng 5 文章
  8. 星星之火 5 文章