基于ARM含SD控制器的SD卡的SDIO模式驱动解析
SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。
SD卡的结构能保证数字文件传送的安全性,也很容易重新格式化,因此越来越多的被应用的嵌入式系统中。
SD卡的使用非常方便,常见的有两种工作模式:SPI和SDIO。SPI是串行的工作模式,速度相对较低,但是使用方便,只要MCU含有SPI接口均可使用。SDIO模式,可以最多4线传输,因此速度比较快,由于SD卡的普及,越来越多的MCU内部集成了SDIO控制器,简化了我们的工作。本文以三星s3c2410为例介绍。
1. SD卡的接口电路
![](../img/eep/emb/emb-65793f1as5j5wpnd.jpg)
2. SD卡的协议
SD卡的控制指令非常强大,支持SPI,SDIO模式,兼容MMC等。而且不同的
指令有不同的响应(3种),这在我们使用指令是要注意的。我在附件里面放了一个SD卡的中文协议,包括数据包介绍,指令索引介绍,反馈介绍等。
3. S3C2410 SD卡控制器的介绍
SD卡控制器帮我们完成了协议上的很多工作,我们只需要按照协议配置寄存器
以及按照协议流程对SD卡操作就可以完成SD卡的功能了。
SDICON:完成SD卡基础配置,包括大小端,中断允许,模式选择,时钟使能等。
SDIPRE:对SDCLK的配置。
SDICARG:指令的参数存放在这里
SDICCON:控制指令形式的寄存器,配置SPI还是SDI指令,指令的反馈长度,是否等待反馈,是否运行指令,指令的索引等
SDICSTA:指令状态寄存器,指令是否超时,传送,结束,CRC是否正确等
SDIRSPO:反映SD的状态
SDITIMER:设置超时时间
SDIBSIZE:block的大小
SDIDCON:数据控制寄存器,配置是几线传输,数据发送方向,数据传送方式等。
SDIDSTA: 数据状态寄存器,数据是否发送完,CRC效验,超时等
SDIFSTA: FIFO状态积存器,DMA传输时否判断FIFO
SDIMSK:中断屏蔽
4. SD卡SDIO模式的驱动分析
4.1 SD卡的初始化
步骤是:1)配置时钟,慢速一般为400K,设置工作模式
2)发送CMD0,进入空闲态,该指令没有反馈
3)发送CMD55+ACMD41,判断SD卡的上电是否正确,短反馈
4)发送CMD2,验证SD卡是否接入,长反馈
5)发送CMD3,读取SD卡的RCA(地址),短反馈
6)发送CMD7,使能SD卡
7)配置高速时钟,准备数据传输,一般20M~25M
8)发送CMD55+ACMD6配置为4bit数据传输模式
代码如下:
int SD_card_init(void)
{
int i;
char key;
rSDIPRE=PCLK/(2*INICLK)-1; //时钟 400KHz
rSDICON=(1<<4)|(1<<1)|1; // Type B, FIFO reset, clk enable
rSDIBSIZE=0x200; // 512byte(128word)
rSDIDTIMER=0xffff; // Set timeout count
for(i=0;i<0x1000;i++); // Wait 74SDCLK for MMC card
CMD0(); //进入idle
//-- Check SD card OCR
if(Chk_SD_OCR()) //发送AM41,判断电压正确否
;
else
{
;
return 0;
}
RECMD2:
rSDICARG=0x0;
// CMD2(stuff bit),判断连接
rSDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x42;
//lng_resp, wait_resp, start, CMD2
//-- Check end of CMD2
if(!Chk_CMDend(2, 1)) //查询反馈是否正确
goto RECMD2;
RECMD3:
//--Send RCA,得到SD卡的地址
rSDICARG=MMC<<16;
// CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
rSDICCON=(0x1<<9)|(0x1<<8)|0x43;
// sht_resp, wait_resp, start, CMD3
//-- Check end of CMD3
if(!Chk_CMDend(3, 1))
goto RECMD3;
//--Publish RCA
RCA=( rSDIRSP0 & 0xffff0000 )>>16;
//--State(stand-by) check
if( rSDIRSP0 & 0x1e00!=0x600 )
// CURRENT_STATE check 验证反馈
goto RECMD3;
rSDIPRE=PCLK/(2*NORCLK)-1;
// 设置高速时钟Normal clock="25MHz"
Card_sel_desel(1); // Select SD
Set_4bit_bus(); //设置为4bit模式
}
void Set_4bit_bus(void)
{
Wide=1;
SetBus();
}
void SetBus(void)
{
SET_BUS:
CMD55();
// Make ACMD
//-- CMD6 implement
rSDICARG=Wide<<1;
//Wide 0: 1bit, 1: 4bit
rSDICCON=(0x1<<9)|(0x1<<8)|0x46;
//sht_resp, wait_resp, start, CMD55
if(!Chk_CMDend(6, 1)) // ACMD6
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于ARM体系的嵌入式系统BSP的程序设计方案(04-11)
- 在Ubuntu上建立Arm Linux 开发环境(04-23)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- SQLite嵌入式数据库系统的研究与实现(02-20)
- 革新2410D开发板试用手记(04-21)