SD卡读写包括两种模式.docx
- 文档编号:9753137
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:37
- 大小:25.36KB
SD卡读写包括两种模式.docx
《SD卡读写包括两种模式.docx》由会员分享,可在线阅读,更多相关《SD卡读写包括两种模式.docx(37页珍藏版)》请在冰豆网上搜索。
SD卡读写包括两种模式
SD卡读写包括两种模式:
SD模式和SPI模式。
其中SD模式又可以分为1bit和4bit两种传输模式。
SD卡缺省使用专有的SD模式。
SD卡规范中主要讲了一些命令,响应和CRC效验等等,整个规范的内容还是很多的。
SD卡上电后,卡处于空闲状态,主机发送CMD复位SD卡,然后通过CMD55和ACMD4判断当前电压是否在卡的工作范围内。
在得到了正确的响应后,主机可以继续通过CMD1读取SD卡的CID寄存器,通过CMD1设置数据块长度,通过CMD读取卡的CSD寄存器。
从CSD寄存器中,主机可以获知卡容量,支持的命令集等重要参数。
此时,卡以进入了传输状态,主机就可以通过CMD17/18和
CMD24/25对卡进行读写。
CRC校验是为了防止SD卡的命令,应答,数据传输出现错误。
每个命令和应答信号都会产生CRC效验码,每个数据块的传输也会长生CRC效验码。
这段程序是友善之臂推出的mini2440开发板中带的ADS测试源码。
整个阅读代码的过程是对这S3C2440的芯片手册和SD卡规范来看的,对于MM咪没有给出注释,其实和SD卡是大同小异。
由于是初次接触ARM对SD规范的认识也不是很深入,再加上自己水平有限,还不能完全读懂源代码,其中的肯定存在一些错误,欢迎大家一起交流讨论。
#include
#include
#include
"def.h"
#include
"option.h"
#include
"2440addr.h"
#include
"2440lib.h"
#include
"sdi.h"
#defineINICLK300000
#defineSDCLK24000000〃PCLK=49.392MHz
#defineMMCCLK15000000/PCLK=49.392MHz
#definePOL0
#defineINT1#defineDMA2
intCMD1$void);//SendcardstatusintCMDQvoid);
unsigned
int*Tx_buffer;
〃128[word]*16[blk]=8192[byte]
unsigned
int*Rx_buffer;
〃128[word]*16[blk]=8192[byte]
volatile
unsigned
int
rd
ent
;//读数据计数器
volatile
unsigned
int
wtent
;//写数据计数器
volatile
unsigned
int
block;
//读写块总数
volatile
unsigned
int
TR_end=0;
int
Wide=0;//0:
1bit,1:
4bitintMMC0;//0:
SD,1:
MMC
intMaker_ID;
charProduet_Name[7];
intSerial_Num;
volatileintRCA
voidTest_SDI(void)
{
U32save_rGPEUPsave_rGPECON
RCA=0;
MMC=O;
block=3072;〃3072Blocks=1.5MByte,
((2Block=1024Byte)*1024Block=1MByte)
save_rGPEUP=rGPEUP
save_rGPECONrGPECON
//**配置SD/MM控制器
rGPEUP=0xf83f;//SDCMD,SDDAT[3:
0]=>PUEn.
rGPECON=0xaaaaaaaa;//SDCMD,SDDAT[3:
0]
Uart_Printf("\nSDICardWriteandReadTest\n");
if(!
SD_card」nit())//等待SD卡初始化完成
return;
TR_Buf_new();//发送数据缓冲区初始化
Wt_Block();//写卡
Rd_Block();//读卡
View_Rx_buf();
if(MMC
TR_Buf_new[);
if(MMC
{
rSDICON|=(1<<5);//YH0519,MMCTypeSDCLK
Wt_Stream();
Rd_Stream();
View_Rx_buf();
}
Card_sel_desel(0);//Carddeselect
if(!
CMD9)
Uart_Printf("GetCSDfail!
!
!
\n");
rSDIDCON=0;//tark?
?
?
rSDICSTA=0xffff;
rGPEUP=save_rGPEUP
rGPECO=bave_rGPECON
}
voidTR_Buf_new(void)//发送数据缓冲区初始化
{
//--Tx&RxBufferinitialize
inti,j;
Tx_buffer=(unsignedint*)0x31000000;
j=0;
for(i=0;i<2048;i++)〃128[word]*16[blk]=8192[byte]
*(Tx_buffer+i)=i+j;
Flush_Rx_buf();
}
voidFlush_Rx_buf(void)//接收数据缓冲区清0
//--FlushingRxbuffer
inti;
Rx_buffer=(unsignedint*)0x31800000;
for(i=0;i<2048;i++)〃128[word]*16[blk]=8192[byte]
*(Rx_buffer+i)=0;
Uart_Printf("EndRxbufferflush'n");
}
voidView_Rx_buf()
{
//--DisplayRxbuffer
inti,error=0;
Tx_buffer=(unsignedint*)0x31000000;
Rx_buffer=(unsignedint*)0x31800000;
Uart_Printf("CheckRxdata\n");
for(i=0;i<128*block;i++)
{
if(Rx_buffer[i]!
=Tx_buffer[i])
{
Uart_Printf("\nTx/Rxerror\n");
Uart_Printf("%d:
Tx-0x%08x,Rx-0x%08x\n",i,Tx_buffer[i],Rx_buffer[i]);
error=1;
break;
}
if(!
error)
{
Uart_Printf("\nTheTx_bufferissametoRx_buffer!
\n");
Uart_Printf("SDCARDWriteandReadtestisOK!
\n");
}
}
voidView_Tx_buf(void)
{
}
intSD_card_init(void)//SD卡初始化
{
//--SDcontroller&cardinitialize
inti;
/*ImportantnoticeforMMCtestcondition*/
/*Cmd&Datalinesmustbeenabledbypullupresister*/
rSDIPRE=PCLK(INICLK)-1;//400KHz
Uart_Printf("Init.Frequencyis%dHz\n",(PCLK;rSDIPREH)));
rSDICON=(1<<4)|1;//先传高位,再传低位,使能CLK
rSDIFSTA=rSDIFSTA|(1<<16);//SDIFIFOstatusregister,FIFO复位
rSDIBSIZE=0x200;//SDIblocksizeregister,设置每块大小为
512byte(128word)
rSDIDTIMER=0x7fffff;//SDIdata/busytimerregister,设置超时
周期
for(i=0;i<0x1000;i++);//延时,CARD!
身初始化需要74个CLK
CMD0();//发送CMD0
Uart_Printf("Inidle\n");
//--CheckMMCcardOCR
if(Chk_MMC_OCR
{
Uart_Printf("InMMCready\n");
MMC1;
gotoRECMD2
}
Uart_Printf("MMCcheckend!
!
\n");
//--CheckSDcardOCR
if(Chk_SD_OCR
Uart_Printf("InSDready\n");
else
{
Uart_Printf("Initializefail'nNoCardassertion\n");
return0;
}
RECMD2
//检查连接的卡,识别卡的状态
rSDICARG=0x0;//CMD2(stuffbit)rSDICCON(0x1«10)|(0x1<<9)|(0x1<<8)|0x42;//CMD2为长应答并等待应答
开始发
//送CMD2命令卡发回CID寄存器(保存了生产厂家/时间/批号等等),产生
RSP2
//检查CMD是否成功发送并收到响应
if(!
Chk_CMDen(2,1))
gotoRECMD2//CMD2出错,重新发送
rSDICSTA=0xa00;//清除命令和应答结束标志位
Uart_Printf("Endid\n");
RECMD3
//--发送CMD3给卡分配RCA,
rSDICARG=MMC<16;//CMD3参数,MMC设置RCA,SD:
请求发RCArSDICCON(0x1<<9)|(0x1<<8)|0x43;//CMD3为短应答并等待应答,开始发//送CMD3,MMC设置RCA产生RSP1,SD(设置RCA产生RSP6
//检查CMD是否成功发送并收到响应
if(!
Chk_CMDen((3,1))
gotoRECMD3//CMD3出错,重新发送
rSDICSTA=OxaOO;//清除命令和应答结束标志位
//--PublishRCA
if(MMC{
RCA=1;
rSDIPRE=(PCLKMMCCLK1;
Uart_Printf("MMCFrequencyis%dHz\n",(PCLK(rSDIPREM)));
}
else
{
RCA=(rSDIRSP0&0xffff0000)>>16;//回读RCA卡被分配RCAf进入
//TransferMODE,准备读写
Uart_Printf("RCA=0x%x\n"RCA;
rSDIPRE=PCLK(SDCLK1;//Normalclock=25MHz
Uart_Printf("SDFrequencyis%dHz\n",(PCLK(rSDIPREM)));
}〃--State(stand-by)check
//根据SD规范,rSDIRSP0高16位存储RCA低16位存储CARD勺状态
if(rSDIRSP0&0x1e00!
=0x600)//检查CARD^态,不是处于stand-by
状态
gotoRECMD3////未就绪,重新发送CMD3
UartPrintf("Instand-by\n");
Card_sel_desel
(1);//Select
if(!
MMC〃若位SD卡,设置4bit的数据传输模式
Set_4bit_bus();
else//若位MMC卡设置1bit的数据传输模式
Set_1bit_bus();
return1;
}
voidCard_sel_desel(charsel_desel)
{
//--Cardselectordeselect
if(sel_desel)//选择该卡
{
RECMDS7//送CMD7表示选择该卡,准备读写,产生RSP1.
rSDICARG=RCA<16;//CMD7参数(RCA,stuffbit),其中高16位为RCArSDICCON=(0x1<<9)|(0x1<<8)|0x47;//CMD7为短应答并等待应答,开始发//送CMD选择该卡,准备读写,产生RSP1
//检查CMD是否成功发送并收到响应
if(!
ChkCMDer((7,1))
gotoRECMDS7//出错,重新发送
rSDICSTA=0xa00;//清除命令和应答结束标志位
//检查是否处于transfermode
if(rSDIRSP0&0x1e00!
=0x800)
gotoRECMDS7//不处于transfermode,重新发送CMD7
}
else//卸载该卡
{
RECMDD7
rSDICARG=0<<16;//CMD7参数(RCA,stuffbit),其中高16位为RCArSDICCON=(0x1«8)|0x47;//无应答并,并开始发送CMD7
//检查CMD是否成功
if(!
Chk_CMDer((7,0))
gotoRECMDD7//失败,重新卸载
rSDICSTA=0x800;////清除命令结束标志位
}
}
void__irqRd_Int(void)//读中断函数
{
U32i,status;
status=rSDIFSTA
if((status&0x200)==0x200)//检查接收FIFO最后是否有数据到来
{
for(i=(status&0x7f)/4;i>0;i--)
{
*Rx_buffer++=rSDIDAT
rd_cnt++;
}
rSDIFSTA=rSDIFSTA&)x200;//清RxFIFOLastdataReady标志位
}
elseif((status&0x80)==0x80)//检查HalfFULLinterrupt标志,
只要大于31个字节,就会将该标志置1
{
for(i=0;i<8;i++)
{
*Rx_buffer++=rSDIDAT
rd_cnt++;
}
}
ClearPending(BIT_SDI);//清零源中断挂起寄存器和中断挂起寄存器
}void__irqWt_Int(void)//写中断函数
ClearPending(BIT_SDI);//清零源中断挂起寄存器和中断挂起寄存器
rSDIDAT=*Tx_buffer++;
wt_cnt++;
if(wt_cnt==128*block)
{
rINTMSK|=BIT_SDI;//屏蔽BIT_SDI中断
rSDIDAT=*Tx_buffer;
TR_end=1;
}
}
void__irqDMA_end(void)
{
ClearPending(BIT_DMA0//清零源中断挂起寄存器和中断挂起寄存器
TR_end=1;
}
voidRd_Block(void)
{
U32mode;
intstatus;
rd_cnt=0;
Uart_Printf("Blockreadtest[Pollingread]\n");
mode=0;
rSDIFSTA=rSDIFSTA(1<<16);//复位FIFO
if(mode!
=2)
rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)|(2<<12)|(block<<0);//YH040220
//设置数据控制寄存器:
字传输,块数据传输,4bit数据传输,开始数据传输,数据发送模〃式,共读block个块
rSDICARG=0x0;//CMD17/18地址参数
RERDCMD
switch(mode
{
casePOL:
if(block<2)//SINGLE_READ写单块
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x51;//CMD17为短应答并等待应答,开始发
//送CMD1单块读命令,开始读,产生RSP1
if(!
Chk_CMDend7,1))//--CheckendofCMD17
gotoRERDCMD//失败,继续发送
}
else//MULTI_READ,读多块
rSDICCON=(Ox1«9)|(0x1<<8)|0x52;//CMD18为短应答并等待应答,开始发
//送CMD1多块读命令,开始读,产生RSP1
if(!
Chk_CMDend8,1))//--CheckendofCMD18
gotoRERDCMD//失败,继续发送
}
rSDICSTA=0xa00;//清命令和应答结束标志
while(rd_cnt<128*block)//512块个字节
{
if((rSDIDSTA0x20)==0x20)//是否超时
{
rSDIDSTA=(0x1<<0x5);//清超时标志位
break;
}
status=rSDIFSTA
if((status&0x1000)==0x1000)//FIFO非空
{
*Rx_buffer++=rSDIDAT
rd_cnt++;
}
}
break;
caseINT:
plSR_SDI=(unsigned)Rd」nt;
rINTMSK=~(BIT_SDI);//屏蔽除所有其他中断
rSDIIMSK=5;//开启Last&RxFIFOhalf中断.
if(block<2)//SINGLE_READ
{
rSDICCON=(Ox1«9)|(0x1<<8)|0x51;//CMD17为短应答并等待应答,开始发
//送CMD1单块读命令,开始读,产生RSP1
if(!
Chk_CMDer(d7,1))//--CheckendofCMD17
gotoRERDCMD//失败,继续发送
}
else//MULTI_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52;//CMD18为短应答并等待应答,开始发
//送CMD1多块读命令,开始读,产生RSP1
if(!
ChkCMDer(d8,1))//--CheckendofCMD18
gotoRERDCMD//失败,继续发送
}
rSDICSTA=0xa00;//清命令和应答结束标志
while(rd_cnt<128*block);
rINTMSK
|=(BIT_SDI);//屏蔽BIT_SDI中断
rSDIIMSK
=0;//屏蔽所有中断
break;
caseDMA
pISR_DMA0=(unsigned)DMA_end
rINTMSK
=~(BIT_DMA0
rSDIDCON=rSDIDCON1<<24);//YH040227,Burst4Enable
rDISRC0
=(int)(SDIDAT;//SDIDAT
rDISRCC0
=(1<<1)+(1<<0);//APB,fix
rDIDST0
=(U32)(Rx_buffer);//Rx_buffer
rDIDSTC0
=(0<<1)+(0<<0);//AHB,inc
rDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)
+(1<<22)+(2<<20)+128*block;
rDMASKTRIG0=(0<<2)+(1<<1)+0;//no-stop,DMA2channelon,no-sw
trigger
rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<15)|(<<12)|(block<<0);
if(block<2)//SINGLE_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x51;//sht_resp,wait_resp,
CMD17
if(!
Chk_CMDend7,1))//--CheckendofCMD17
gotoRERDCM|D
}
else//MULTI_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52;//sht_resp,wait_resp,
CMD18
if(!
Chk_CMDer(d8,1))//--CheckendofCMD18
gotoRERDCMD
}
rSDICSTA=0xa00;//Clearcmd_end(withrsp)
while(!
TR_end;
1<<14)|(2
dat,start,
dat,start,
〃Uart_Printf("rSDIFSTA=0x%x\n",rSDIFSTA);
rINTMSK|=(BIT_DMA0
TR_end=0;
rDMASKTRIGO=(1<<2);//DMA0stop
break;
default:
break;
}
//--CheckendofDATA
if(!
Chk_DATenQ)
Uart_Printf("daterror'n");
rSDIDCON=rSDIDCO&~(7<<12);
rSDIFSTA=rSDIFSTA&0x200;//ClearRxFIFOLastdataReady,YH040221rSDIDSTA=0x10;//CleardataTx/Rxenddetect
if(block>1)
{
RERCMD12
//--S
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SD 读写 包括 模式