📄 hs_mmc.c
字号:
ReadBlockCnt_INT = 0;
printf("\nSD/MMC block Read test\n");
printf("\n0:Polling Read 1:Interrupt Read 2:DMA Read");
printf("\nSelect the test mode : ");
Testmode=GetIntNum();
printf("\nInput Write Start block number : ");
StartAddr = GetIntNum();
Addr_temp = StartAddr;
while((BlockNum_HSMMC == 0) || (BlockNum_HSMMC > 65535))
{
printf("Input number of block[1~4095] : ");
BlockNum_HSMMC = GetIntNum();
}
if(SectorMode == 1)
StartAddr = StartAddr;
else
StartAddr = StartAddr * 512;
OneBlockSize = Card_OneBlockSize_ver1;
Rx_buffer_HSMMC = (U32 *)SDI_Rx_buffer_HSMMC;
for(i=0 ; i<(OneBlockSize*BlockNum_HSMMC)/4 ; i++)
*(Rx_buffer_HSMMC+i) = 0x0;
switch(Testmode)
{
case POL_Ver1:
printf("\nPolling mode data read\n");
while (!IsCardInProgrammingState());
SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
SetArgumentReg(StartAddr); // Card Address to Write
if(BlockNum_HSMMC == 1)//single block
{
printf("Single block read\n");
SetTransferModeReg(0, 1, 0, 1, 0);
SetCommandReg(17, 0); // CMD17: Single-Read
}
else//multi block
{
printf("Multi block read\n");
SetTransferModeReg(1, 1, 1, 1, 0);
SetCommandReg(18, 0); // CMD18: Multi-Read
}
while (!WaitForCommandComplete());
ClearCommandCompleteStatus();
for(j=0; j<BlockNum_HSMMC; j++)
{
if (!WaitForBufferReadReady())
printf("ReadBuffer NOT Ready\n");
else
ClearBufferReadReadyStatus();
for(i=0; i<512/4; i++)
{
*Rx_buffer_HSMMC++ = rHM_BDATA;
rd_cnt_HSMMC++;
}
WriteBlockCnt ++;
printf("\nWrite block count = %d", WriteBlockCnt);
}
TotalReadByte = wt_cnt_HSMMC *4;
printf("\nWrite count=%dByte\n",TotalReadByte);
printf("\nWrite count=%x\n",rd_cnt_HSMMC);
if(!WaitForTransferComplete())
{
printf(("Transfer NOT Complete\n"));
}
ClearTransferCompleteStatus();
break;
case INT_Ver1:
printf("\nInterrupt mode data Read\n");
pISR_SDI_1=(unsigned)HS_READ_INT;
SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
SetArgumentReg(StartAddr); // Card Address to Write
StartStopwatch();
if(BlockNum_HSMMC == 1)//single block
{
SetTransferModeReg(0, 1, 0, 1, 0);
SetCommandReg(17, 0); // CMD17: Single-Read
}
else//multi block
{
SetTransferModeReg(1, 1, 1, 1, 0);
SetCommandReg(18, 0); // CMD18: Multi-Read
}
if (!WaitForCommandComplete());
ClearCommandCompleteStatus();
rINTMSK &= ~(BIT_SDI1);
rHM_NORINTSIGEN = rHM_NORINTSIGEN & ~(0xffff) | BUFFER_READREADY_SIG_INT_EN;
while(!READINT_DONE);
if(!WaitForTransferComplete())
{
printf(("Transfer NOT Complete\n"));
}
ClearTransferCompleteStatus();
transtime = EndStopwatch();
CalculationBPS_HSMMC(transtime);
printf("\nInterupt mode Read End\n");
break;
case DMA_Ver1:
pISR_SDI_1=(unsigned)HS_DMA_INT;
rINTMSK &= ~(BIT_SDI1);
rHM_NORINTSTSEN &= ~(DMA_STS_INT_EN|BLOCKGAP_EVENT_STS_INT_EN);
rHM_NORINTSIGEN = rHM_NORINTSIGEN & ~(0xffff) | TRANSFERCOMPLETE_SIG_INT_EN;
SetSystemAddressReg(SDI_Rx_buffer_HSMMC);// AHB System Address For Write
SetBlockSizeReg(7, 512); // Maximum DMA Buffer Size, Block Size
SetBlockCountReg(BlockNum_HSMMC); // Block Numbers to Write
SetArgumentReg(StartAddr);// Card Start Block Address to Write
StartStopwatch();
if (BlockNum_HSMMC == 1)
{
SetTransferModeReg(0, 1, 0, 1, 1);
SetCommandReg(17, 0); // CMD17: Single-Read
}
else
{
SetTransferModeReg(1, 1, 1, 1, 1);
SetCommandReg(18, 0); // CMD18: Multi-Read
}
if (!WaitForCommandComplete())
{
printf(("Command NOT Complete\n"));
}
else
ClearCommandCompleteStatus();
while(!HS_DMA_END);
transtime = EndStopwatch();
CalculationBPS_HSMMC(transtime);
printf(("\nDMA Read End\n"));
break;
default : break;
}
Rx_buffer_HSMMC = (U32 *)SDI_Rx_buffer_HSMMC;
for(j=0 ; j<(OneBlockSize*BlockNum_HSMMC)/4 ; j++)
{
if(j%4 == 0)
printf("\n0x%04xh : ",Addr_temp);
printf("0x%08x ",*Rx_buffer_HSMMC++);
Addr_temp += 4;
}
printf("\n");
HS_DMA_END = 0;
BlockNum_HSMMC = 0;
rd_cnt_HSMMC = 0;
ReadBlockCnt_INT = 0;
}
void HS_MMC_EraseBlock(void)
{
U16 EraseBlockStartNum, EraseBlockEndNum;
printf("\nHigh speed MMC block erase test\n");
printf("\nInput Erase Start Block Number(ex 0, 1, 2 ...) : ");
EraseBlockStartNum = GetIntNum();
printf("Input Erase End Block Number(ex 0, 1, 2 ...) : ");
EraseBlockEndNum = GetIntNum();
if(ThisIsMmc == 0)
{
SetArgumentReg(EraseBlockStartNum*512);
SetCommandReg(32, 0);
while (!WaitForCommandComplete());
ClearCommandCompleteStatus();
SetArgumentReg(EraseBlockEndNum*512);
SetCommandReg(33, 0);
while (!WaitForCommandComplete());
ClearCommandCompleteStatus();
}
else if(ThisIsMmc == 1)
{
SetArgumentReg(EraseBlockStartNum*512);
SetCommandReg(35, 0);
while (!WaitForCommandComplete());
ClearCommandCompleteStatus();
SetArgumentReg(EraseBlockEndNum*512);
SetCommandReg(36, 0);
while (!WaitForCommandComplete());
ClearCommandCompleteStatus();
}
SetArgumentReg(0);
SetCommandReg(38, 0);
printf("\n[SD/TFlash card Erase Block Test...End]\n");
}
void HS_MMC_CardDetect(void)
{
rGPJCON = (rGPJCON & ~(0x3<<28)) | (1<<29);
//rHM_CONTROL2 |= (1<<13)|(1<<12);//Card Detect using a DAT[3] signal
rHM_NORINTSTSEN |= (1<<7)|(1<<6);
rHM_NORINTSIGEN |= (1<<7)|(1<<6) ;
if(rHM_PRNSTS & (1<<16))
{
HS_CARD_DETECT = 1;
printf("\nCard is Inserted\n");
}
while(!HS_CARD_DETECT)
{
printf("\nInsert a Card\n");
HS_CARD_DETECT=0;
HS_MMC_Irq();
do {
printf(".");
Delay(5000);
} while(HS_CARD_DETECT==0);
}
HS_CARD_DETECT = 0;
rHM_CONTROL2 &= ~(1<<13);
}
int SetDataTransferWidth(void)
{
U8 uBitMode=0;
U32 uArg=0;
U8 m_ucHostCtrlReg = 0;
U32 BD_BUS_WIDTH, ucBusWidth;
printf("\nSelect the bus width 8-bit, 4-bit, 1-bit\n");
printf("\nType a bus width: ");
BD_BUS_WIDTH = GetIntNum();
switch (BD_BUS_WIDTH)
{
case 8:
ucBusWidth = ThisIsMmc ? 8 : 4;
break;
case 4:
ucBusWidth = 4;
break;
case 1:
ucBusWidth = 1;
break;
default :
ucBusWidth = 4;
break;
}
SetSdhcCardIntEnable(0); // Disable sd card interrupt
if(!ThisIsMmc)// <------------------------- SD Card Case
{
if (!IssueCommand(55, m_uRca, 0))
return 0;
else
{
if (ucBusWidth==1)
{
uBitMode = 0;
if (!IssueCommand(6, 0, 1)) // 1-bits
return 0;
}
else
{
uBitMode = 1;
if (!IssueCommand(6, 2, 1)) // 4-bits
return 0;
}
}
}
else // <-------------------------------- MMC Card Case
{
if (m_ucMMCSpecVer==4) // It is for a newest MMC Card
{
if (ucBusWidth==1)
uBitMode = 0;
else if (ucBusWidth==4)
uBitMode = 1;//4 // 4-bit bus
else
uBitMode = 2;//8-bit bus
uArg=((3<<24)|(183<<16)|(uBitMode<<8));
while(!IssueCommand(6, uArg, 0));
}
else
uBitMode = 0;
}
if (uBitMode==2)
{
m_ucHostCtrlReg &= 0xdf;
m_ucHostCtrlReg |= 1<<5;
}
else
{
m_ucHostCtrlReg &= 0xfd;
m_ucHostCtrlReg |= uBitMode<<1;
}
rHM_HOSTCTL = m_ucHostCtrlReg;
SetSdhcCardIntEnable(1);
return 1;
}
void SetSdhcCardIntEnable(U8 ucTemp)
{
rHM_NORINTSTSEN &= 0xFEFF;
rHM_NORINTSTSEN |= (ucTemp<<8);
}
int SetSDOCR(void)
{
U32 i;
for(i=0; i<250; i++)
{
#if 1
IssueCommand(55, 0x0000, 0); // CMD55 (For ACMD)
IssueCommand(41, 0x40ff8000, 1); // (Ocr:2.7V~3.6V)
#else
IssueCommand(55, 0x0, 0); // CMD55 (For ACMD)
IssueCommand(41, 0x0, 1); // (Ocr:2.7V~3.6V)
OCR = rHM_RSPREG0 | (1<<30);
//printf("\nrHM_RSPREG0=%x",rHM_RSPREG0);
//Delay(1000);
IssueCommand(55, 0x0, 0); // CMD55 (For ACMD)
IssueCommand(41, OCR, 1); // (Ocr:2.7V~3.6V)
#endif
if (rHM_RSPREG0&(U32)(0x1<<31))
{
if(rHM_RSPREG0 & (1<<7))
printf("\nVoltage range : 1.65V ~ 1.95V");
if(rHM_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n\n");
else if(rHM_RSPREG0 & (1<<20))
printf("\nVoltage range: 2.7V ~ 3.3V\n\n");
else if(rHM_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n\n");
else if(rHM_RSPREG0 & (1<<23))
printf("\nVoltage range: 2.7V ~ 3.6V\n\n");
if(rHM_RSPREG0&(0x1<<30))
{
printf("\nHigh Capacity Card\n");
SectorMode = 1;
}
ThisIsMmc = 0;
return 1;
}
Delay(10);
}
// The current card is MMC card, then there's time out error, need to be cleared.
ClearErrInterruptStatus();
return 0;
}
int SetMMCOCR(void)
{
U32 i, OCR;
for (i=0; i<250; i++)
{
IssueCommand(1, 0x0, 0);
OCR = rHM_RSPREG0 | (1<<30);
IssueCommand(1, OCR, 0); // (Ocr:2.7V~3.6V)
if (rHM_RSPREG0&(U32)(0x1<<31))
{
if(rHM_RSPREG0 & (1<<7))
printf("\nVoltage range : 1.65V ~ 1.95V");
if(rHM_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n");
else if(rHM_RSPREG0 & (1<<20))
printf("\nVoltage range: 2.7V ~ 3.3V\n");
else if(rHM_RSPREG0 & (1<<19))
printf("\nVoltage range: 2.7V ~ 3.2V\n");
else if(rHM_RSPREG0 & (1<<18))
printf("\nVoltage range: 2.7V ~ 3.1V\n");
if(rHM_RSPREG0 & (1<<30))
{
printf("\nHigh Capacity Sector Mode Operation\n");
SectorMode = 1;
}
ThisIsMmc=1;
printf("\nrHM_RSPREG0 = %x\n",rHM_RSPREG0);
return 1;
}
}
ClearErrInterruptStatus();
return 0;
}
void SetCommandReg(U16 uCmd,U32 uIsAcmd)
{
U16 usSfr = 0;
if (!uIsAcmd)//No ACMD
{
/* R2: 136-bits Resp.*/
if ((uCmd==2||uCmd==9||uCmd==10))
usSfr=(uCmd<<8)|(0<<4)|(1<<3)|(1<<0);
/* R1,R6,R5: 48-bits Resp. */
else if (uCmd==3||uCmd==8||uCmd==13||uCmd==16||uCmd==27||uCmd==30||uCmd==32||uCmd==33||uCmd==35||uCmd==36||uCmd==42||uCmd==55||uCmd==56)
usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(2<<0);
else if (uCmd==11||uCmd==14||uCmd==17||uCmd==18||uCmd==19||uCmd==20||uCmd==24||uCmd==25)
usSfr=(uCmd<<8)|(1<<5)|(1<<4)|(1<<3)|(2<<0);
/* R1b,R5b: 48-bits Resp. */
else if (uCmd==6||uCmd==7||uCmd==12||uCmd==28||uCmd==29||uCmd==38)
{
if (uCmd==12)
usSfr=(uCmd<<8)|(3<<6)|(1<<4)|(1<<3)|(3<<0);
else if (uCmd==6)
{
if(!ThisIsMmc) // SD card
usSfr=(uCmd<<8)|(1<<5)|(1<<4)|(1<<3)|(2<<0);
else // MMC card
usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(3<<0);
}
else
usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(3<<0);
}
/* R3,R4: 48-bits Resp. */
else if (uCmd==1)
usSfr=(uCmd<<8)|(0<<4)|(0<<3)|(2<<0);
/* No-Resp. */
else
usSfr=(uCmd<<8)|(0<<4)|(0<<3)|(0<<0);
}
else//ACMD
{
if (uCmd==6||uCmd==22||uCmd==23) // R1
usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(2<<0);
else if (uCmd==13||uCmd==51)
usSfr=(uCmd<<8)|(1<<5)|(1<<4)|(1<<3)|(2<<0);
else
usSfr=(uCmd<<8)|(0<<4)|(0<<3)|(2<<0);
}
rHM_CMDREG = usSfr;
}
void SetMMCSpeedMode(U32 eSDSpeedMode)
{
U8 ucSpeedMode;
U32 uArg=0;
ucSpeedMode = (eSDSpeedMode == HIGH) ? 1 : 0;
uArg=(3<<24)|(185<<16)|(ucSpeedMode<<8); // Change to the high-speed mode
while(!IssueCommand(6, uArg, 0));
}
void SetSDSpeedMode(U32 eSDSpeedMode)
{
U32 uArg = 0;
U8 ucSpeedMode;
ucSpeedMode = (eSDSpeedMode == HIGH) ? 1 : 0;
if (!IssueCommand(16, 64, 0)) // CMD16
printf("CMD16 fail\n");
else
{
SetBlockSizeReg(7, 64);
SetBlockCountReg(1);
SetArgumentReg(0*64);
SetTransferModeReg(0, 1, 0, 0, 0);
uArg = (0x1<<31)|(0xffff<<8)|(ucSpeedMode<<0);
if (!IssueCommand(6, uArg, 0))
printf("CMD6 fail\n");
}
}
void SetClock(U32 ClkSrc, U16 Divisor)
{
rHM_CONTROL2 = (rHM_CONTROL2 & ~(0xffffffff)) | (0x1<<15)|(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
//rHM_CONTROL2 = (rHM_CONTROL2 & ~(0xffffffff)) |(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
rHM_CONTROL3 = (0<<31) | (1<<23) | (0<<15) | (1<<7);//SD OK
//rHM_CONTROL3 = (1<<31) | (1<<23) | (1<<15) | (1<<7);
rHM_CLKCON &= ~(0xff<<8);
// SDCLK Value Setting + Internal Clock Enable
rHM_CLKCON = (rHM_CLKCON & ~((0xff<<8)|(0x1))) | (Divisor<<8)|(1<<0);
// CheckInternalClockStable
while (!(rHM_CLKCON&0x2));
ClockOnOff(1);
}
int IssueCommand( U16 uCmd, U32 uArg, U32 uIsAcmd)
{
U32 uSfr;
while ((rHM_PRNSTS&0x1)); // Check CommandInhibit_CMD
if (!uIsAcmd)//R1b type commands have to check CommandInhibit_DAT bit
{
if((uCmd==6&&ThisIsMmc)||uCmd==7||uCmd==12||uCmd==28||uCmd==29||uCmd==38||((uCmd==42||uCmd==56)&&(!ThisIsMmc)))
{
do {
uSfr = rHM_PRNSTS;
} while((uSfr&0x2)); // Check CommandInhibit_DAT
}
}
// Argument Setting
if (!uIsAcmd)// <------------------- Normal Command (CMD)
{
if(uCmd==3||uCmd==4||uCmd==7||uCmd==9||uCmd==10||uCmd==13||uCmd==15||uCmd==55)
rHM_ARGUMENT = uArg<<16;
else
rHM_ARGUMENT = uArg;
}
else// <--------------------------- APP.Commnad (ACMD)
rHM_ARGUMENT = uArg;
SetCommandReg(uCmd,uIsAcmd);
if (!WaitForCommandComplete())
{
printf(("Command NOT Complete\n"));
}
else
ClearCommandCompleteStatus();
if (!(rHM_NORINTSTS&0x8000))
{
if(((rHM_CMDREG>>8) == 0x8) &&(ThisIsMmc !=1))
{
printf("\nCMD8 Support");
SDSpecVer = 2;
}
return 1;
}
else
{
if(OCRcheck == 1)
return 0;
else
{
printf("Command = %d, Error Stat = %x\n",(rHM_CMDREG>>8),rHM_ERRINTSTS);
rHM_ERRINTSTS = rHM_ERRINTSTS;
rHM_NORINTSTS =rHM_NORINTSTS;
if((rHM_CMDREG>>8) == 0x8)
{
printf("\nThis Card version is NOT SD 2.0\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -