📄 hs0_mmc.c
字号:
printf("\nHigh Capacity Card\n");
SectorMode_ch0 = 1;
}
ThisIsMmc_ch0 = 0;
return 1;
}
Delay(10);
}
// The current card is MMC card, then there's time out error, need to be cleared.
ClearErrInterruptStatus_CH0();
return 0;
}
int SetMMCOCR_CH0(void)
{
U32 i, OCR;
for (i=0; i<250; i++)
{
IssueCommand_CH0(1, 0x0, 0);
OCR = rHM0_RSPREG0 | (1<<30);
IssueCommand_CH0(1, OCR, 0); // (Ocr:2.7V~3.6V)
if (rHM0_RSPREG0&(0x1<<31))
{
if(rHM0_RSPREG0 & (1<<7))
printf("\nVoltage range : 1.65V ~ 1.95V");
if(rHM0_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n");
else if(rHM0_RSPREG0 & (1<<20))
printf("\nVoltage range: 2.7V ~ 3.3V\n");
else if(rHM0_RSPREG0 & (1<<19))
printf("\nVoltage range: 2.7V ~ 3.2V\n");
else if(rHM0_RSPREG0 & (1<<18))
printf("\nVoltage range: 2.7V ~ 3.1V\n");
if(rHM0_RSPREG0 & (1<<30))
{
printf("\nHigh Capacity Sector Mode Operation\n");
SectorMode_ch0 = 1;
}
ThisIsMmc_ch0=1;
printf("\nrHM_RSPREG0 = %x\n",rHM0_RSPREG0);
return 1;
}
}
ClearErrInterruptStatus_CH0();
return 0;
}
void SetCommandReg_CH0(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_ch0) // 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);
}
rHM0_CMDREG = usSfr;
}
void setmmcspeedmode_CH0(U32 eSDSpeedMode)
{
U8 ucSpeedMode;
U32 uArg=0;
ucSpeedMode = (eSDSpeedMode == HIGH_CH0) ? 1 : 0;
uArg=(3<<24)|(185<<16)|(ucSpeedMode<<8); // Change to the high-speed mode
while(!IssueCommand_CH0(6, uArg, 0));
}
void SetSDSpeedMode_CH0(U32 eSDSpeedMode)
{
U32 uSfr;
U32 uArg = 0;
U8 ucSpeedMode;
int i;
ucSpeedMode = (eSDSpeedMode == HIGH_CH0) ? 1 : 0;
if (!IssueCommand_CH0(16, 64, 0)) // CMD16
printf("CMD16 fail\n");
else
{
SetBlockSizeReg_CH0(7, 64);
SetBlockCountReg_CH0(1);
SetArgumentReg_CH0(0*64);
SetTransferModeReg_CH0(0, 1, 0, 0, 0);
uArg = (0x1<<31)|(0xffff<<8)|(ucSpeedMode<<0);
if (!IssueCommand_CH0(6, uArg, 0))
printf("CMD6 fail\n");
else
{
WaitForBufferReadReady_CH0();
ClearBufferReadReadyStatus_CH0();
for(i=0; i<16; i++)
{
uSfr = rHM0_BDATA ;
}
WaitForTransferComplete_CH0();
ClearTransferCompleteStatus_CH0();
}
}
}
void SetClock_CH0(U32 ClkSrc, U16 Divisor)
{
rHM0_CONTROL2 = (rHM0_CONTROL2 & ~(0xffffffff)) | (0x1<<15)|(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
//rHM_CONTROL2 = (rHM_CONTROL2 & ~(0xffffffff)) |(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
//rHM0_CONTROL3 = (0<<31) | (1<<23) | (0<<15) | (1<<7);//SD OK
rHM0_CONTROL3 = (1<<31) | (1<<23) | (1<<15) | (1<<7);
// SDCLK Value Setting + Internal Clock Enable
rHM0_CLKCON = (rHM0_CLKCON & ~((0xff<<8)|(0x1))) | (Divisor<<8)|(1<<0);
// CheckInternalClockStable
while (!(rHM0_CLKCON&0x2));
ClockOnOff_CH0(1);
}
int IssueCommand_CH0( U16 uCmd, U32 uArg, U32 uIsAcmd)
{
U32 uSfr;
while ((rHM0_PRNSTS&0x1)); // Check CommandInhibit_CMD
if (!uIsAcmd)//R1b type commands have to check CommandInhibit_DAT bit
{
if((uCmd==6&&ThisIsMmc_ch0)||uCmd==7||uCmd==12||uCmd==28||uCmd==29||uCmd==38||((uCmd==42||uCmd==56)&&(!ThisIsMmc_ch0)))
{
do {
uSfr = rHM0_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)
rHM0_ARGUMENT = uArg<<16;
else
rHM0_ARGUMENT = uArg;
}
else// <--------------------------- APP.Commnad (ACMD)
rHM0_ARGUMENT = uArg;
SetCommandReg_CH0(uCmd,uIsAcmd);
if (!WaitForCommandComplete_CH0())
{
printf(("Command NOT Complete\n"));
}
else
ClearCommandCompleteStatus_CH0();
if (!(rHM0_NORINTSTS&0x8000))
{
if(((rHM0_CMDREG>>8) == 0x8) &&(ThisIsMmc_ch0 !=1))
{
printf("\nCMD8 Support");
SDSpecVer_ch0 = 2;
}
return 1;
}
else
{
if(OCRcheck_ch0 == 1)
return 0;
else
{
printf("Command = %d, Error Stat = %x\n",(rHM0_CMDREG>>8),rHM0_ERRINTSTS);
rHM0_ERRINTSTS = rHM0_ERRINTSTS;
rHM0_NORINTSTS =rHM0_NORINTSTS;
if((rHM0_CMDREG>>8) == 0x8)
{
printf("\nThis Card version is NOT SD 2.0\n");
}
return 0;
}
}
}
void GetResponseData_CH0(U32 uCmd)
{
U32 uSfr0,uSfr1,uSfr2,uSfr3;
uSfr0 = rHM0_RSPREG0;
uSfr1 = rHM0_RSPREG1;
uSfr2 = rHM0_RSPREG2;
uSfr3 = rHM0_RSPREG3;
if(uCmd==3)
{
if(!ThisIsMmc_ch0)
{
m_uRca_ch0 = (uSfr0>>16)&0xFFFF;
printf("=> RCA=%d\n", m_uRca_ch0);
}
}
else if (uCmd==9)
{
if(ThisIsMmc_ch0)
{
m_ucMMCSpecVer_ch0=(rHM0_RSPREG3>>18)& 0xF;
printf("=> m_ucMMCSpecVer_ch0=%d\n", m_ucMMCSpecVer_ch0);
}
}
}
int GetSdSCR_CH0()
{
U32 uSCR1, uSCR2;
if (!IssueCommand_CH0(16, 8, 0))
return 0;
else
{
SetBlockSizeReg_CH0(7, 8);
SetBlockCountReg_CH0(1);
SetArgumentReg_CH0(0*8);
SetTransferModeReg_CH0(0, 1, 0, 0, 0);
if (!IssueCommand_CH0(55, m_uRca_ch0, 0)) // CMD55 (For ACMD)
return 0;
else
{
if (!IssueCommand_CH0(51, 0, 1)) // Acmd51
return 0;
else
{
WaitForBufferReadReady_CH0();
ClearBufferReadReadyStatus_CH0();
uSCR1 = rHM0_BDATA;
uSCR2 = rHM0_BDATA;
WaitForTransferComplete_CH0();
ClearTransferCompleteStatus_CH0();
if ((uSCR1&0xf) == 0x0)
SDSpecVer_ch0 = 0; // Version 1.0 ~ 1.01
else if ((uSCR1&0xf) == 0x1)
SDSpecVer_ch0 = 1; // Version 1.10, support cmd6
else if((uSCR1&0xf) == 0x2)
SDSpecVer_ch0 = 2; // Version 2.0 support cmd6 and cmd8
printf("SDSpecVer_ch0=%d\n", SDSpecVer_ch0);
return 1;
}
}
}
}
int IsCardInProgrammingState_CH0(void)
{
// check the card status.
U32 uSfr;
if (!IssueCommand_CH0(13, m_uRca_ch0, 0))
return 0;
else
{
if(((rHM0_RSPREG0>>9)&0xf) == 4)
{
printf("Card is transfer status\n");
return 1;
}
return 0;
}
}
void HostCtrlSpeedMode_CH0(U8 SpeedMode)
{
U8 ucSpeedMode;
ucSpeedMode = (SpeedMode == HIGH_CH0) ? 1 : 0;
rHM0_HOSTCTL &= ~(0x1<<2);
rHM0_HOSTCTL |= ucSpeedMode<<2;
}
void ClockConfig_CH0(U32 Clksrc, U32 Divisior)
{
U32 SrcFreq, WorkingFreq;
U32 RealDivisor;
if (Clksrc == SD_HCLK_CH0)
SrcFreq = HCLK;
else if (Clksrc == SD_EPLL_CH0)//Epll Out 48MHz
SrcFreq = 100000000;
else
Clksrc = HCLK;
if (Divisior !=0)
{
WorkingFreq = SrcFreq/(Divisior*2);
printf("WorkingFreq = %dMHz\n",WorkingFreq/(1000000));
}
else
{
WorkingFreq = SrcFreq;
printf("WorkingFreq = %dMHz\n",WorkingFreq/(1000000));
}
if (ThisIsMmc_ch0)
{
if (m_ucMMCSpecVer_ch0==4)
{
if (WorkingFreq>20000000)// It is necessary to enable the high speed mode in the card before changing the clock freq to a freq higher than 20MHz.
{
setmmcspeedmode_CH0(HIGH_CH0);
printf("\nSet MMC High speed mode OK!!\n");
}
else
{
setmmcspeedmode_CH0(NORMAL_CH0);
printf("\nSet MMC Normal speed mode OK!!\n");
}
}
else // old version
printf("Old version MMC card can not support working frequency higher than 25MHz");
}
else
{
GetSdSCR_CH0();
if (SDSpecVer_ch0==1||SDSpecVer_ch0==2 )
{
if (WorkingFreq>25000000)
{
SetSDSpeedMode_CH0(HIGH_CH0);//Higher than 25MHz, should use high speed mode. Max 50MHz and 25MB/sec
printf("\nSet SD High speed mode OK!!\n");
}
else
{
SetSDSpeedMode_CH0(NORMAL_CH0);
printf("\nSet SD Normal speed mode OK!!\n");
}
}
else
printf("Old version SD card can not support working frequency higher than 25MHz");
}
if (WorkingFreq>25000000)// Higher than 25MHz, it is necessary to enable high speed mode of the host controller.
{
HostCtrlSpeedMode_CH0(HIGH_CH0);
}
else
{
HostCtrlSpeedMode_CH0(NORMAL_CH0);
}
ClockOnOff_CH0(0); // when change the sd clock frequency, need to stop sd clock.
SetClock_CH0(Clksrc, Divisior);
}
void HS_MMC_Irq_CH0(void)
{
pISR_SDI_0 = (int)HS_CARD_DETECT_INT_CH0; // Set interrupt service routine.
rINTMSK &= ~(BIT_SDI0);
}
void HS_MMC_Reset_CH0(void)
{
rHM0_SWRST = 0x3;
}
void HS_MMC_SETGPIO_CH0(void)
{
//SD1
rGPLCON = rGPLCON & ~(0xfffff) | (0xaaaaa);
rGPJCON = rGPJCON & ~(0x3f<<26) | (0x2a<<26);
rGPJCON &= ~(0x3<<30) | (1<<30);
rGPJDAT |=(1<<15);
//SD0
rGPECON = (rGPECON& ~(0x3ffc00))|(0x1<<21)|(0x1<<19)|(0x1<<17)|(0x1<<15)|(0x1<<13)|(0x1<<11);
}
void SetTransferModeReg_CH0(U32 MultiBlk,U32 DataDirection, U32 AutoCmd12En,U32 BlockCntEn,U32 DmaEn)
{
rHM0_TRNMOD = (rHM0_TRNMOD & ~(0xffff)) | (MultiBlk<<5)|(DataDirection<<4)|(AutoCmd12En<<2)|(BlockCntEn<<1)|(DmaEn<<0);
}
void SetArgumentReg_CH0(U32 uArg)
{
rHM0_ARGUMENT = uArg;
}
void SetBlockCountReg_CH0(U16 uBlkCnt)
{
rHM0_BLKCNT = uBlkCnt;
}
void SetSystemAddressReg_CH0(U32 SysAddr)
{
rHM0_SYSAD = SysAddr;
}
void SetBlockSizeReg_CH0(U16 uDmaBufBoundary, U16 uBlkSize)
{
rHM0_BLKSIZE = (uDmaBufBoundary<<12)|(uBlkSize);
}
void ClockOnOff_CH0(int OnOff)
{
if (OnOff == 0)
{
rHM0_CLKCON &=~(0x1<<2);
}
else
{
rHM0_CLKCON|=(0x1<<2);
while (1)
{
if (rHM0_CLKCON&(0x1<<3)) // SD_CLKSRC is Stable
break;
}
}
}
void ClearCommandCompleteStatus_CH0(void)
{
rHM0_NORINTSTS=(1<<0);
while (rHM0_NORINTSTS&0x1)
{
rHM0_NORINTSTS=(1<<0);
}
}
void ClearTransferCompleteStatus_CH0(void)
{
rHM0_NORINTSTS = (1<<1);
while (rHM0_NORINTSTS&0x2)
{
rHM0_NORINTSTS = (1<<1);
}
}
void ClearBufferWriteReadyStatus_CH0(void)
{
rHM0_NORINTSTS = (1<<4);
while (rHM0_NORINTSTS & 0x10)
rHM0_NORINTSTS = (1<<4);
}
void ClearBufferReadReadyStatus_CH0(void)
{
rHM0_NORINTSTS = (1<<5);
while (rHM0_NORINTSTS & 0x20)
rHM0_NORINTSTS = (1<<5);
}
void ClearErrInterruptStatus_CH0(void)
{
while (rHM0_NORINTSTS&(0x1<<15))
{
rHM0_NORINTSTS =rHM0_NORINTSTS;
rHM0_ERRINTSTS =rHM0_ERRINTSTS;
}
}
int WaitForBufferWriteReady_CH0(void)
{
while (!(rHM0_NORINTSTS&0x10));
return 1;
}
int WaitForBufferReadReady_CH0(void)
{
U32 uLoop=0;
while (!(rHM0_NORINTSTS&0x20))
{
if (uLoop%500000==0&&uLoop>0)
{
return 0;
}
uLoop++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -