<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > s3c2440的SD/MMC的應用

s3c2440的SD/MMC的應用

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò ) 收藏

SD(全名為Secure Digital Memory Card,安全數碼卡),是一種存儲卡的標準,它被廣泛地用于便攜式設備上,如數碼相機、個(gè)人數字助理(PDA)和多媒體播放器等。它的技術(shù)是基于MMC(MultiMedia Card)格式,因此SD兼容MMC。

s3c2440集成了SD控制器,可以方便地讀寫(xiě)SD、MMC和對SDIO進(jìn)行操作。在這里,我們只研究對SD/MMC的操作。

要想能夠使s3c2440正確讀寫(xiě)SD/MMC,就首先要清楚SD的規范協(xié)議,由于SD兼容MMC,所以?xún)烧叩膮f(xié)議差別不大。SD的協(xié)議較為繁瑣,下面只簡(jiǎn)略介紹最基本的內容:

對SD進(jìn)行操作包括兩個(gè)階段:卡的識別和卡的數據傳輸。主機通過(guò)各種命令對SD進(jìn)行操作,絕大多數命令都需要SD進(jìn)行應答響應。在卡的識別階段,用到的命令只有CMD1(得到主機的操作電壓)、CMD2(得到卡的識別碼)和CMD3(配置或得到卡的相對地址),其中也可以使用CMD0命令使卡進(jìn)入空閑狀態(tài)。CMD1只能用于MMC,SD要用ACMD41輔助命令。在正確配置完該階段后,卡進(jìn)入待機狀態(tài)。在卡的數據傳輸階段可以完成對卡內存地址的讀寫(xiě)等操作。

卡內還配備了幾個(gè)寄存器,主要有OCR寄存器,用于配置操作電壓范圍,使用命令CMD1可以獲得;CID寄存器,用于得到卡的基本信息,使用命令CMD2或CMD10可以獲得;CSD寄存器,用于提供卡特性信息,使用CMD9可以獲得;RCA寄存器,保存卡的相對地址。另外在卡應答響應信息中,會(huì )包括卡的狀態(tài)信息,主機可以利用該信息獲知卡的各種狀態(tài),以便進(jìn)一步操作。

s3c2440只要按照SD的協(xié)議去操作,就能正確讀寫(xiě)SD。在初始化階段,要配置SDICON寄存器以及負責傳輸頻率的SDIPRE寄存器,并且還要等待一段時(shí)間,以保證初始化正確執行。在命令傳輸階段,SDICmdArg寄存器負責傳輸命令參數,SDICmgCon寄存器負責傳輸命令索引值,通過(guò)SDICmdSta寄存器可以獲知命令傳輸過(guò)程中的各種狀態(tài),命令的響應信息存儲在SDIRSPn中。在數據傳輸階段,SDIDTimer寄存器可以設置數據傳輸的超時(shí)時(shí)間,SDIBSize寄存器用于設置數據傳輸塊的大小,寄存器SDIDatCon和SDIDatSta用于數據傳輸的控制和狀態(tài),而數據是通過(guò)SDIDAT寄存器利用內部的FIFO來(lái)進(jìn)行傳輸的,其中寄存器SDIFSTA用于獲知FIFO的各種狀態(tài)。

下面就具體給出一個(gè)讀寫(xiě)SD的測試實(shí)例。該段程序是先對SD進(jìn)行寫(xiě)操作,然后再從SD中讀取該組數據,檢查寫(xiě)入的數據和讀取的數據是否一致,其中我們利用UART來(lái)獲知一些必要的傳輸狀態(tài)。我們只用查詢(xún)方式進(jìn)行數據傳輸,并且使用的是塊操作模式。該段程序是針對MMC所編寫(xiě),并不適用于SD,但只需做少許改動(dòng)(在設置相對地址的地方)就可以用于SD。


unsigned int *Tx_buffer;
unsigned int *Rx_buffer;

…………

