📄 sdi.c
字号:
SDIO_Command(StartAddr<<9, WRITE_MULTIPLE_BLOCK, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while((Check_CMDend(WRITE_MULTIPLE_BLOCK, 1) !=1));
}
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
// printf("\nBlock zise=%x\n",Card_OneBlockSize/4*BlockNum);
// timpcount = rSDIDCNT;
while(wt_cnt < (Card_OneBlockSize/4*BlockNum))
{
// status = rSDIFSTA;
if(rSDIFSTA & TX_FIFO_AVAILABLE_DETECT)
{
if ( rSDIDSTA & (1<<5) );
else {
rSDIDAT = *Tx_buffer++;
//timpcount = timpcount -4;
// if ( timpcount == rSDIDCNT )
// {
// //printf ( "[%d]rSDIDCNT mismatch %x,%x\n", wt_cnt, timpcount, rSDIDCNT );
// printf ( "[%d]rSDIDCNT same %x,%x, state:%x,FIFO:%x\n", wt_cnt, timpcount, rSDIDCNT, rSDIDSTA, rSDIFSTA );
// //timpcount = rSDIDCNT;
// }
// timpcount = rSDIDCNT;
wt_cnt++;
// timeout_count=0;
}
}
// else if(rSDIDSTA & (1<<5) ) {
// if ( timeout_count++ > 100 ) {
// rSDIFSTA |= (1<<16);
// rSDIDSTA |= (1<<5);
// }
// }
}
// printf("\nWrite count=%x\n",wt_cnt);
break;
case INT:
// printf("\nInterrupt mode data write\n");
pISR_SDI_CF=(unsigned)Wt_Int;
rSDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|(BlockNum<<0);
Timer_Start(3);
if(BlockNum<2)//single block
{
do { // StartAddr * 512
SDIO_Command(StartAddr<<9, WRITE_BLOCK_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while((Check_CMDend(WRITE_BLOCK_CMD, 1) !=1));
}
else//multi block
{
do {
SDIO_Command(StartAddr<<9, WRITE_MULTIPLE_BLOCK, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while((Check_CMDend(WRITE_MULTIPLE_BLOCK, 1) !=1));
}
rSDICSTA |= DATA_TIMEOUT|CMD_END|RESP_END; // Clear cmd_end(with rsp)
rINTMSK &= ~(BIT_SDI_CF);
rINTSUBMSK &=~(BIT_SUB_SDI);
rSDIIMSK=0x10; // Tx FIFO half int.
while(!TR_end);
rINTSUBMSK |= (BIT_SUB_SDI);
rINTMSK |= (BIT_SDI_CF);
TR_end=0;
rSDIIMSK=0; // All mask
break;
case DMA:
// printf("\nDMA mode data write\n");
pISR_DMA0=(unsigned)DMA_end;
rINTMSK&=~(BIT_DMA0);
//rINTSUBMSK&=~(BIT_SUB_DMA0);
rDISRC0 = (int)(Tx_buffer);
rDISRCC0 = (0<<1) | (0<<0);
rDIDST0 = (U32)(SDIDAT);
rDIDSTC0 = (1<<1)|(1<<0);
rDCON0 = (1<<31)|(0<<30)|(1<<29)|(1<<28)|(0<<27)|(1<<24)|(1<<22)|(2<<20) | (128*BlockNum)/4;
rDMASKTRIG0 = (0<<2)|(1<<1)|0; //no-stop, DMA0 channel on, no-sw trigger
rDMAREQSEL0 = (10 <<1) | 1;
if(Wide!=0)
rSDIDCON |= WIDE_BUS_EN;
else
rSDIDCON &= ~WIDE_BUS_EN;
rSDIDCON |=BURST4_EN|WORD_TRANSFER|TRANS_AFTER_RESP|BLOCK_TRANSFER|DMA_EN|BlockNum;
rSDIDCON |= DATA_TRANSMIT_MODE|DATA_TRANSMIT_START;
Timer_Start(3);
if(BlockNum<2)//single block
{
do { // StartAddr * 512
SDIO_Command(StartAddr<<9, WRITE_BLOCK_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while((Check_CMDend(WRITE_BLOCK_CMD, 1) !=1));
}
else//multi block
{
do {
SDIO_Command(StartAddr<<9, WRITE_MULTIPLE_BLOCK, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while((Check_CMDend(WRITE_MULTIPLE_BLOCK, 1) !=1));
}
rSDICSTA |= CMD_END|RESP_END; // Clear cmd_end(with rsp)
while(!TR_end);
rINTMSK |= (1<<20);
rINTSUBMSK |= (1<<27);
TR_end=0;
rDMASKTRIG0 |=(1<<2);//DMA Stop
default : break;
}
while(!Check_DATend()) ;
//printf("\nData End Error\n");
rSDIDCON=rSDIDCON&~(7<<12); //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
rSDIDSTA |= DATA_FINISH; // Clear data Tx/Rx end
if(BlockNum>1)
{
rSDIDCON=BUSY_AFTER_CMD|BLOCK_TRANSFER|WIDE_BUS_DIS|DATA_TRANSMIT_START|ONLYBUSY_CHECK|(BlockNum<<0);
do {
SDIO_Command(0, STOP_TRANSMISSION_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
} while(Check_CMDend(12, 1) != 1) ;
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
if(!Check_BUSYend())
printf("error\n");
rSDIDSTA|= DATA_FINISH; //! Should be cleared by writing '1'.
}
time=Timer_Stop();
printf ("TIME is : %d us\n", time<<7); // time is 1/128 mux
printf ( "Transfer Rate is : %f MB per sec \n", ((float)(BlockNum<<9)) / ((float)(time<<7)) );
BlockNum =0;
}
void eraseBlock_beforewrite(unsigned int StartAddr, unsigned EndAddr) {
// clean data space.
if(card_type == SD_CARD)
{
do {
SDIO_Command(StartAddr, 32, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(32, 1) != 1) ;
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
do {
SDIO_Command(EndAddr, 33, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(33, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
}
else if(card_type == MMC_CARD || card_type == MOVI_NAND_CARD )
{
do {
SDIO_Command(StartAddr, ERASE_GROUP_START_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(ERASE_GROUP_START_CMD, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
do {
SDIO_Command(EndAddr, ERASE_GROUP_END_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(ERASE_GROUP_END_CMD, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
}
rSDIDSTA |= (1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2);
rSDIDCON = 0;
if(Wide==0)
rSDIDCON &= ~WIDE_BUS_EN;
else
rSDIDCON |= WIDE_BUS_EN;
rSDIDCON |= BUSY_AFTER_CMD|BLOCK_TRANSFER|BlockNum;
rSDIDCON |= ONLYBUSY_CHECK|DATA_TRANSMIT_START;
do {
SDIO_Command(0, ERASE_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
} while(Check_CMDend(ERASE_CMD, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
if(!Check_BUSYend())
printf("\nBusy Check Error...\n");
rSDIDSTA = (1<<3);
// ereasing block done.
Delay(1000);
}
void SDIO_EraseBlock(void)
{
U32 StartAddr, EndAddr;
printf("\nSD/MMC block erase test\n");
printf("\nInput Write Start Block Address(0x200, 0x400...) : "); //ex) 0x200[512bytes], 0x400, 0x800.....
StartAddr = GetIntNum();
printf("Input Write End Block Address(0x200, 0x400...) : "); //ex) 0x200[512bytes], 0x400, 0x800.......
EndAddr = GetIntNum();
if(card_type == SD_CARD)
{
do {
SDIO_Command(StartAddr, 32, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(32, 1) != 1) ;
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
do {
SDIO_Command(EndAddr, 33, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(33, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
}
else if(card_type == MMC_CARD || card_type == MOVI_NAND_CARD )
{
do {
SDIO_Command(StartAddr, ERASE_GROUP_START_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(ERASE_GROUP_START_CMD, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
do {
SDIO_Command(EndAddr, ERASE_GROUP_END_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(ERASE_GROUP_END_CMD, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
}
rSDIDSTA |= (1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2);
rSDIDCON = 0;
if(Wide==0)
rSDIDCON &= ~WIDE_BUS_EN;
else
rSDIDCON |= WIDE_BUS_EN;
rSDIDCON |= BUSY_AFTER_CMD|BLOCK_TRANSFER|BlockNum;
rSDIDCON |= ONLYBUSY_CHECK|DATA_TRANSMIT_START;
do {
SDIO_Command(0, ERASE_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
} while(Check_CMDend(ERASE_CMD, 1) != 1);
rSDICSTA = CMD_END|RESP_END; // Clear cmd_end(with rsp)
if(!Check_BUSYend())
printf("\nBusy Check Error...\n");
rSDIDSTA = (1<<3);
printf("\n[SD/TFlash card Erase Block Test...End]\n");
}
int SD_card_init(void)
{
int datasize;
U32 C_SIZE, C_SIZE_MULT, READ_BL_LEN, CardSize, OneBlockSize;
U32 WRITE_BL_LEN,TRANS_SPEED,TRANS_SPEED_MUL;
rSDIPRE=PCLK/(INICLK)-1; // Clock setting
// youngbo.song SD客 MMC 埃俊 构啊 促甫瘤 积阿茄促. - 弊府绊 捞甫 老瘤皑摹 备盒且 规过篮 绝摆绰啊?
SDIO_TypeSetting(SDIO_SD_TYPE, SDIO_TYPE_A);// clock type setting
// SDIO_TypeSetting(SDIO_MMC_TYPE, SDIO_TYPE_A);// clock type setting
Delay(1); // Give some time for reset.
rSDICON |= ENCLK; //Clock enable
rSDIFSTA |= (1<<16);//FIFO reset
SDIO_BlockSizeSetting(Card_OneBlockSize); //block size setting
rSDIDTIMER = 0x7fffff; //busy timer setting
Delay(0x1000); // Wait 74SDCLK for MMC card
SDIO_Command(0x0, GO_TO_IDLE_CMD, SDIO_NO_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
Check_CMDend(GO_TO_IDLE_CMD,0);
//-------------------------------------------------------------------------------------//
printf("\nEnter to the Idle State\n");
card_type = Check_OCR();
if(card_type==ERROR_CARD) {
printf("\n\nInitialize fail\nNo Card assertion\n");
return 0;
}
// initially we setted sd type.
if ( card_type != SD_CARD ) {
SDIO_TypeSetting(SDIO_MMC_TYPE, SDIO_TYPE_A);
}
//-------------------------------------------------------------------------------------//
printf("\nCMD2 : CID response\n");
do {
SDIO_Command(0x0, ALL_SEND_SID_CMD, SDIO_WAIT_RESP, SDIO_LONG_RESP, SDIO_WITHOUT_DATA);
} while(Check_CMDend(ALL_SEND_SID_CMD, 1) != 1);
printf("\n - Product Name : %c%c%c%c%c%c",(rSDIRSP0&0xFF),((rSDIRSP1>>24)&0xFF),((rSDIRSP1>>16)&0xFF),((rSDIRSP1>>8)&0xFF),(rSDIRSP1&0xFF),((rSDIRSP2>>24)&0xFF));
//-------------------------------------------------------------------------------------//
printf("\nCMD3 : assign relative address\n");
do {
if ( card_type == SD_CARD )
SDIO_Command((0<<16), SET_RELATIVE_ADDR, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITHOUT_DATA);
else if ( card_type == MMC_CARD )
SDIO_Command((1<<16), SET_RELATIVE_ADDR, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
else if ( card_type == MOVI_NAND_CARD )
SDIO_Command((1<<16), SET_RELATIVE_ADDR, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while( Check_CMDend(3, 1) !=1);
//-------------------------------------------------------------------------------------//
if(card_type == SD_CARD ) {
RCA = ( rSDIRSP0 & 0xffff0000 )>>16;
}
else if(card_type == MMC_CARD ) {
RCA = 1;
}
else if(card_type == MOVI_NAND_CARD ) {
RCA = 1;
}
//-------------------------------------------------------------------------------------//
do {
SDIO_Command(RCA<<16, SEND_CSD_CMD, SDIO_WAIT_RESP, SDIO_LONG_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(SEND_CSD_CMD, 1) != 1);
READ_BL_LEN = (rSDIRSP1>>16&0xF);
C_SIZE = ((rSDIRSP1&0x3ff)<<2) | (rSDIRSP2>>30&0x3);
C_SIZE_MULT = (rSDIRSP2>>15&0x7);
WRITE_BL_LEN=(rSDIRSP3>>22&0xf);
TRANS_SPEED= rSDIRSP0 & 0xff;
TRANS_SPEED_MUL = (TRANS_SPEED >> 3)&0xf;
TRANS_SPEED= (TRANS_SPEED&0x7);
CardSize = (1<<READ_BL_LEN)*(C_SIZE+1)*(1<<(C_SIZE_MULT+2))/1048576;
OneBlockSize = (1<<READ_BL_LEN);
printf("\n READ_BL_LEN: %d",READ_BL_LEN);
printf("\n C_SIZE: %d",C_SIZE);
printf("\n C_SIZE_MULT: %d\n",C_SIZE_MULT);
printf("\n TRANS_SPEED: %d, Mul : %d\n", TRANS_SPEED, TRANS_SPEED_MUL);
printf("\n One Block Size: %dByte",OneBlockSize);
printf("\n Total Card Size: %dMByte\n",CardSize+1);
//-------------------------------------------------------------------------------------//
// CMD7 - SELECT Command
CARD_SEL_DESEL(1);//Enter Card state to the transfer mode
if(card_type == MMC_CARD) {
SDIO_PrescalerSetting(MMCCLK);
while(PCLK/(rSDIPRE+1) > 20000000)
rSDIPRE = rSDIPRE+1;
printf("\nMMC Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));
}
else if ( card_type == MOVI_NAND_CARD ) {
SDIO_PrescalerSetting(MOVICLK);
while(PCLK/(rSDIPRE+1) > MOVICLK)
rSDIPRE = rSDIPRE+1;
printf("\nMOVINAND Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));
}
else if ( card_type == SD_CARD ) {
SDIO_PrescalerSetting(SDCLK);
while(PCLK/(rSDIPRE+1) > 25000000)
rSDIPRE = rSDIPRE+1;
printf("\nSD Frequency is %dHz\n",(PCLK/(rSDIPRE+1)));
}
Set_Bus(card_type);
if ( card_type==MOVI_NAND_CARD ) {
if (PCLK/(rSDIPRE+1) > 20000000 )
{
do {
SDIO_Command((3<<24)|(185<<16)|(1<<8), SWITCH_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);//ACMD6 select bus width
} while((Check_CMDend(6, 1) !=1));
rSDICON &= ~(1);
Delay(1);
rSDICON |= 1;
Delay(1);
}
}
do {
SDIO_Command(Card_OneBlockSize, SET_BLOCKLEN_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
} while(Check_CMDend(SET_BLOCKLEN_CMD, 1) != 1);
printf("\nSet Block Length");
return 1;
}
void Set_Bus(CardType type)
{
if( type == SD_CARD ) {
Wide = 1;
}
else if(type == MMC_CARD ) {
Wide = 0;
}
else if( type == MOVI_NAND_CARD ) {
Wide = 1;
}
SET_BUSWIDTH( type );
if ( Wide )
printf("\n****4bit bus****\n");
else
printf("\n****1bit bus****\n");
}
void SET_BUSWIDTH(CardType type)
{
int arg;
if ( type==MOVI_NAND_CARD ) {
arg = (3<<24)|(183<<16)|(1<<8);
do {
SDIO_Command(arg, SWITCH_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);//ACMD6 select bus width
} while((Check_CMDend(6, 1) !=1));
}
else if ( type == SD_CARD ) {
do {
SDIO_Command((RCA<<16), APP_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);//befoe using ACMD
} while((Check_CMDend(APP_CMD, 1) !=1));
do {
SDIO_Command((Wide<<1), SWITCH_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);//ACMD6 select bus width
} while((Check_CMDend(SWITCH_CMD, 1) !=1));
}
else if ( type == MMC_CARD ) {
// do not need anything.
}
rSDICSTA |= CMD_END|RESP_END;
}
void CARD_SEL_DESEL(U8 sel_desel)
{
printf("\nCMD7 : Command toggles a card between the stand-by and transfer state\n");
if(sel_desel)
{
printf("\nCMD7 : Select\n");
SDIO_Command((RCA<<16), SELECT_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
if((Check_CMDend(SELECT_CMD, 1) !=1)||(rSDIRSP0 != 0x800))//entering the standby mode
SDIO_Command((RCA<<16), SELECT_CMD, SDIO_WAIT_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
rSDICSTA |=CMD_END|RESP_END;
printf("\nEntered to the Transfer state\n");
}
else
{
printf("\nCMD7 : Deselect\n");
SDIO_Command((RCA<<16), SELECT_CMD, SDIO_NO_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
if((Check_CMDend(SELECT_CMD, 0) !=1))
SDIO_Command((RCA<<16), SELECT_CMD, SDIO_NO_RESP, SDIO_SHORT_RESP, SDIO_WITH_DATA);
rSDICSTA |= CMD_END;
printf("\nEntered to the Stand-by State\n");
}
}
void SDIO_PrescalerSetting(U32 BaudRate)
{
rSDIPRE = (PCLK/BaudRate) - 1;
}
void SDIO_Command(U32 CmdArg, U32 Command, U32 WaitResp, U32 LongResp, U32 WithData)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -