您的位置:首页 > 其它

SD Card 驱动流程分析

2013-12-27 17:30 561 查看
一、硬件接口电路
首先来看一下SDcard的一个硬件应用电路,如下图所示:



SD卡有两种工作模式,一个是spi接口模式,一个是SD模式,后者传输速率快些,这里讨论SD模式;SD总线包含4个数据总线(SDIO0-SDIO3),1个命令线(SDCMD)和一个同步时钟SDCLK;图上第10脚是卡检测信号。这里需注意的是传输总线必须加上拉。数据总线不一定全部要用到,根据需求可以选择数据总线个数。



二、SD卡初始化过程

SD卡的初始化过程,简单一点说包括:1.主机reset所有挂在SD总线上的CARD.2.确认卡的工作电压范围。3.获取卡的RCA(相对地址)。卡划分为十个工作状态,分别是如下所示:





初始化阶段需要涉及前面四个状态,即inactivestate、idle、ready、identificationstate。初始化状态图如下:





SD卡是通过命令与host互动的,主机发命令,sd卡接收到命令后返回相应的响应。所有命令和响应的传输都是在命令线上进行的。刚上电时,host发送CMD0来reset所有的sd卡(不管当前处于什么状态),使之进入idle状态。

通过发送CMD8命令,告诉SD卡host提供的工作电压范围,若SD卡支持host提供的工作范围,将在命令线上返回该值,可以说明当前是ver2.0SD存储卡。若SD卡不支持host提供的工作电压范围,它将没有响应而继续处在idlestate。如果该卡没有响应则是ver1.x。对于高容量SD存储卡CMD8命令是必须的。接下来需要发送ACMD41来决定是否拒绝或者说抛弃当前的SD卡(让它们进入inactivestate),很明显那些与host设计工作电压范围不匹配的卡将会遭此待遇。另外ACMD41命令的参数里面还包含了HCS位,即host
capicitysupport,置1表示host支持高容量sd卡。对于高容量SD存储卡,该位必须设为1,否则高容量卡响应中的busy位不会置1,该busy位在OCR寄存器的第31位,是用来指示SD卡是否初始化完毕,即进入readystate(busybitissetto1)。对于标准SD容量卡,HCS位设为0。要使的sd卡初始化完成并进入ready状态,不仅HCS位要设置正确,host还必须重复发送ACMD41命令,直到busy位置1。ACMD41的响应中除了busy位,还有一个CCS位(card
capcitystatus),当CCS=1时,表示当前sd卡是高容量sd卡,CCS=0表示当前sd卡是标准容量sd卡。

接着host发送cmd2来获取sd卡的一些出厂信息(CID),比如出厂序列号之类的,这些信息也是通过命令响应的方式传送给host,sd卡返回CID信息后就进入identificationstate。

发送cmd3使card传送rca给host,rca是用来给sd卡编址的,用于后面的数据传送。一旦获取了rca,sd卡就进入stand-bystate。这个时候如果host想得到新的rca,再次发送cmd3即可。

具体的初始化和卡识别流程如下图:



初始化注意事项:1、在初始化动作之前,至少发送74个nullclock,否则可能会遇到初始化失败。

2、ACMD命令发送之前需要发送cmd55命令,告诉sd卡host接下来要发送ACMD类型的命令,A表示application,初始化的时候cmd55命令参数中的rca使用默认的值0x0000,初始化之后必须是相应rca。

3、整个初始化过程使用小于400KHZ时钟,因为有的卡在初始化和识别阶段对clock有限制,在数据传送之前把clock调整即可。



三、数据传送





从上图可以很清晰地看到它的一个流程,进入数据传送模式开始sd卡是处在Stand-by状态的,此时可以发送命令获取SD卡的一些信息,比如发送cmd9来计算sd卡的容量。要想进入transfer状态,我们必须通过CMD7先选中某一张卡,该命令的参数设为我们想要选中sd卡的RCA,即初始化阶段得到的RCA。在同一个时刻,只能有一张卡处在transfer状态,其他与cmd7命令携带参数(RCA)不匹配的卡会回到stand-by状态。所以说要选中某张卡,只要设置相应的RCA,而释放一张卡,我们就设置与之不匹配的RCA(一般设为默认的值0x0000)。选中卡之后就进入transferstate,这时我们可以发送acmd6设置数据传输的总线位宽,默认是1,注意此操作有两个前提,一是处在transferstate,二是当前卡没有被lock。发送cmd17读单快数据,cmd18读多块数据,cmd24写单块,cmd25写多块,这些命令都带需要读取数据的首地址。在对多块进行读写的时,直到host发送cmd12才停止。

对block写数据操作完成后,sd卡会进入编程阶段,sd卡是提供缓冲区的,也就是说上一个block在编程时可以写下一个block数据。当缓冲区满了,并且这是卡还在programming,这时DAT0数据线会被拉低,告诉host此时忙碌。

四、程序

程序是在ZSP200内核的DSP芯片上实现的,16位数据总线,60MH的奔跑速度。下面是调试代码,还没来及优化,实现了block的读写,在板子上验证ok。

[cpp]
viewplaincopyprint?

<SPANstyle="FONT-SIZE:12px;FONT-FAMILY:MicrosoftYaHei"></SPAN>



[cpp]
viewplaincopyprint?

<SPANstyle="FONT-SIZE:12px;FONT-FAMILY:MicrosoftYaHei">voidsd_mmc_setup()
{
uint16reg16_val;
uint32reg32_val;
U8i;

SysReadAMBAReg((uint32)SYS_PWRPEN_REG,reg32_val);
reg32_val|=(1L<<2);
SysWriteAMBAReg((uint32)SYS_PWRPEN_REG,reg32_val);//开启SD/MMC控制器


sys_delay_ms(300L);

mmc_write_reg(MMC_CAR_SEL,0xdd);//enablemodule,enablemmcclk

mmc_write_reg(MMC_CRC_CTL,0xd0);//CRCcircuitenable

mmc_write_reg(MMC_CTL,0x0b);//1bit,lowspeed(256KHZ),1/4divider,autotransfer,mmcmode.

//mmc_write_reg(MMC_INT_MASK,0x7f);//unmaskallinterrupt


for(i=0;i<10;i++)//atleast74clockforsetup

{
mmc_write_reg(MMC_IO,0x24);//only8nullclockgeneration


mmc_read_reg(MMC_INT_CLR,reg16_val);
while(reg16_val!=0x01)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
mmc_write_reg(MMC_INT_CLR,reg16_val);
}myptf("sd_mmc_setupfinished!\r\n");

return;
}U8sd_write_cmd(U8*cmd,BOOLb_resp)
{
U8i;
uint16reg16_val;
uint32addr=MMC_CMD_BUF4;

for(i=0;i<5;i++)
{
mmc_write_reg(addr,cmd[i]);
addr-=2;
}
if(b_resp==FALSE)
{
mmc_write_reg(MMC_IO,0x04);//autoonlycommandenable

}
elseif((cmd==cmd2)||(cmd==cmd9))
{
mmc_write_reg(MMC_IO,0x54);//autocommand+response,enablegetCIDfrontcommandbuffer[135:8]

//mmc_write_reg(MMC_IO,0x0c);//autoonlyresponseenable

}
/*elseif(cmd==cmd24)
{
mmc_write_reg(MMC_IO,0x01);//writedata,trigtransfer
}*/
else
{
mmc_write_reg(MMC_IO,0x44);//autocommand+response

}/*waitandclearsdmmcCMDdoneinterrupt*/
mmc_read_reg(MMC_INT_CLR,reg16_val);
while(!(reg16_val&(1<<0)))
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
if((reg16_val&(1<<6))!=0)//commandorresponsetimerout

{
mmc_write_reg(MMC_INT_CLR,0x40);//clearinterrupt;

myptf("SendCmd%dTimerout!\r\n",cmd[0]-0x40);
return0;
}
}
myptf("InterruptFlag:%d\r\n",reg16_val);
mmc_write_reg(MMC_INT_CLR,0x1);//clearCMDdoneinterrupt;


return1;
}
SD_RESPONSE_INFOget_response_info(void)//Onlyfor48bitresponse

{
SD_RESPONSE_INFOres;
uint16reg16_val;
uint32reg32_val,addr;
U8i;

addr=MMC_CMD_BUF3;
mmc_read_reg(MMC_CMD_BUF4,reg16_val);
myptf("res.cmd_index=%d\r\n",reg16_val);
res.cmd_index=reg16_val;

for(i=0;i<4;i++)
{
reg32_val<<=8;
mmc_read_reg(addr,reg16_val);
reg32_val|=reg16_val;
addr-=2;
}
res.card_status=reg32_val;

myptf("res.card_status=%ld\r\n",reg32_val);

mmc_read_reg(MMC_CRC_VAL,reg16_val);
res.crc=reg16_val;

returnres;

}BOOLsd_mmc_identify()
{
SD_RESPONSE_INFOresp;
U16reg16_val;
U8i;

sd_write_cmd(cmd0,FALSE);//setthecardintoidlestate


sd_write_cmd(cmd8,TRUE);//verifythecardoperationcondition;

resp=get_response_info();

CardType=0;//ver2.0
if((resp.cmd_index!=0x08)
||(resp.card_status!=0x15a))
{
myptf("ErroResponseforcmd8\r\n");
CardType=1;
}myptf("ReadytoTansmitACMD!\r\n");
do
{
CMD55:
sd_write_cmd(cmd55,TRUE);//ForTransmitACMD;

resp=get_response_info();
if((resp.card_status&(1L<<5))!=0x20)
{
gotoCMD55;
}if(CardType==0)
sd_write_cmd(acmd41_1,TRUE);
else
sd_write_cmd(acmd41_0,TRUE);
resp=get_response_info();
if((resp.cmd_index!=0x3f)
||((resp.card_status&0x00ffffff)!=0xff8000))
{
myptf("UnusableCard!\r\n");
//returnFALSE;
}
}while((resp.card_status&(1L<<31))==0);//cardisbusyWaitforpowerup!

myptf("SDCardPowerOn!\r\n");
if(!(resp.card_status&(1L<<30)))
{
myptf("ThisisStandardCapacitySDMemeryCard!\r\n");
}
else
{
myptf("ThisisHighCapacitySDMemeryCard!\r\n");
}
CMD2:
sd_write_cmd(cmd2,TRUE);//itmakescardidentificationstate

mmc_read_reg(MMC_CMD_BUF15,reg16_val);
if(reg16_val!=0x3f)
{
gotoCMD2;
}
myptf("ReadCID...\r\n");
CMD3:
sd_write_cmd(cmd3,TRUE);//getthecard'sRCAandchangetostandbystate;

resp=get_response_info();
if(resp.cmd_index!=0x03)
{
//myptf("ErroResponseforcmd3!\r\n");

gotoCMD3;
}
card_addr=(U16)((resp.card_status&0xffff0000)>>16);
card_state=(U16)(resp.card_status&0x0000ffff);
myptf("currentcardaddris%ld\r\n",card_addr);
myptf("currentcardstateis%ld\r\n",card_state);

returnTRUE;
}
BOOLread_cards_capacity(U16rca)
{
U16reg16_val;
U32c_size;

cmd9[1]=rca/256;
cmd9[2]=rca%256;
sd_write_cmd(cmd9,TRUE);
mmc_read_reg(MMC_CMD_BUF15,reg16_val);
if(reg16_val!=0x3f)
{
myptf("ReadCapacityFailed!\r\n");
returnFALSE;
}mmc_read_reg(MMC_CMD_BUF7,reg16_val);//readc_zizevalue

c_size=reg16_val&0x3f;
c_size<<=8;
mmc_read_reg(MMC_CMD_BUF6,reg16_val);
c_size|=reg16_val;
c_size<<=8;
mmc_read_reg(MMC_CMD_BUF5,reg16_val);
c_size|=reg16_val;

card_capacity=((c_size+1)*512)/1024;

returnTRUE;
}
voidcard_select(U16rca,BOOLsel)//changebetweenstandbyandtransferstate;

{
SD_RESPONSE_INFOresp;

cmd7[1]=0x00;//deselectcard;

cmd7[2]=0x00;
if(sel==TRUE)//Selectcard

{
cmd7[1]=rca/256;
cmd7[2]=rca%256;
}
CMD7:
if(!(sd_write_cmd(cmd7,TRUE)))
{
gotoCMD7;
}
//get_response_info();

}voidset_bus_width(U8wide)//width=0:1bit;width=2:4bit;

{

acmd6[4]=wide;
cmd55[1]=card_addr/256;
cmd55[2]=card_addr%256;//note:cmd55'sargumentincluderca;

SETBUS:
sd_write_cmd(cmd55,TRUE);//ForTransmitACMD;

//get_response_info();
if(!(sd_write_cmd(acmd6,TRUE)))
gotoSETBUS;
get_response_info();
return;
}voidset_block_size()
{
sd_write_cmd(cmd16,TRUE);//setblocklength512bytes;

get_response_info();
}voidread_block(U32addr,U8block_cnt)
{
U16reg16_val;
U32reg32_val;
U8i,j;
//SD_RESPONSE_INFOresp;

//addr<<=9;//addr*521

mmc_write_reg(MMC_buf_ctl,0x9000);//activefifostatus,flushfifo,disabledma,readsd-card,wm-128


if(block_cnt<2)//readsingleblock

{
cmd17[1]=(U8)(addr>>24);
cmd17[2]=(U8)((addr>>16)&0xff);
cmd17[3]=(U8)((addr>>8)&0xff);
cmd17[4]=(U8)(addr&0xff);
CMD17:
if(!(sd_write_cmd(cmd17,TRUE)))
{
gotoCMD17;
}
get_response_info();
mmc_write_reg(MMC_BYTE_CNTH,0x02);//transfer512bytes

mmc_write_reg(MMC_IO,0x03);//readdata,autotransfer

}
else//readmultiblockss

{
cmd18[1]=(U8)(addr>>24);
cmd18[2]=(U8)((addr>>16)&0xff);
cmd18[3]=(U8)((addr>>8)&0xff);
cmd18[4]=(U8)(addr&0xff);
CMD18:
if(!(sd_write_cmd(cmd18,TRUE)))
{
gotoCMD18;
}
//get_response_info();

//sys_delay_ms(20L);//delaybefortrigtransferorelseerro

mmc_write_reg(MMC_BLOCK_CNT,block_cnt);//setreadblocknumber;

//mmc_write_reg(MMC_IO,0xc0);

mmc_write_reg(MMC_IO_MBCTL,0x53);//trigdatatransfer;

}mmc_read_reg(MMC_buf_ctl,reg16_val);
while(!(reg16_val&(1<<0)))//waitforfifofull;

{
mmc_read_reg(MMC_buf_ctl,reg16_val);
}
//myptf("FIFOFull\r\n");

for(j=0;j<128*block_cnt;j++)
{
/*mmc_read_reg(MMC_buf_ctl,reg16_val);
while((reg16_val&(1<<1))==0x02)//fifoempty?
{
mmc_read_reg(MMC_buf_ctl,reg16_val);
myptf("fifoempty!\nPleaseWait...\r\n");
}*/
SysReadAMBAReg(MMC_DATA_BUF0,sd_rd_buf[j]);
//for(i=0;i<50;i++);//delayforreadingdataelsedataerroappeared;

}
mmc_read_reg(MMC_INT_CLR,reg16_val);//waitfordatatransferfinished

while((reg16_val&(1<<1))!=0x02)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
myptf("ReadDataFinished!\r\n");
mmc_write_reg(MMC_INT_CLR,0x02);//clearinterrupt;


//mmc_read_reg(MMC_buf_ctl,reg16_val);

//myptf("fifofull?:%d\r\n",(reg16_val&0x01));

//myptf("fifoEmpty?:%d\r\n",(reg16_val&0x02));


if(block_cnt>1)
{
while((reg16_val&(1<<4))!=0x10)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
mmc_write_reg(MMC_INT_CLR,0x10);//clearinterruptflag;

myptf("ReadMulitiBlockFinished!\r\n");
CMD12:
if(!(sd_write_cmd(cmd12,TRUE)))
{
gotoCMD12;
}
}
}voidwrite_block(U32addr,U8block_cnt)//block_cnt<65536

