📄 sd.c
字号:
while((i<50) && (!Chk_CMDend(6, 1))); // ACMD6
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
if (i < 50)
{
Uart_Printf("****1bit bus****\n");
return 1;
}
else
{
return 0;
}
}
static void TR_Buf_new(void)
{
//-- Tx & Rx Buffer initialize
int i;
for(i = 0; i < MAX_RWBUFFER_BLOCKNUM * WORDS_PER_BLOCK; i++) //128[word]*16[blk]=8192[byte]
{
*(Tx_buffer + i) = i;
}
for(i = 0; i < MAX_RWBUFFER_BLOCKNUM * WORDS_PER_BLOCK; i++) //128[word]*16[blk]=8192[byte]
{
*(Rx_buffer + i) = 0;
}
}
static void View_Rx_buf(U32 blocknum)
{
//-- Display Rx buffer
int i;
for(i = 0; i < WORDS_PER_BLOCK * blocknum; i++)
{
Uart_Printf("Rx[%02x] = %08x\n", i, *(Rx_buffer+i));
}
}
static void View_Tx_buf(U32 blocknum)
{
//-- Display Tx buffer
int i;
for(i = 0; i < WORDS_PER_BLOCK * blocknum; i++)
{
Uart_Printf("Tx[%02x] = %08x\n", i, *(Tx_buffer+i));
}
}
static void Check_RxTx_buf(U32 blocknum)
{
//-- Check Rx/Tx buffer
int i, error = 0;
Uart_Printf("----Check Rx/Tx data----\n");
for(i=0; i < WORDS_PER_BLOCK * blocknum; i++)
{
if(*(Rx_buffer+i) != *(Tx_buffer+i))
{
Uart_Printf("\nTx/Rx error:");
Uart_Printf("%d:Tx-0x%08x, Rx-0x%08x\n",i,*(Tx_buffer+i), *(Rx_buffer+i));
error = 1;
//break;
}
}
if(!error)
{
Uart_Printf("The Tx_buffer is the same to Rx_buffer!\n");
Uart_Printf("SD CARD Write and Read test is Successful!\n");
}
}
static int Chk_DATend(void)
{
int i=0,finish;
finish = rSDIDSTA;
while( !( ((finish&0x10) == 0x10) | ((finish&0x20) ==0x20) | (i>500) )) // Chek timeout or data end
{
finish = rSDIDSTA;
i++;
}
if( ((finish&0x2) == 0x2) || ((finish&0x1) == 0x1) )
{
Delay(200);
}
if( (finish&0xf0) != 0x10 ) //wangq,reserved 位也可能为1!!
{
Uart_Printf("DATA Error:SDIDatSta=0x%x\n", finish);
//rSDIDSTA=0xec; // Clear error state
rSDIDSTA = 0xf8; // Clear error state,wangq
return 0;
}
return 1;
}
static int Chk_BUSYend(void)
{
int finish;
finish = rSDIDSTA;
while( !( ((finish&0x08)==0x08) | ((finish&0x20)==0x20) ))
{
finish = rSDIDSTA;
}
if( (finish&0xf8) != 0x08 )
{
Uart_Printf("DATA Error:SDIDSTA=0x%x\n", finish);
//rSDIDSTA=0xf4; //clear error state
rSDIDSTA = 0xf8; //clear error state,wangq
return 0;
}
return 1;
}
int SD_Card_Init(card_desc *CardInfo)
{
//-- SD controller & card initialize
int i;
card_desc *pCardInfo = CardInfo;
pCardInfo->RCA = 0;
/* Important notice for MMC test condition */
/* Cmd & Data lines must be enabled by pull up resister */
SD_Set_IOPort();
rSDIPRE = PCLK/(INICLK) - 1; // 400KHz
Uart_Printf("Initial Frequency is %dKHz\n",(PCLK/(rSDIPRE+1))/1000 );
rSDICON = (1<<4)|1; // Type B, clk enable
rSDIFSTA = rSDIFSTA|(1<<16); // YH 040223 FIFO reset
rSDIBSIZE = 0x200; // 512byte(128word)
rSDIDTIMER = MAX_DATABUSY_TIMEOUT; // Set timeout count
for(i = 0; i < 0x1000; i++); // Wait 74 SDCLK for MMC card
CMD0();
Uart_Printf("Card is in idle\n");
/*
//-- Check MMC card OCR
if (Chk_MMC_OCR() == ENUM_CARD_TYPE_MMC) //ACMD1
{
Uart_Printf("MMC check end!!\nIn MMC ready\n");
pCardInfo->Card_Type = ENUM_CARD_TYPE_MMC;
goto RECMD2;
}
else
{
pCardInfo->Card_Type = ENUM_CARD_TYPE_SD;
}
//-- Check SD card OCR
if (!CMD8())
{
return 0;
}
*/
pCardInfo->Card_Type = ENUM_CARD_TYPE_SD;
i = Chk_SD_OCR(); //ACMD41
if (i == 1)
{
//Uart_Printf("----SD Card is Ready----\n");
pCardInfo->Card_Capacity_Stat = ENUM_High_Capacity;
}
else if (i == 2)
{
pCardInfo->Card_Capacity_Stat = ENUM_Standard_Capacity;
}
else
{
return 0;
}
RECMD2:
//-- Check attached cards, it makes card identification state
if(CMD2()) //Get_CID
{
pCardInfo->Maker_ID = ((rSDIRSP0 & 0xff000000) >> 24);
pCardInfo->Product_Name[0] = (rSDIRSP0&0xff0000)>>16;
pCardInfo->Product_Name[1] = (rSDIRSP0&0xff00)>>8;
pCardInfo->Product_Name[2] = rSDIRSP0&0xff;
pCardInfo->Product_Name[3] = (rSDIRSP1 & 0xff000000) >> 24;
pCardInfo->Product_Name[4] = (rSDIRSP1&0xff0000)>>16;
pCardInfo->Product_Name[5] = (rSDIRSP1&0xff00)>>8;
pCardInfo->Product_Name[6] = rSDIRSP1&0xff;
pCardInfo->Product_Name[7] = 0;
pCardInfo->Serial_Num = ((rSDIRSP2 & 0xffffff) << 8) | ((rSDIRSP3 & 0xff000000) >> 24);
pCardInfo->Manufacturing_Date[0] = 2000+((rSDIRSP3&0xff000)>>12);
pCardInfo->Manufacturing_Date[1] = (rSDIRSP3&0xf00)>>8;
}
else
{
return 0;
}
if(CMD3() != 0) // Get_RCA
{
if(pCardInfo->Card_Type == ENUM_CARD_TYPE_MMC)
{
pCardInfo->RCA = 1;
rSDIPRE=(PCLK/MMCCLK)-1; // YH 0812, Normal clock=20MHz
Uart_Printf("MMC Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));
}
else
{
pCardInfo->RCA = ( rSDIRSP0 & 0xffff0000 )>>16;
Uart_Printf("RCA = 0x%x\n",pCardInfo->RCA);
rSDIPRE = (PCLK/SDCLK) - 1; // Normal clock=25MHz
Uart_Printf("Now SD Frequency is %dMHz\n",(PCLK/(rSDIPRE+1))/1000000);
}
}
else
{
return 0;
}
//CMD13(); // Get card status
Card_Select(pCardInfo->RCA); // 选中当前卡
//--设置总线位数
if(pCardInfo->Card_Type == ENUM_CARD_TYPE_SD)
{
SetBus(pCardInfo->RCA, Wide);
}
else
{
Set_1bit_bus(pCardInfo->RCA);
}
return 1;
}
static void __irq DMA_end(void)
{
ClearPending(BIT_DMA0);
TR_end = 1;
}
void __irq IsrEINT8_23(void)
{
rINTMSK = rINTMSK | BIT_EINT8_23; // 关中断
if ( rEINTPEND & (1<<16) )
{
Uart_Printf("\nSD Card (EINT16) Detect!!!\n");
}
ClearPending(BIT_EINT8_23); // 清中断状态标志位
rEINTPEND = (1<<16); // 清外部中断状态标志位--------重要
SD_CardIn = 1;
rINTMSK = ~(BIT_EINT8_23); // 开EINT8_23中断
}
int SD_Rd_Block(card_desc *CardInfo, U32 mode, U32 addr, U32 blocknum)
{
int status;
int i = 0;
int rd_cnt = 0;
const U32 cc = 1;
//----- Reset the FIFO -----
rSDIFSTA = rSDIFSTA|(1<<16); // FIFO reset
if(mode!=2)
rSDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)|(2<<12)|(blocknum<<0); //YH 040220
//Word Rx, Rx after cmd, blk, 4bit bus, Rx start, blk num, data start, data transmit mode
rSDICARG = addr; // CMD17/18(addr)读地址
switch(mode)
{
case POL:
if(blocknum<2) // SINGLE_READ
{
do
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x51; // sht_resp, wait_resp, dat, start, CMD17
i++;
}
while(!Chk_CMDend(17, 1) && (i<50)); //-- Check end of CMD17
if(i == 50)
{
Uart_Printf("CMD18 Failed\n");
return 0;
}
}
else // MULTI_READ
{
do
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52; // sht_resp, wait_resp, dat, start, CMD18
i++;
}
while(!Chk_CMDend(18, 1) && (i<50)); //-- Check end of CMD18
if(i == 50)
{
Uart_Printf("CMD18 Failed\n");
return 0;
}
}
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
while(rd_cnt < (128*blocknum)) // 512*block bytes
{
//Uart_Printf("***rd_cnt:%d dat:%d\n",rd_cnt,rSDIDAT);
if ((rSDIDSTA & 0x20) == 0x20) // Check timeout
{
//rSDIDSTA=(0x1<<0x5); // Clear timeout flag
rSDIDSTA = (0x1<<5); // Clear timeout flag,wangq
Uart_Printf("Read Error,timeout!!!\n");
break;
}
status = rSDIFSTA;
if((status&0x1000) == 0x1000) // Is Rx data?
{
//Uart_Printf("Number of data(byte) in FIFO:%d \n",status&0x7f);
//for(i=0; i < (status&0x7f); i++)
{
*(Rx_buffer+rd_cnt) = rSDIDAT;
//Uart_Printf("rd_cnt:%d dat:%d\n", rd_cnt, *(Rx_buffer+rd_cnt));
rd_cnt++;
}
}
}
break;
case INT:
return 0;
/*
pISR_SDI=(unsigned)Rd_Int;
rINTMSK = ~(BIT_SDI);
rSDIIMSK=5; // Last & Rx FIFO half int.
if(blocknum<2) // SINGLE_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x51; // sht_resp, wait_resp, dat, start, CMD17
if(!Chk_CMDend(17, 1)) //-- Check end of CMD17
goto RERDCMD;
}
else // MULTI_READ
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52; // sht_resp, wait_resp, dat, start, CMD18
if(!Chk_CMDend(18, 1)) //-- Check end of CMD18
goto RERDCMD;
}
rSDICSTA=0xa00; // Clear cmd_end(with rsp)
while(rd_cnt<128*blocknum);
rINTMSK |= (BIT_SDI);
rSDIIMSK=0; // All mask
break;
*/
case DMA:
pISR_DMA0 = (unsigned)DMA_end;
rINTMSK = ~(BIT_DMA0); // 开DMA0中断
rSDIDCON = rSDIDCON | (1<<24); //YH 040227, Burst4 Enable
//----- Initialize the DMA channel for input mode -----
rDISRC0 = (int)(SDIDAT); // source=SDIDAT
rDISRCC0 = (1<<1) | (1<<0); // APB, fix
rDIDST0 = (U32)(Rx_buffer); // Destination=Rx_buffer
rDIDSTC0 = (0<<1) | (0<<0); // TC reaches 0 Interrupt,AHB, inc
rDCON0 = (cc<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+(128*blocknum);
//handshake, sync PCLK, TC int, A unit tx, single service, SDI, H/W request,
//auto-reload off, word, 128blk*num
rSDIDCON = (2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(2<<12)|(blocknum<<0);
// Word Rx, Rx after rsp, blk, 4bit bus, dma enable, Rx start, blk num, Data start, data receive mode, YH 040220
i = 0;
if(blocknum<2) // SINGLE_READ
{
do
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x51; // sht_resp, wait_resp, dat, start, CMD17
i++;
}
while(!Chk_CMDend(17, 1) && (i<50)); //-- Check end of CMD17
if(i == 50)
{
Uart_Printf("CMD18 Failed\n");
return 0;
}
}
else // MULTI_READ
{
do
{
rSDICCON=(0x1<<9)|(0x1<<8)|0x52; // sht_resp, wait_resp, dat, start, CMD18
i++;
}
while(!Chk_CMDend(18, 1) && (i<50)); //-- Check end of CMD18
if(i == 50)
{
Uart_Printf("CMD18 Failed\n");
return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -