接口名称:SDIO
英文全称:Secure Digital Input/output (SD I/O)
中文:安全数字输入输出接口
标准维护:SDA(SD Card Association),由松下、东芝和SanDisk三家公司牵头成立。
以及SD Group.安全数字卡联盟
当前规范:www.sdcard.org
最新版本:V3.0(SD V6.0/2017年4月10日)
生效时间:2009.04.16
下一版本:
说明:SDIO规范定义了SDIO卡和嵌入式SDIO设备(Embedded SDIO Device),SDIO规范是应用SD总线和SD命令的一个总线。在此述及的SDIO是指Embedded SDIO Device,它必须符合SD PHY规范和SDIO规范。SPI模式是其一个可选模式。
一、接口结构
SDIO (Input/Output)是一种IO接口规范。目前,其最主要用途是为带有SD卡槽的设备进行外设功能扩展。SDIO卡是一种IO外设,而不是Memory,其外形与SD卡一致,可直接插入SD卡槽中。
一个完整的SDIO控制系统包括:SDIO/SD/MMC卡、主控制器硬件层以及由主控制器驱动、功能卡相关驱动、顶层应用程序组成的软件部分等。SDIO主控制器介于片上系统总线和外设卡之间,实现了系统总线信号到SD总线信号的转化,CPU对接在SDIO主控制器上的外设的操作只要符合APB的时序要求,而底层的细节处理交给SDIO主控制器来完成。
SDIO主控制器的主要功能包括:控制卡的读/写时序、命令生成与发送、响应接收与分析、数据发送与接收、硬件中断的处理、时钟域功耗的控制(主控制器必须提供频率可配置的时钟,因为外设卡的时钟由主控制器通过时钟线提供,需匹配不同种类的外设卡;同时时钟与功耗有着直接关联)等。
SDIO卡插入带有标准SD卡槽的设备后,如果该设备不支持SDIO,SDIO卡不会对SD卡的命令作出响应,处于非激活状态,不影响设备的正常工作;如果该设备支持SDIO卡,则按照规范的要求激活SDIO卡。
SDIO卡允许设备按IO的方式直接对寄存器进行访问,无须执行FAT文件结构或数据Sector等复杂操作。此外,SDIO卡还能向设备发出中断,这是与SD memory卡的本质区别。
SDIO总线也有两端,其中一端是主机(HOST)端,另一端是设备端(DEVICE),采用HOST- DEVICE这样的设计是为了简化DEVICE的设计,所有的通信都是由HOST端发出命令开始的。在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信。
SDIO总线通信基于3种格式的比特流:命令包、响应包和数据包。
控制器要按照SDIO协议的格式给命令添加起始位、标志位、CRC校验位、停止位等。命令在写入命令寄存器后,通过CMD线传给外设卡,卡收到命令后在CMD线上返回特定的响应到主控制器,主控制器把响应存放到响应寄存器,用来对卡状态进行分析判断。
SDIO接口包括以下信号:
CLK:HOST给DEVICE的时钟信号.
CMD:双向信号,用于传送命令和反应。
DAT0-DAT3:四条用于传送的数据线,支持1位或4位两种数据宽度的传输。
VDD信号:电源信号。
VSS1&VSS2:地。
其中,DAT1线可复用为中断线,即在SDIO的1BIT模式下DAT0传输数据,DAT1作中断线;在SDIO的4BIT模式下DAT0-DAT3用来传输数据,其中DAT1复用作中断线。
SDIO命令:DIO总线上都是HOST端发起请求,然后DEVICE端回应请求。其中请求和回应中会数据信息。
Command:用于开始传输的命令,是由HOST端发往DEVICE端的,是通过CMD信号线传送的。
Response:DEVICE响应返回给HOST的命令,作为Command的回应,也是通过CMD线传送的。
Data:数据是双向的传送的。可以设置为1线模式,也可以设置为4线模式。数据是通过DAT0-DAT3信号线传输的。
SDIO的每次操作都是由HOST在CMD线上发起一个CMD,对于有的CMD,DEVICE需要返回Response,有的则不需要。
读命令:首先HOST会向DEVICE发送命令,紧接着DEVICE会返回一个握手信号,当HOST收到回应的握手信号后,会将数据放在4位的数据线上,在传送数据的同时会跟随着CRC校验码。当整个读传送完毕后,HOST会再次发送一个命令,通知DEVICE操作完毕,DEVICE同时会返回一个响应。
写命令:首先HOST会向DEVICE发送命令,紧接着DEVICE会返回一个握手信号,当HOST收到回应的握手信号后,会将数据放在4位的数据线上,在传送数据的同时会跟随着CRC校验码。当整个写传送完毕后,HOST会再次发送一个命令,通知DEVICE操作完毕,DEVICE同时会返回一个响应。
SDIO的寄存器:SDIO卡的设备驱动80%的任务就是操作SDIO卡上的有关寄存器。SDIO卡最多允许有7个功能(function),这个同其功能号是对应的(1~7),每个功能都对应一个128K字节大小的寄存器,这个见下面的图。功能号之所以取值范围是1~7,而没有包含0,是因为功能0并不代表真正的功能,而代表CIA寄存器,即Common I/O Area,这个记录着SDIO卡的一些基本信息和特性,并且可以改写这些寄存器。其中地址0x1000~0x17fff是SDIO卡的CIS区域,就是基本信息区域,Common Information Structure。初始化的时候读取并配对SDIO设备
SDIO接口的硬件结构如下图的示。即SDIO接口由1~4根数据线、1根时钟线和1根命令线构成。就是说SD总线包含以下信号:CLK为主机端HOST向Device设备端发送的时钟信号;CMD为双向的命令响应信号;DAT0~DAT3为4个双向的数据信号;VDD、VSS1及VSS2为电源和地信号。每个SDIO设备具有1至7个功能Function以及一个存储功能Memory Function。一个功能Function是一个自包含的IO设备,彼此之间可以完全相同也可以完全不同。
SDIO控制器中主要包括命令控制器、数据控制器、中断控制器、时钟功耗控制器和数据FIFO等模块。SDIO传输模式同SD卡一样,也有SPI 、1-bit 和 4-bit等3 种。需要注意的是:在SPI模式中,第8脚被当成中断信号(低电平有效),其它脚的功能和通信协定与SD记忆卡的标准规范一样;而在1 bit模式中,8脚用作中断脚(低电平有效),9脚用作Read Wait(读等待)脚,其它脚的功能和通信协定与SD记忆卡的标准规范一样;而在4 bit模式中,没有专门的中断脚,中断功能的实现需要专门的中断周期(即在中断周期内,当8脚电平为低时,认为是中断)来实现。SDIO 3.0版本实现了UHS-I的速率,其最高可达104MB/S。
CD:Connect/Disconnect检测
RCLK由主机HOST端传输参考时钟给设备端Device,D0是数据差分对,它们由主机端传输数据、命令和其它包给设备端(下行);D1也是数据差分对,它们由设备端传输响应、数据和其它包给主机端(上行)。
UHS-III最高速率可达6.24Gbps,它分为Range A、B、C及D等4个等级,其速率分别为156MB/S(8b/10b半双工)、312MB/S(8b/10b半双工)、321MB/S(8b/10b全双工)以及624MB/S(8b/10b全双工)。UHS-II可支持8K VIDEO和3D cameras/drones(无人机)。它包含三个差分对,即RCLK、D0和D1,如上图所示。Command, data and other packets or symbols are transmitted by D0 (basically from host to SD memory card) and D1 (basically from SD memory card to host) lanes.
Command
四种用于控制卡设备的指令类型,每个command都是固定的48位长度:
broadcast commands(bc), no response:广播类型的指令,不需要有响应;
broadcast commands with response(bcr):广播类型的指令且需要响应;
addressed(point-to-point) commands(ac):由HOST发送到指定的卡设备,没有数据的传输;
address(point-to-point) data transfercommands(adtc):由HOST发送到指定的卡设备且伴随有数据传输。
SD卡命令共分为12类,分别为class0到class11,不同的SDd卡,主控根据其功能,支持不同的命令集,如下:
Class0 :(卡的识别、初始化等基本命令集)
CMD0:复位SD 卡.
CMD1:读OCR寄存器.
CMD9:读CSD寄存器.
CMD10:读CID寄存器.
CMD12:停止读多块时的数据传输
CMD13:读 Card_Status 寄存器
Class2 (读卡命令集):
CMD16:设置块的长度
CMD17:读单块.
CMD18:读多块,直至主机发送CMD12为止 .
Class4(写卡命令集) :
CMD24:写单块.
CMD25:写多块.
CMD27:写CSD寄存器 .
Class5 (擦除卡命令集):
CMD32:设置擦除块的起始地址.
CMD33:设置擦除块的终止地址.
CMD38: 擦除所选择的块.
Class6(写保护命令集):
CMD28:设置写保护块的地址.
CMD29:擦除写保护块的地址.
CMD30: Ask the card for the status of the write protection bits
class7:卡的锁定,解锁功能命令集
class8:申请特定命令集 。
class10 -11 :保留
Card register
主要的寄存器:OCR,CID,CSD,RCA和SCR。
Operation condition register(OCR):32位的OCR包含卡设备支持的工作电压表;
Card identification number register (CID):包含用于在卡识别阶段的卡信息,包括制造商ID,产品名等;
Card specific data register(CSD):CSD寄存器提供了如何访问卡设备的信息,包括定义了数据格式,错误校验类型,最大访问次数,数据传输率等;
Relative card address register(RCA):存放在卡识别阶段分配的相对卡地址,缺省相对卡地址为0000h;
SD card configuration register(SCR):SCR是一个配置寄存器,用于配置SD memory card的特殊功能。
Response
所有的response都通过CMD线发送到host端,R4和R5响应类型是SDIO中特有的:
R1(normal response command):用来响应常用指令;
R2(CID,CSD register):用来响应CMD2、CMD10或CMD9,并把CID或CSD寄存器作为响应数据;
R3(OCR register):用来响应ACMD41指令,并把OCR寄存器作为响应数据;
R4(CMD5):响应CMD5,并把OCR寄存器作为响应数据;
R5(CMD52):CMD52是一个读写寄存器的指令,R5用于CMD52的响应;
R6(published RCA response):分配相对卡地址的响应;
R7(card interface condition):响应CMD8,返回卡支持的电压信息。
Response 格式:
二、工作原理
SDIO与SD接口的区别:SDIO协议是由SD卡的协议演化升级而来的,很多地方保留了SD卡的读写协议,同时SDIO协议又在SD卡协议之上添加了CMD52和CMD53命令。由于这个,SDIO和SD卡规范间的一个重要区别是增加了低速标准,低速卡的目标应用是以最小的硬件开始来支持低速I/O能力。低速卡支持类似调制解调器,条形码扫描仪和GPS接收器等应用。高速卡支持网卡,电视卡还有“组合”卡等,组合卡指的是存储器+SDIO。在非组合卡的SDIO设备里,其最高速度要只有达到25M,而组合卡的最高速度同SD卡的最高速度一样,要高于25M。此外,SD卡和SDIO卡还在一些commands, R6 register, reset, bus width, card detect resistor, data transfer block sizes, data transfer abort, some fixed sd memory registers有差异,具体差异可查阅simplified sdio card spec.pdf第四章4.2~4.10.
有两种SDIO功能类型:标准SDIO和非标准SDIO。
工作电压:高压2.7~3.6V ,低压1.70~1.95V(UHS-II)。SDIO3.0定义了8比特模式以及1个异步中断脚(低有效)、开漏输出Open Drain(需接上拉)
总线速率模式包括UHS-I、UHS-II及UHS-III:
1) 默认速率模式:3.3V信号,高达25MHz,数据速率12.5MB/S
2) 高速率模式:3.3V信号,高达50MHz,数据速率25MB/S
3) SDR12:UHS-I 1.8V信号,高达25MHz,数据速率12.5MB/S
4) SDR25:UHS-I 1.8V信号,高达50MHz,数据速率25MB/S
5) SDR50:UHS-I 1.8V信号,高达100MHz,数据速率50MB/S
6) SDR104: UHS-I 1.8V信号,高达208MHz,数据速率104MB/S
7) DDR50: UHS-I 1.8V信号,高达50MHz,双时钟边沿采样,数据速率50MB/S
8) UHS156: UHS-II,RCLK频率26~52MHz,最高1.56Gbps/Lane
9) UHS624: UHS-III,RCLK频率26~52MHz,最高6.24Gbps/Lane
UHS: Ultra High Speed
在上电后, SD存储卡默认只使用DAT0进行数据传输。CS信号在SPI处理(命令、响应和数据)期间必须连续有效。
SDIO接口硬件主要由三个部分组成:SDIO控制器、SD总线和SDIO卡。
SDIO控制器是SDIO接口与系统连接的部分,它与内部系统总线相连;SDIO控制器中主要包括命令控制器、数据控制器、中断控制器、时钟功耗控制器和数据FIFO等模块. SDIO控制器通过SD总线与SDlO卡进行命令和数据的交互。
SDIO卡是具体功能的实现单元;软件部分主要由控制器驱动、SDIO卡驱动和应用程序组成。SDIO接口的软硬件结构如下图所示。
SD总线传输命令、响应和数据。命令是由控制器通过命令线发往SDIO卡,是控制器通知SDIO卡动作的承载体,包括向SDIO卡传输的地址信息和参数,其格式.
响应是由SDIO卡发通过命令线往控制器,传输内容包括SDIO卡寄存器值、CRC校验码反馈信息等,其格式如下图所示.
SD总线的数据传输主要有两种模式:单数据线模式与多数据线模式。当传输数据量较小的情况下,可以选择单数据线传输模式,在此模式下,数据传输仅使用DAT0数据线;在传输数据量很大的情况下,可选择多数据线传输模式,此时使用全部四根数据线DAT0-DAT3。SD总线在数据传输时,可以进行块(block)传输。下图为单数据线模式,传输大小为512字节的数据块的传输格式。
当使用多数据线模式传输数据时,要使用全部四根数据线。此时对于传输的数据块而言,要将块内的数据按顺序从四根数据线上传输。下图为多数据线模式下,传输大小为512字节的数据块的传输格式。
三、应用设计
SDIO接口应用比较简单,注意区分SDIO2.0和SDIO3.0.其物理连接如下图所示。控制器向SD总线提供的电压值有三种:3.3V,3.0V和1.8V. 在初始化阶段SDIO接口的工作电压为2.0V~3.6V,在正常工作阶段其1=作电压为3.1V~3.5V。在选择合适的工作作电压前,控制器驱动首先要检卉将要设定的电压值是否被忙和SD总线所支持,否则如果选择了SDIO卡或者SD总线不支持的电压值,控制器将不能向SD总线正常提供电流。在选择了正确的电压值后,控制器驱动程序通过设置SD总线能量(power)寄存器,开始向SD总线提供电流。
在SDIO HOST端的数据线DATA0~3上必须接上拉电阻。注意SPI和1位数据传输模式的中断不同。
SD卡使用的是SD卡协议,而SDIO卡使用的是SDIO协议!
SDIO-Wifi 模块
SDIO-Wifi 模块是基于 SDIO 接口的符合 wifi 无线网络标准的嵌入式模块,内置无线网络协议IEEE802.11协议栈以及TCP/IP协议栈,能够实现用户主平台数据通过SDIO口到无线网络之间的转换。
SDIO 具有传输数据快,兼容SD、MMC接口等特点。
对于SDIO接口的wifi,首先,它是一个sdio的卡的设备,然后具备了wifi的功能。
所以,注册的时候还是先以sdio的卡的设备去注册的。然后检测到卡之后就要驱动他的wifi功能。
SDIO协议是由SD卡的协议演化升级而来的,很多地方保留了SD卡的读写协议,同时SDIO协议又在SD卡协议之上添加了CMD52和CMD53命令
以IO_SEND_OP_COND命令为例包含以下部分:
S(开始位) 总为0
D(方向位) 1 从host到 device (0 从device到host)
命令索引: 通过值000101B来
填充位 0
IO_OCR 运转条件寄存器所支持的VDD的最小值和最大值
CRC7 7位CRC校验数据
E(结束位) 总为1
MMC命令总共有40多个,分为class0 ~class7共8类,class0的所有卡必须支持。驱动程序通过发送cmd1、cmd41来区分sd卡和mmc卡,如果发送cmd1返回成功,则为mmc卡,否则发送cmd41返回成功,则为sd卡。
Linux mmc子系统驱动架构如下:
Linux kernel把mmc,sd以及sdio三者的驱动代码整合在一起,俗称mmc子系统。源码位于drivers/mmc下。其下有三个子目录,分别是:
其中,card用于构建一个块设备作为上层与mmc子系统沟通的桥梁;core抽象了mmc,sd,sdio三者的通用操作;Linux下的任何驱动在内核中最终都抽象为bus, driver以及device三者间的相互作用。host则是各类平台上的host驱动代码.Kernel/drivers/mmc下有三个目录的作用分别为:
1) card 这个目录是衔接最上层应用的接口,应用层使用sd卡一般都是通过文件系统来操作的,card目录里面的代码就是让sd卡成为一个块设备,这样应用层就可以把它当作磁盘来操作了。
2) core 这个目录是MMC子系统的核心,里面实现了card和host要用到的一些通用的函数接口和数据结构,它起到衔接作用,可以看作成中间层,是MMC总线驱动程序。mmc/sd/sdio协议部分就是在这个文件夹里面实现的(card目录里面也会涉及到协议)。
3) host 这个目录存放了各个mmc/sd/sdio控制器的代码,最终操作mmc/sd/sdio卡的部分 (硬件通讯接口)就是在这里实现的。
重要的数据结构位于core核心层,主要用于核心层与主机驱动层的数据交换处理。/include/linux/mmc/host.h
struct mmc_host用来描述卡控制器
Struct mmc_card 用来描述卡
Struct mmc_driver 用来描述mmc卡驱动
Struct sdio_func 用来描述功能设备
Struct mmc_host_ops 用来描述卡控制器操作接口函数功能,用于从主机控制器层向core 层注册操作函数,从而将core 层与具体的主机控制器隔离。也就是说 core 要操作主机控制器,就用这个 ops 当中给的函数指针操作,不能直接调用具体主控制器的函数.
Mmc子系统涉及到三条总线。
Host驱动相应的driver和device挂载在Linux内核内置的虚拟抽象总线platform_bus_type
两者的匹配采用名称匹配的方式,即driver和device两者的name一样则认为该device对应该driver,这里是”omap_hsmmc”。
Card驱动相应的driver和device挂载在mmc自己创建的虚拟总线mmc_bus_type下,直接匹配。
Sdio驱动相应的driver和device挂载在mmc自己创建的虚拟总线sdio_bus_type下,ID匹配。
注意:Linux内核中,匹配函数默认使用bus注册的匹配函数,如果bus没有注册则使用driver注册的匹配函数。所以,一般自己创建虚拟总线时,其匹配函数和driver的匹配函数都是一致的。
我们知道host在扫描卡的过程中,其识别的顺序为SDIO-> SD MMC,并且从它的注释可以看出,这个顺序是很重要的。那这篇文章,我们就看看SDIO的识别过程,它对应的函数就是mmc_attach_sdio(host) (函数位于文件drivers/mmc/core/sdio.c)
这个函数大概来说做了如下的工作
1、向卡发送CMD5命令,该命令有两个作用:第一,通过判断卡是否有反馈信息来判断是否为SDIO设备(只有SDIO设备才对CMD5命令有反馈,其他卡是没有回馈的);第二,如果是SDIO设备,就会给host反馈电压信息,就是说告诉host,本卡所能支持的电压是多少多少。
2、host根据SDIO卡反馈回来的电压要求,给其提供合适的电压。
3、初始化该SDIO卡
4、注册SDIO的各个功能模块
5、注册SDIO
对于以上功能的具体解释,下面将结合程序娓娓道来:
1、CMD5命令的发送
第789行的函数就是发送的CMD5命令,如果卡对该命令有回馈的话,err就是0,否则,err为非0,直接退出了;并且需要重点说明的一点就是,该函数的最后一个参数ocr,它是存储反馈命令的,SDIO设备对CMD5的反馈命令为R4,下面来仔细分析一下这个R4,因为后面要用到这个R4命令。从SDIO spec文档里面,我们能得到R4命令的格式
从上图可以看出,该命令有48位,但我们的ocr变量是32位的,那怎么存储呢?系统就去掉原命令的开头8位以及结尾的8位,只保留中间的32为,也就是截短后的命令格式是如下:
具体各位的描述如下:
C -- 1位
Number 0f IO functions 3位 每个SDIO设备都有功能块,表明该设备有多少个功能块,最多7个
Memory Present – 1位,指明该设备是纯粹只有功能块的设备,还是同时包含了存储空间,如果为0就是前者,如果是1就是后者
Stuff Bits --3位,没有实际用途一般为0
I/O OCR – 24位,该设备所能支持的电压范围(具体描述见sdio spec)
2、配置电压
ocr就是我们上面讲的反馈命令R4(截短之后的32位),那么ocr&0x7f的意义是什么呢?从R4的格式就可以看出来,其低24位就代表了所能支持的电压范围,我们再来详细的看一下这24位的OCR格式
现在应该可以知道ocr&0x7f的意义了吧,就是摈弃那些保留的电压范围。
重点关注mmc_select_voltage
第1080行的相与 过程就是判断host实际所支持的电压与card所需要的电压是否匹配,如果匹配,那么ocr的值就非0,否则就为0
简单介绍下第1082行的ffs函数,它的作用就是返回参数中第一个为1的bit的位置(ffs(0)=0,ffs(1)=1,ffs(8)=4),那么该函数用在这里的作用就是取出card需要的实际电压是多少;
第1090行的mmc_set_ios函数里面通过调用sdhci_set_power将host->ios.vdd所代表的电压写入寄存器PWRCONn中 完成那个对电压的重新配置(想要了解更详细的过程,请跟踪源代码)。
3、初始化SDIO卡
第821行就是初始化SDIO卡的函数,这个函数很长,也很重要,这里笔者就不列出其程序代码,只是列出其中最重要的几条:
n 通过函数mmc_alloc_card分配一个mmc_card的变量card
n 通过读取R4命令中的bit27(也就是Memory Present)来判断此卡是纯IO卡还是同时包含存储功能。笔者使用的WIFI模块为纯IO功能,所以card->type = MMC_TYPE_SDIO(这个很重要,以后会用到) (接下来重点分析MMC_TYPE_SDIO的情况)
n 通过发送CMD3命令获取设备的从地址(relative addr),并且存放在变量card->rca中。笔者使用的WIFI模块的card->rca = 1
n 通过发送CMD7,选中相应从地址的卡
n 通过调用函数mmc_set_clock设置卡工作的时钟频率
n 通过发送CMD52命令,设置4位数据传输模式。
4、注册SDIO功能模块
847行的变量funcs存储该SDIO卡所包含的IO功能块的个数,851行到857行就是逐一初始化各个IO功能块,下面来重点看一下该函数的内容:
第71行就是分配sdio_func结构体变量,该结构体存储了功能块的参数。
第75行就是给功能块编号,编号是从1到7(因为一个SDIO设备最多只有7个功能块),存储在变量func->num中。
第78行就是读取SDIO卡中的FBR寄存器中关于该卡的功能类型的数据,存储在func->class变量中(具体关于FBR寄存器内容,可以参考SDIO spec文档)
第82行就是读取SDIO卡中的CIS寄存器的内容
上面的程序就是将功能模块逐个的注册进设备模型,这里想重点说明一下注册的名称(name),它是由三部分组成的,每部分之间用冒号隔开(即 host的名称:rca:功能块编号) 。具体到笔者使用的WIFI模块,因为其host名称是mmc2 ,rca = 1,并且有两个功能模块(功能模块编号分别是1和2),所以在/sys/bus/sdio/devices目录下能见到如下两个设备名
mmc2:0001:1
mmc2:0001:2
5、注册SDIO卡
上面的mmc_add_card函数就是注册card(这个card是在第3部分,初始化SDIO卡 里面分配和定义的)
第259行就是给card命名,格式为host名字:从地址,对于笔者的WIFI模块 就是mmc2:0001
第261到273行就是根据card->type来分辨出card的类型,给赋予相应的字符串,笔者的WIFI模块就是"SDIO"
第275行就是打印信息,具体不解释 笔者的打印信息为 mmc2:new high speed SDIO card at address 0001(通常可以通过查看内核启动信息中是否有该语句来判断card是否被正确识别)
第283行 就是将card注册进linux设备模型 注册结果就是可以在/sys/bus/mmc/devices目录下见到card 的名字,笔者的就是mmc2:0001。