void Main(void)
{
int i;
int tempSta;
int block=16;//傳輸數據塊大小
char flag;
int response;

//UART0的基本配置
…………

//SDI端口配置
rGPEUP = 0xf83f;//SDCMD, SDDAT[3:0]上拉有效.
rGPECON = 0xaaa<<10;//SDCMD, SDDAT[3:0], SDCLK

//初始化SDI
rSDIPRE=124;//SDI初始階段傳輸頻率為400KHz
rSDICON=(3<<4)|1;//SDCLK為MMC類(lèi)型,字節順序為T(mén)ype B,使能SDCLK輸出
rSDIFSTA|=1<<16;//FIFO復位
rSDIBSIZE=0x200;//傳輸數據塊大小為512字節(128字)
rSDIDTIMER=0x7fffff;//設置數據傳輸的超時(shí)時(shí)間

flag=1;

for(i=0;i<0x1000;i++)
;//等待74個(gè)SDCLK

//卡的識別階段
//CMD0GO_IDLE_STATE
rSDICARG=0x0;//設置CMD0參數為0
rSDICCON=(1<<8)|0x40;//無(wú)響應,開(kāi)始傳輸CMD0,命令信息為命令索引值加0x40
//等待CMD0結束
tempSta=rSDICSTA;//讀取命令狀態(tài)寄存器
while((tempSta&0x800)!=0x800)//判斷命令是否結束
tempSta=rSDICSTA;//沒(méi)有結束,則繼續等待
rSDICSTA=tempSta;//清命令狀態(tài)
rSDICSTA=0xa00;//

//CMD1CEND_OP_COND
for(i=0;i<200;i++)
{
rSDICARG=0xff8000;//CMD1參數:2.7V~3.6V
rSDICCON=(0x1<<9)|(0x1<<8)|0x41;//有響應,開(kāi)始傳輸CMD1

//檢查命令狀態(tài)
tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;//檢查命令傳輸是否結束或超時(shí)

if( (tempSta&0xf00) == 0xa00 )//如果命令傳輸沒(méi)有錯誤或超時(shí)
{
if((rSDIRSP0>>16)==0x80ff)//OCR內容正確,且不忙
{
rSDICSTA=0xa00;//清命令狀態(tài)
break;//退出循環(huán)
}
}
}

if(i>190)//沒(méi)有檢測到MMC
{
flag=0;//清標志
while(!(rUTRSTAT0 & 0x2));
rUTXH0=0x66;//向UART0發(fā)送信息,表示無(wú)MMC
rGPBDAT =~0x1e0;//亮4個(gè)LED
}
else//檢測到了MMC
{
rSDICSTA=0xa00;//清命令狀態(tài)

//CMD2ALL_SEND_CID
while(flag)
{
rSDICARG=0x0;//CMD2無(wú)需參數
rSDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x42;//有128位長(cháng)響應,開(kāi)始傳輸CMD2
tempSta=rSDICSTA;
while(!(((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400)))
tempSta=rSDICSTA;//檢查命令傳輸是否結束或超時(shí)

if( (tempSta&0x1f00) == 0xa00 )//如果命令傳輸沒(méi)有錯誤或超時(shí)
{
rSDICSTA=0xa00;
break;//退出循環(huán)體
}
rSDICSTA=0xF<<9;
}
//通過(guò)UART0輸出MMC的CID信息,一共128位
//在這里得到的CID信息為15 00 00 30 30 30 30 30 30 11 F1 01 11 28 29 ED
while(!(rUTRSTAT0 & 0x2));
rUTXH0=0xee;
response=rSDIRSP0;
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>24);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>16);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>8);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response);

response=rSDIRSP1;
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>24);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>16);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>8);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response);

response=rSDIRSP2;
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>24);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>16);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>8);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response);

response=rSDIRSP3;
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>24);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>16);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response>>8);
while(!(rUTRSTAT0 & 0x2));
rUTXH0=(char)(response);

//CMD3SET_RELATIVE_ADDR,設置卡的相對地址
while(flag)
{
rSDICARG=1<<16;//設置CMD3參數,即相對地址,為1
rSDICCON=(0x1<<9)|(0x1<<8)|0x43;//等待響應,開(kāi)始傳輸CMD3

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;
}

//卡的數據傳輸階段
rSDIPRE=2;//重新設置SDI的傳輸頻率,約為16MHz

//CMD13SEND_STATUS
//檢查當前狀態(tài)是否為待機狀態(tài),否則等待直到變?yōu)榇龣C狀態(tài)為止
while(flag)
{
rSDICARG=1<<16;//設置CMD13參數,即相對地址
rSDICCON= (0x1<<9)|(0x1<<8)|0x4d;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
if((rSDIRSP0 & 0x1e00)==0x600)
break;
}
rSDICSTA=0xF<<9;
}

//CMD7SELECT/DESELECT_CARD,把當前狀態(tài)從待機狀態(tài)變?yōu)閭鬏敔顟B(tài)
while(flag)
{
rSDICARG=1<<16;
rSDICCON= (0x1<<9)|(0x1<<8)|0x47;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( ((tempSta&0x1f00) == 0xa00) )// Check no error and tranfro state
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;
}

//CMD13SEND_STATUS
//檢查當前狀態(tài)是否為傳輸狀態(tài),否則等待直到變?yōu)閭鬏敔顟B(tài)為止
while(flag)
{
rSDICARG=1<<16;
rSDICCON= (0x1<<9)|(0x1<<8)|0x4d;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
if((rSDIRSP0 & 0x1e00)==0x800)
break;
}
rSDICSTA=0xF<<9;//clear all
}

//由于MMC是1位的總線(xiàn)寬,而系統默認就是1位總線(xiàn)寬,所以在這里無(wú)需改動(dòng)數據總線(xiàn)寬度

//為數據的讀寫(xiě),準備緩存數組
Tx_buffer=(unsigned int *)0x31000000;//發(fā)送數組
for(i=0;i<2048;i++)//512(一塊數據的字節數)×16(數據塊)=2048×4
*(Tx_buffer+i)=2*i+1;//寫(xiě)值

Rx_buffer=(unsigned int *)0x31800000;//接收數組
for(i=0;i<2048;i++)
*(Rx_buffer+i)=0;//清零

//寫(xiě)數據,查詢(xún)方式
rSDIFSTA |= 1<<16;//FIFO復位