{
U16reg16_val;
U8i,j;
//SD_RESPONSE_INFOresp;


//addr<<=9;
if(block_cnt<2)//writesingleblock

{
cmd24[1]=(U8)(addr>>24);
cmd24[2]=(U8)((addr>>16)&0xff);
cmd24[3]=(U8)((addr>>8)&0xff);
cmd24[4]=(U8)(addr&0xff);
CMD24:
if(!(sd_write_cmd(cmd24,TRUE)))
{
gotoCMD24;
}
//get_response_info();

//sys_delay_ms(20L);
mmc_write_reg(MMC_BYTE_CNTH,0x02);//transfer512bytes

mmc_write_reg(MMC_buf_ctl,0x9800);//activefifostatus,disabledma,writesd-card,

mmc_write_reg(MMC_IO,0x01);//writedata,trigtransfer

}
else//writemultiblock

{
cmd25[1]=(U8)(addr>>24);
cmd25[2]=(U8)((addr>>16)&0xff);
cmd25[3]=(U8)((addr>>8)&0xff);
cmd25[4]=(U8)(addr&0xff);
cmd55[1]=card_addr/256;
cmd55[2]=card_addr%256;
acmd23[3]=block_cnt/256;
acmd23[4]=block_cnt%256;
ACMD23:
sd_write_cmd(cmd55,TRUE);
if(!(sd_write_cmd(acmd23,TRUE)))
{
gotoACMD23;
}
CMD25:
if(!(sd_write_cmd(cmd25,TRUE)))
{
gotoCMD25;
}
//get_response_info();
//sys_delay_ms(20L);

mmc_write_reg(MMC_BLOCK_CNT,block_cnt);//setwriteblocknumber;

mmc_write_reg(MMC_buf_ctl,0x9800);//activefifostatus,disabledma,writesd-card,

mmc_write_reg(MMC_IO_MBCTL,0x51);//trigdatatransfer;

}
mmc_read_reg(MMC_buf_ctl,reg16_val);
while(!(reg16_val&(1<<1)))//waitforfifoempty;

{
mmc_read_reg(MMC_buf_ctl,reg16_val);
}
//myptf("FIFOEmpty\r\n");

for(j=0;j<128*block_cnt;j++)
{
SysWriteAMBAReg(MMC_DATA_BUF0,sd_rd_buf[j]);
//for(i=0;i<220;i++);

/*mmc_read_reg(MMC_buf_ctl,reg16_val);
while((reg16_val&0x01)==0x01)//fifofull?
{
myptf("fifofull!\nPleaseWait...\r\n");
mmc_read_reg(MMC_buf_ctl,reg16_val);
}*/
}
mmc_read_reg(MMC_INT_CLR,reg16_val);//waitfordatatransferfinished

while((reg16_val&(1<<1))!=0x02)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
myptf("InterruptFlag:%d\r\n",reg16_val);
mmc_write_reg(MMC_INT_CLR,0x02);//cleardatadoneinterrupt;

myptf("WriteDatafinished!\r\n");
if(block_cnt>1)
{
while((reg16_val&(1<<4))!=0x10)//waitmultiblockdone

{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
mmc_write_reg(MMC_INT_CLR,0x10);//clearmultiblockdoneinterrupt;

myptf("Writemultiblockfinished!\r\n");
CMD12_1:
if(!(sd_write_cmd(cmd12,TRUE)))//EndDatatransfer;

{
gotoCMD12_1;
}
get_response_info();
}
}voidsd_mmc_initial()
{
sd_mmc_setup();
if(sd_mmc_identify()==FALSE)
{
myptf("sdcardinitialfailed!\r\n");
}
else
{
myptf("sdcardinitialsuccesful!\r\n");

if(read_cards_capacity(card_addr)==TRUE)
{
myptf("currentcardcapacityis:%ldM\r\n",card_capacity);
}
card_select(card_addr,TRUE);
set_bus_width(BUS_4_BIT);//settransferdatabus;

set_block_size();
mmc_write_reg(MMC_CTL,0xc3);//4bitdata,highspeed(30M),1/2divider,autotransfer,mmcmode.

mmc_write_reg(MMC_IO_MBCTL,0x50);//timeroutscal

}
}</SPAN>

voidsd_mmc_setup()
{
uint16reg16_val;
uint32reg32_val;
U8i;

SysReadAMBAReg((uint32)SYS_PWRPEN_REG,reg32_val);
reg32_val|=(1L<<2);
SysWriteAMBAReg((uint32)SYS_PWRPEN_REG,reg32_val);//开启SD/MMC控制器

sys_delay_ms(300L);

mmc_write_reg(MMC_CAR_SEL,0xdd);//enablemodule,enablemmcclk
mmc_write_reg(MMC_CRC_CTL,0xd0);//CRCcircuitenable
mmc_write_reg(MMC_CTL,0x0b);//1bit,lowspeed(256KHZ),1/4divider,autotransfer,mmcmode.
//mmc_write_reg(MMC_INT_MASK,0x7f);//unmaskallinterrupt

for(i=0;i<10;i++)//atleast74clockforsetup
{
mmc_write_reg(MMC_IO,0x24);//only8nullclockgeneration

mmc_read_reg(MMC_INT_CLR,reg16_val);
while(reg16_val!=0x01)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
mmc_write_reg(MMC_INT_CLR,reg16_val);
}myptf("sd_mmc_setupfinished!\r\n");

return;
}U8sd_write_cmd(U8*cmd,BOOLb_resp)
{
U8i;
uint16reg16_val;
uint32addr=MMC_CMD_BUF4;

for(i=0;i<5;i++)
{
mmc_write_reg(addr,cmd[i]);
addr-=2;
}
if(b_resp==FALSE)
{
mmc_write_reg(MMC_IO,0x04);//autoonlycommandenable
}
elseif((cmd==cmd2)||(cmd==cmd9))
{
mmc_write_reg(MMC_IO,0x54);//autocommand+response,enablegetCIDfrontcommandbuffer[135:8]
//mmc_write_reg(MMC_IO,0x0c);//autoonlyresponseenable
}
/*elseif(cmd==cmd24)
{
mmc_write_reg(MMC_IO,0x01);//writedata,trigtransfer
}*/
else
{
mmc_write_reg(MMC_IO,0x44);//autocommand+response
}/*waitandclearsdmmcCMDdoneinterrupt*/
mmc_read_reg(MMC_INT_CLR,reg16_val);
while(!(reg16_val&(1<<0)))
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
if((reg16_val&(1<<6))!=0)//commandorresponsetimerout
{
mmc_write_reg(MMC_INT_CLR,0x40);//clearinterrupt;
myptf("SendCmd%dTimerout!\r\n",cmd[0]-0x40);
return0;
}
}
myptf("InterruptFlag:%d\r\n",reg16_val);
mmc_write_reg(MMC_INT_CLR,0x1);//clearCMDdoneinterrupt;

return1;
}
SD_RESPONSE_INFOget_response_info(void)//Onlyfor48bitresponse
{
SD_RESPONSE_INFOres;
uint16reg16_val;
uint32reg32_val,addr;
U8i;

addr=MMC_CMD_BUF3;
mmc_read_reg(MMC_CMD_BUF4,reg16_val);
myptf("res.cmd_index=%d\r\n",reg16_val);
res.cmd_index=reg16_val;

for(i=0;i<4;i++)
{
reg32_val<<=8;
mmc_read_reg(addr,reg16_val);
reg32_val|=reg16_val;
addr-=2;
}
res.card_status=reg32_val;

myptf("res.card_status=%ld\r\n",reg32_val);

mmc_read_reg(MMC_CRC_VAL,reg16_val);
res.crc=reg16_val;

returnres;

}BOOLsd_mmc_identify()
{
SD_RESPONSE_INFOresp;
U16reg16_val;
U8i;

sd_write_cmd(cmd0,FALSE);//setthecardintoidlestate

sd_write_cmd(cmd8,TRUE);//verifythecardoperationcondition;
resp=get_response_info();

CardType=0;//ver2.0
if((resp.cmd_index!=0x08)
||(resp.card_status!=0x15a))
{
myptf("ErroResponseforcmd8\r\n");
CardType=1;
}myptf("ReadytoTansmitACMD!\r\n");
do
{
CMD55:
sd_write_cmd(cmd55,TRUE);//ForTransmitACMD;
resp=get_response_info();
if((resp.card_status&(1L<<5))!=0x20)
{
gotoCMD55;
}if(CardType==0)
sd_write_cmd(acmd41_1,TRUE);
else
sd_write_cmd(acmd41_0,TRUE);
resp=get_response_info();
if((resp.cmd_index!=0x3f)
||((resp.card_status&0x00ffffff)!=0xff8000))
{
myptf("UnusableCard!\r\n");
//returnFALSE;
}
}while((resp.card_status&(1L<<31))==0);//cardisbusyWaitforpowerup!
myptf("SDCardPowerOn!\r\n");
if(!(resp.card_status&(1L<<30)))
{
myptf("ThisisStandardCapacitySDMemeryCard!\r\n");
}
else
{
myptf("ThisisHighCapacitySDMemeryCard!\r\n");
}
CMD2:
sd_write_cmd(cmd2,TRUE);//itmakescardidentificationstate
mmc_read_reg(MMC_CMD_BUF15,reg16_val);
if(reg16_val!=0x3f)
{
gotoCMD2;
}
myptf("ReadCID...\r\n");
CMD3:
sd_write_cmd(cmd3,TRUE);//getthecard'sRCAandchangetostandbystate;
resp=get_response_info();
if(resp.cmd_index!=0x03)
{
//myptf("ErroResponseforcmd3!\r\n");
gotoCMD3;
}
card_addr=(U16)((resp.card_status&0xffff0000)>>16);
card_state=(U16)(resp.card_status&0x0000ffff);
myptf("currentcardaddris%ld\r\n",card_addr);
myptf("currentcardstateis%ld\r\n",card_state);

returnTRUE;
}
BOOLread_cards_capacity(U16rca)
{
U16reg16_val;
U32c_size;

cmd9[1]=rca/256;
cmd9[2]=rca%256;
sd_write_cmd(cmd9,TRUE);
mmc_read_reg(MMC_CMD_BUF15,reg16_val);
if(reg16_val!=0x3f)
{
myptf("ReadCapacityFailed!\r\n");
returnFALSE;
}mmc_read_reg(MMC_CMD_BUF7,reg16_val);//readc_zizevalue
c_size=reg16_val&0x3f;
c_size<<=8;
mmc_read_reg(MMC_CMD_BUF6,reg16_val);
c_size|=reg16_val;
c_size<<=8;
mmc_read_reg(MMC_CMD_BUF5,reg16_val);
c_size|=reg16_val;

card_capacity=((c_size+1)*512)/1024;

returnTRUE;
}
voidcard_select(U16rca,BOOLsel)//changebetweenstandbyandtransferstate;
{
SD_RESPONSE_INFOresp;

cmd7[1]=0x00;//deselectcard;
cmd7[2]=0x00;
if(sel==TRUE)//Selectcard
{
cmd7[1]=rca/256;
cmd7[2]=rca%256;
}
CMD7:
if(!(sd_write_cmd(cmd7,TRUE)))
{
gotoCMD7;
}
//get_response_info();
}voidset_bus_width(U8wide)//width=0:1bit;width=2:4bit;
{

acmd6[4]=wide;
cmd55[1]=card_addr/256;
cmd55[2]=card_addr%256;//note:cmd55'sargumentincluderca;
SETBUS:
sd_write_cmd(cmd55,TRUE);//ForTransmitACMD;
//get_response_info();
if(!(sd_write_cmd(acmd6,TRUE)))
gotoSETBUS;
get_response_info();
return;
}voidset_block_size()
{
sd_write_cmd(cmd16,TRUE);//setblocklength512bytes;
get_response_info();
}voidread_block(U32addr,U8block_cnt)
{
U16reg16_val;
U32reg32_val;
U8i,j;
//SD_RESPONSE_INFOresp;

//addr<<=9;//addr*521
mmc_write_reg(MMC_buf_ctl,0x9000);//activefifostatus,flushfifo,disabledma,readsd-card,wm-128

if(block_cnt<2)//readsingleblock
{
cmd17[1]=(U8)(addr>>24);
cmd17[2]=(U8)((addr>>16)&0xff);
cmd17[3]=(U8)((addr>>8)&0xff);
cmd17[4]=(U8)(addr&0xff);
CMD17:
if(!(sd_write_cmd(cmd17,TRUE)))
{
gotoCMD17;
}
get_response_info();
mmc_write_reg(MMC_BYTE_CNTH,0x02);//transfer512bytes
mmc_write_reg(MMC_IO,0x03);//readdata,autotransfer
}
else//readmultiblockss
{
cmd18[1]=(U8)(addr>>24);
cmd18[2]=(U8)((addr>>16)&0xff);
cmd18[3]=(U8)((addr>>8)&0xff);
cmd18[4]=(U8)(addr&0xff);
CMD18:
if(!(sd_write_cmd(cmd18,TRUE)))
{
gotoCMD18;
}
//get_response_info();
//sys_delay_ms(20L);//delaybefortrigtransferorelseerro
mmc_write_reg(MMC_BLOCK_CNT,block_cnt);//setreadblocknumber;
//mmc_write_reg(MMC_IO,0xc0);
mmc_write_reg(MMC_IO_MBCTL,0x53);//trigdatatransfer;
}mmc_read_reg(MMC_buf_ctl,reg16_val);
while(!(reg16_val&(1<<0)))//waitforfifofull;
{
mmc_read_reg(MMC_buf_ctl,reg16_val);
}
//myptf("FIFOFull\r\n");
for(j=0;j<128*block_cnt;j++)
{
/*mmc_read_reg(MMC_buf_ctl,reg16_val);
while((reg16_val&(1<<1))==0x02)//fifoempty?
{
mmc_read_reg(MMC_buf_ctl,reg16_val);
myptf("fifoempty!\nPleaseWait...\r\n");
}*/
SysReadAMBAReg(MMC_DATA_BUF0,sd_rd_buf[j]);
//for(i=0;i<50;i++);//delayforreadingdataelsedataerroappeared;
}
mmc_read_reg(MMC_INT_CLR,reg16_val);//waitfordatatransferfinished
while((reg16_val&(1<<1))!=0x02)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
myptf("ReadDataFinished!\r\n");
mmc_write_reg(MMC_INT_CLR,0x02);//clearinterrupt;

//mmc_read_reg(MMC_buf_ctl,reg16_val);
//myptf("fifofull?:%d\r\n",(reg16_val&0x01));
//myptf("fifoEmpty?:%d\r\n",(reg16_val&0x02));

if(block_cnt>1)
{
while((reg16_val&(1<<4))!=0x10)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
mmc_write_reg(MMC_INT_CLR,0x10);//clearinterruptflag;
myptf("ReadMulitiBlockFinished!\r\n");
CMD12:
if(!(sd_write_cmd(cmd12,TRUE)))
{
gotoCMD12;
}
}
}voidwrite_block(U32addr,U8block_cnt)//block_cnt<65536
{
U16reg16_val;
U8i,j;
//SD_RESPONSE_INFOresp;

//addr<<=9;
if(block_cnt<2)//writesingleblock
{
cmd24[1]=(U8)(addr>>24);
cmd24[2]=(U8)((addr>>16)&0xff);
cmd24[3]=(U8)((addr>>8)&0xff);
cmd24[4]=(U8)(addr&0xff);
CMD24:
if(!(sd_write_cmd(cmd24,TRUE)))
{
gotoCMD24;
}
//get_response_info();
//sys_delay_ms(20L);
mmc_write_reg(MMC_BYTE_CNTH,0x02);//transfer512bytes
mmc_write_reg(MMC_buf_ctl,0x9800);//activefifostatus,disabledma,writesd-card,
mmc_write_reg(MMC_IO,0x01);//writedata,trigtransfer
}
else//writemultiblock
{
cmd25[1]=(U8)(addr>>24);
cmd25[2]=(U8)((addr>>16)&0xff);
cmd25[3]=(U8)((addr>>8)&0xff);
cmd25[4]=(U8)(addr&0xff);
cmd55[1]=card_addr/256;
cmd55[2]=card_addr%256;
acmd23[3]=block_cnt/256;
acmd23[4]=block_cnt%256;
ACMD23:
sd_write_cmd(cmd55,TRUE);
if(!(sd_write_cmd(acmd23,TRUE)))
{
gotoACMD23;
}
CMD25:
if(!(sd_write_cmd(cmd25,TRUE)))
{
gotoCMD25;
}
//get_response_info();
//sys_delay_ms(20L);
mmc_write_reg(MMC_BLOCK_CNT,block_cnt);//setwriteblocknumber;
mmc_write_reg(MMC_buf_ctl,0x9800);//activefifostatus,disabledma,writesd-card,
mmc_write_reg(MMC_IO_MBCTL,0x51);//trigdatatransfer;
}
mmc_read_reg(MMC_buf_ctl,reg16_val);
while(!(reg16_val&(1<<1)))//waitforfifoempty;
{
mmc_read_reg(MMC_buf_ctl,reg16_val);
}
//myptf("FIFOEmpty\r\n");
for(j=0;j<128*block_cnt;j++)
{
SysWriteAMBAReg(MMC_DATA_BUF0,sd_rd_buf[j]);
//for(i=0;i<220;i++);
/*mmc_read_reg(MMC_buf_ctl,reg16_val);
while((reg16_val&0x01)==0x01)//fifofull?
{
myptf("fifofull!\nPleaseWait...\r\n");
mmc_read_reg(MMC_buf_ctl,reg16_val);
}*/
}
mmc_read_reg(MMC_INT_CLR,reg16_val);//waitfordatatransferfinished
while((reg16_val&(1<<1))!=0x02)
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
myptf("InterruptFlag:%d\r\n",reg16_val);
mmc_write_reg(MMC_INT_CLR,0x02);//cleardatadoneinterrupt;
myptf("WriteDatafinished!\r\n");
if(block_cnt>1)
{
while((reg16_val&(1<<4))!=0x10)//waitmultiblockdone
{
mmc_read_reg(MMC_INT_CLR,reg16_val);
}
mmc_write_reg(MMC_INT_CLR,0x10);//clearmultiblockdoneinterrupt;
myptf("Writemultiblockfinished!\r\n");
CMD12_1:
if(!(sd_write_cmd(cmd12,TRUE)))//EndDatatransfer;
{
gotoCMD12_1;
}
get_response_info();
}
}voidsd_mmc_initial()
{
sd_mmc_setup();
if(sd_mmc_identify()==FALSE)
{
myptf("sdcardinitialfailed!\r\n");
}
else
{
myptf("sdcardinitialsuccesful!\r\n");

if(read_cards_capacity(card_addr)==TRUE)
{
myptf("currentcardcapacityis:%ldM\r\n",card_capacity);
}
card_select(card_addr,TRUE);
set_bus_width(BUS_4_BIT);//settransferdatabus;
set_block_size();
mmc_write_reg(MMC_CTL,0xc3);//4bitdata,highspeed(30M),1/2divider,autotransfer,mmcmode.
mmc_write_reg(MMC_IO_MBCTL,0x50);//timeroutscal
}
}

/*测试代码*/

[cpp]
viewplaincopyprint?

U8cmd0[5]={0x40,0x00,0x00,0x00,0x00};
U8cmd2[5]={0x42,0x00,0x00,0x00,0x00};
U8cmd3[5]={0x43,0x00,0x00,0x00,0x00};
U8cmd7[5]={0x47,0x00,0x00,0x00,0x00};
U8cmd8[5]={0x48,0x00,0x00,0x01,0x5a};//2.7-3.6V;use‘10101010b’forthe‘checkpattern’

U8cmd9[5]={0x49,0x00,0x00,0x00,0x00};
U8cmd12[5]={0x4c,0x00,0x00,0x00,0x00};//stoptransfercommand;

U8cmd16[5]={0x50,0x00,0x00,0x02,0x00};//setblocklength512bytes;

U8cmd17[5]={0x51,0x00,0x00,0x00,0x00};//readsingleblock;

U8cmd18[5]={0x52,0x00,0x00,0x00,0x00};//readmultiblock;

U8cmd24[5]={0x58,0x00,0x00,0x00,0x00};//writesingleblock;

U8cmd25[5]={0x59,0x00,0x00,0x00,0x00};//writesingleblock;

U8cmd55[5]={0x77,0x00,0x00,0x00,0x00};
U8acmd6[5]={0x46,0x00,0x00,0x00,0x00};//settransferdatabus

U8acmd23[5]={0x57,0x00,0xff,0x80,0x00};
U8acmd41_1[5]={0x69,0x40,0xff,0x80,0x00};//HCS=1;voltagerange2.7-3.6V;

U8acmd41_0[5]={0x69,0x00,0xff,0x80,0x00};//HCS=0;voltagerange2.7-3.6V;


typedefstruct
{
U8cmd_index;
uint32card_status;
U8crc;
}SD_RESPONSE_INFO;

uint16card_addr;
uint16card_state;
U8CardType;
U32card_capacity;
U32sd_rd_buf[1024]={0};
U32sd_write_buf[512]={0};

U8cmd0[5]={0x40,0x00,0x00,0x00,0x00};
U8cmd2[5]={0x42,0x00,0x00,0x00,0x00};
U8cmd3[5]={0x43,0x00,0x00,0x00,0x00};
U8cmd7[5]={0x47,0x00,0x00,0x00,0x00};
U8cmd8[5]={0x48,0x00,0x00,0x01,0x5a};//2.7-3.6V;use‘10101010b’forthe‘checkpattern’
U8cmd9[5]={0x49,0x00,0x00,0x00,0x00};
U8cmd12[5]={0x4c,0x00,0x00,0x00,0x00};//stoptransfercommand;
U8cmd16[5]={0x50,0x00,0x00,0x02,0x00};//setblocklength512bytes;
U8cmd17[5]={0x51,0x00,0x00,0x00,0x00};//readsingleblock;
U8cmd18[5]={0x52,0x00,0x00,0x00,0x00};//readmultiblock;
U8cmd24[5]={0x58,0x00,0x00,0x00,0x00};//writesingleblock;
U8cmd25[5]={0x59,0x00,0x00,0x00,0x00};//writesingleblock;
U8cmd55[5]={0x77,0x00,0x00,0x00,0x00};
U8acmd6[5]={0x46,0x00,0x00,0x00,0x00};//settransferdatabus
U8acmd23[5]={0x57,0x00,0xff,0x80,0x00};
U8acmd41_1[5]={0x69,0x40,0xff,0x80,0x00};//HCS=1;voltagerange2.7-3.6V;
U8acmd41_0[5]={0x69,0x00,0xff,0x80,0x00};//HCS=0;voltagerange2.7-3.6V;