rSDIDCON=(2<<22)|(1<<20)|(1<<17)|(1<<14)|(3<<12)|(block<<0);//字、塊發(fā)送
rSDICARG=0;//寫(xiě)入MMC的內存首地址

//CMD25WRITE_MULTIPLE_BLOCK,多塊寫(xiě)入命令
while(flag)
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x59;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;
}

//寫(xiě)入MMC內存數據
i=0;
while(i<128*block)
{
//檢查FIFO狀態(tài)
tempSta=rSDIFSTA;
if((tempSta&0x2000)==0x2000)//FIFO沒(méi)有滿(mǎn)
{
rSDIDAT=*Tx_buffer++;
i++;
}
}

//判斷數據是否發(fā)送正確
//檢查數據狀態(tài)
tempSta=rSDIDSTA;
while( !( ((tempSta&0x10)==0x10) | ((tempSta&0x20)==0x20) ))
tempSta=rSDIDSTA;//判斷數據傳輸是否結束或超時(shí)

if( (tempSta&0xfc) != 0x10 )//數據傳輸沒(méi)有結束
{
rSDIDSTA=0xec;//清狀態(tài)
while(!(rUTRSTAT0 & 0x2));
rUTXH0=0x88;//向UART0發(fā)送一個(gè)信息,表示SDI的某種錯誤
flag=0;//清標志,結束SDI的傳輸
}

if(flag)
{
rSDIDCON=rSDIDCON&~(7<<12);//清數據傳輸
rSDIDSTA=0x10;
}

//CMD12STOP_TRANSMISSION,結束傳輸,回到傳輸狀態(tài)
while(flag)
{
rSDIDCON=(1<<18)|(1<<17)|(0<<16)|(1<<14)|(1<<12)|(block<<0);//忙檢查
rSDICARG=0x0;//CMD12無(wú)參數
rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;
}

//檢查是否忙
if(flag)
{
tempSta=rSDIDSTA;
while( !( ((tempSta&0x08)==0x08) | ((tempSta&0x20)==0x20) ))
tempSta=rSDIDSTA;

if( (tempSta&0xfc) != 0x08 )//數據傳輸不是正確結束
{
flag=0;//清標志,結束SDI傳輸
}
rSDIDSTA=0xf4;
}

//讀取MMC內存數據
if(flag)
{
rSDIFSTA|=(1<<16);//FIFO復位
rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(1<<14)|(2<<12)|(block<<0);//字、塊接收
rSDICARG=0;//設置讀取MMC的內存首地址,要與寫(xiě)入時(shí)的首地址一致
}

//CMD18READ_MULTIPLE_BLOCK,多塊讀命令
while(flag)
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;//clear all
}

if(flag)
{
i=0;
//讀MMC內存
while(i<128*block)
{
if((rSDIDSTA&0x20)==0x20)//判斷是否超時(shí)
{
rSDIDSTA=(0x1<<0x5);//清狀態(tài)
flag=0;//清標志,退出
break;
}
tempSta=rSDIFSTA;
if((tempSta&0x1000)==0x1000)//檢查FIFO是否為空
{
*Rx_buffer++=rSDIDAT;
i++;
}
}

rSDIDCON=rSDIDCON&~(7<<12);//清數據傳輸
rSDIFSTA &= 0x200;//清FIFO
rSDIDSTA=0x10;//清數據狀態(tài)
}

//CMD12STOP_TRANSMISSION,結束傳輸,回到傳輸狀態(tài)
while(flag)
{
rSDICARG=0x0;
rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;

tempSta=rSDICSTA;
while( !( ((tempSta&0x200)==0x200) | ((tempSta&0x400)==0x400) ))
tempSta=rSDICSTA;

if( (tempSta&0x1f00) == 0xa00 )
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;//clear all
}

if(flag)
{
//比較兩個(gè)數組的內容
Tx_buffer=(unsigned int *)0x31000000;
Rx_buffer=(unsigned int *)0x31800000;

for(i=0;i<128*block;i++)
{
if(Rx_buffer[i] != Tx_buffer[i])//有不相等的情況
{
while(!(rUTRSTAT0 & 0x2));
rUTXH0=0x44;//向UART0發(fā)送一個(gè)信息,表示SDI的某種錯誤
break;
}
}
}

//CMD7SELECT/DESELECT_CARD,把當前狀態(tài)從傳輸狀態(tài)變?yōu)榇龣C狀態(tài)
while(flag)
{
rSDICARG=0<<16;//不帶參數
rSDICCON= (0x1<<8)|0x47;//無(wú)回復

tempSta=rSDICSTA;
if( (tempSta&0x800) != 0x800 )
{
rSDICSTA=0xa00;
break;
}
rSDICSTA=0xF<<9;
}


rSDICSTA=0x800;//結束SD
rSDIDCON=0;
rSDICSTA=0xffff;

if(flag)
rGPBDAT = ~0x60;//SD數據傳輸正確,亮2個(gè)LED
else
rGPBDAT =~0xe0;//SD數據傳輸失敗,亮3個(gè)LED
}

while(1)
;
}


關(guān)鍵詞: s3c2440SDMM

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>