typedefstruct
{
U8cmd_index;
uint32card_status;
U8crc;
}SD_RESPONSE_INFO;

uint16card_addr;
uint16card_state;
U8CardType;
U32card_capacity;
U32sd_rd_buf[1024]={0};
U32sd_write_buf[512]={0};


[cpp]
viewplaincopyprint?





[cpp]
viewplaincopyprint?

voidmain()

voidmain()


[cpp]
viewplaincopyprint?

{

{


[cpp]
viewplaincopyprint?

sd_mmc_initial();
while(1)
{
sys_wdtrestart();
read_block(153600,8);
//read_block(153601,3);//31760

//read_block(300,3);//30760*512

//read_block(30,1);//30*512

for(j=0;j<128;j++)
{
myptf("sd_rd_buf[%d]=%ld\r\n",j,sd_rd_buf[j]);
}
write_block(153605,1);
write_block(153606,8);
//write_block(153609,3);

//read_block(153604,3);
/*for(j=0;j<384;j++)
{
myptf("sd_rd_buf[%d]=%ld\r\n",j,sd_rd_buf[j]);
}*/
//while(1);
}
sd_mmc_initial();
while(1)
{
sys_wdtrestart();
read_block(153600,8);
//read_block(153601,3);//31760
//read_block(300,3);//30760*512
//read_block(30,1);//30*512
for(j=0;j<128;j++)
{
myptf("sd_rd_buf[%d]=%ld\r\n",j,sd_rd_buf[j]);
}
write_block(153605,1);
write_block(153606,8);
//write_block(153609,3);
//read_block(153604,3);
/*for(j=0;j<384;j++)
{
myptf("sd_rd_buf[%d]=%ld\r\n",j,sd_rd_buf[j]);
}*/
//while(1);
}


[cpp]
viewplaincopyprint?

}
}

就分析到这里,有分析不对的地方请博友们指正,愿意同大家交流。

http://blog.csdn.net/rxllh/article/details/8100698
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: