📄 hs1_mmc.c
字号:
if (rHM1_RSPREG0&(0x1<<31))
{
if(rHM1_RSPREG0 & (1<<7))
printf("\nVoltage range : 1.65V ~ 1.95V");
if(rHM1_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n\n");
else if(rHM1_RSPREG0 & (1<<20))
printf("\nVoltage range: 2.7V ~ 3.3V\n\n");
else if(rHM1_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n\n");
else if(rHM1_RSPREG0 & (1<<23))
printf("\nVoltage range: 2.7V ~ 3.6V\n\n");
if(rHM1_RSPREG0&(0x1<<30))
{
printf("\nHigh Capacity Card\n");
SectorMode_ch1 = 1;
}
ThisIsMmc_ch1 = 0;
return 1;
}
Delay(10);
}
// The current card is MMC card, then there's time out error, need to be cleared.
ClearErrInterruptStatus_CH1();
return 0;
}
int SetMMCOCR_CH1(void)
{
U32 i, OCR;
for (i=0; i<250; i++)
{
IssueCommand_CH1(1, 0x0, 0);
OCR = rHM1_RSPREG0 | (1<<30);
IssueCommand_CH1(1, OCR, 0); // (Ocr:2.7V~3.6V)
if (rHM1_RSPREG0&(0x1<<31))
{
if(rHM1_RSPREG0 & (1<<7))
printf("\nVoltage range : 1.65V ~ 1.95V");
if(rHM1_RSPREG0 & (1<<21))
printf("\nVoltage range: 2.7V ~ 3.4V\n");
else if(rHM1_RSPREG0 & (1<<20))
printf("\nVoltage range: 2.7V ~ 3.3V\n");
else if(rHM1_RSPREG0 & (1<<19))
printf("\nVoltage range: 2.7V ~ 3.2V\n");
else if(rHM1_RSPREG0 & (1<<18))
printf("\nVoltage range: 2.7V ~ 3.1V\n");
if(rHM1_RSPREG0 & (1<<30))
{
printf("\nHigh Capacity Sector Mode Operation\n");
SectorMode_ch1 = 1;
}
ThisIsMmc_ch1=1;
printf("\nrHM_RSPREG0 = %x\n",rHM1_RSPREG0);
return 1;
}
}
ClearErrInterruptStatus_CH1();
return 0;
}
void SetCommandReg_CH1(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_ch1) // 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);
}
rHM1_CMDREG = usSfr;
}
void setmmcspeedmode_CH1(U32 eSDSpeedMode)
{
U8 ucSpeedMode;
U32 uArg=0;
ucSpeedMode = (eSDSpeedMode == HIGH_CH1) ? 1 : 0;
uArg=(3<<24)|(185<<16)|(ucSpeedMode<<8); // Change to the high-speed mode
while(!IssueCommand_CH1(6, uArg, 0));
}
void SetSDSpeedMode_CH1(U32 eSDSpeedMode)
{
U32 uSfr;
U32 uArg = 0;
U8 ucSpeedMode;
int i;
ucSpeedMode = (eSDSpeedMode == HIGH_CH1) ? 1 : 0;
if (!IssueCommand_CH1(16, 64, 0)) // CMD16
printf("CMD16 fail\n");
else
{
SetBlockSizeReg_CH1(7, 64);
SetBlockCountReg_CH1(1);
SetArgumentReg_CH1(0*64);
SetTransferModeReg_CH1(0, 1, 0, 0, 0);
uArg = (0x1<<31)|(0xffff<<8)|(ucSpeedMode<<0);
if (!IssueCommand_CH1(6, uArg, 0))
printf("CMD6 fail\n");
else
{
WaitForBufferReadReady_CH1();
ClearBufferReadReadyStatus_CH1();
for(i=0; i<16; i++)
{
uSfr = rHM1_BDATA ;
}
WaitForTransferComplete_CH1();
ClearTransferCompleteStatus_CH1();
}
}
}
void SetClock_CH1(U32 ClkSrc, U16 Divisor)
{
rHM1_CONTROL2 = (rHM1_CONTROL2 & ~(0xffffffff)) | (0x1<<15)|(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
//rHM_CONTROL2 = (rHM_CONTROL2 & ~(0xffffffff)) |(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
//rHM1_CONTROL3 = (0<<31) | (1<<23) | (0<<15) | (1<<7);//SD OK
rHM1_CONTROL3 = (1<<31) | (1<<23) | (1<<15) | (1<<7);
// SDCLK Value Setting + Internal Clock Enable
rHM1_CLKCON = (rHM1_CLKCON & ~((0xff<<8)|(0x1))) | (Divisor<<8)|(1<<0);
// CheckInternalClockStable
while (!(rHM1_CLKCON&0x2));
ClockOnOff_CH1(1);
}
int IssueCommand_CH1( U16 uCmd, U32 uArg, U32 uIsAcmd)
{
U32 uSfr;
while ((rHM1_PRNSTS&0x1)); // Check CommandInhibit_CMD
//while ((rHM1_PRNSTS&0x2)); // Check dataInhibit_CMD
if (!uIsAcmd)//R1b type commands have to check CommandInhibit_DAT bit
{
if((uCmd==6&&ThisIsMmc_ch1)||uCmd==7||uCmd==12||uCmd==28||uCmd==29||uCmd==38||((uCmd==42||uCmd==56)&&(!ThisIsMmc_ch1)))
{
do {
uSfr = rHM1_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)
rHM1_ARGUMENT = uArg<<16;
else
rHM1_ARGUMENT = uArg;
}
else// <--------------------------- APP.Commnad (ACMD)
rHM1_ARGUMENT = uArg;
SetCommandReg_CH1(uCmd,uIsAcmd);
if (!WaitForCommandComplete_CH1())
{
printf(("Command NOT Complete\n"));
}
else
ClearCommandCompleteStatus_CH1();
if (!(rHM1_NORINTSTS&0x8000))
{
if(((rHM1_CMDREG>>8) == 0x8) &&(ThisIsMmc_ch1 !=1))
{
printf("\nCMD8 Support");
SDSpecVer_ch1 = 2;
}
return 1;
}
else
{
if(OCRcheck_ch1 == 1)
return 0;
else
{
printf("Command = %d, Error Stat = %x\n",(rHM1_CMDREG>>8),rHM1_ERRINTSTS);
rHM1_ERRINTSTS = rHM1_ERRINTSTS;
rHM1_NORINTSTS =rHM1_NORINTSTS;
if((rHM1_CMDREG>>8) == 0x8)
{
printf("\nThis Card version is NOT SD 2.0\n");
}
return 0;
}
}
}
void GetResponseData_CH1(U32 uCmd)
{
U32 uSfr0,uSfr1,uSfr2,uSfr3;
uSfr0 = rHM1_RSPREG0;
uSfr1 = rHM1_RSPREG1;
uSfr2 = rHM1_RSPREG2;
uSfr3 = rHM1_RSPREG3;
if(uCmd==3)
{
if(!ThisIsMmc_ch1)
{
m_uRca_ch1 = (uSfr0>>16)&0xFFFF;
printf("=> RCA=%d\n", m_uRca_ch1);
}
}
else if (uCmd==9)
{
if(ThisIsMmc_ch1)
{
m_ucMMCSpecVer_ch1=(rHM1_RSPREG3>>18)& 0xF;
printf("=> m_ucMMCSpecVer_ch1=%d\n", m_ucMMCSpecVer_ch1);
}
}
}
int GetSdSCR_CH1()
{
U32 uSCR1, uSCR2;
if (!IssueCommand_CH1(16, 8, 0))
return 0;
else
{
SetBlockSizeReg_CH1(7, 8);
SetBlockCountReg_CH1(1);
SetArgumentReg_CH1(0*8);
SetTransferModeReg_CH1(0, 1, 0, 0, 0);
if (!IssueCommand_CH1(55, m_uRca_ch1, 0)) // CMD55 (For ACMD)
return 0;
else
{
if (!IssueCommand_CH1(51, 0, 1)) // Acmd51
return 0;
else
{
WaitForBufferReadReady_CH1();
ClearBufferReadReadyStatus_CH1();
uSCR1 = rHM1_BDATA;
uSCR2 = rHM1_BDATA;
WaitForTransferComplete_CH1();
ClearTransferCompleteStatus_CH1();
if ((uSCR1&0xf) == 0x0)
SDSpecVer_ch1 = 0; // Version 1.0 ~ 1.01
else if ((uSCR1&0xf) == 0x1)
SDSpecVer_ch1 = 1; // Version 1.10, support cmd6
else if((uSCR1&0xf) == 0x2)
SDSpecVer_ch1 = 2; // Version 2.0 support cmd6 and cmd8
printf("SDSpecVer_ch1=%d\n", SDSpecVer_ch1);
return 1;
}
}
}
}
int IsCardInProgrammingState_CH1(void)
{
// check the card status.
U32 uSfr;
if (!IssueCommand_CH1(13, m_uRca_ch1, 0))
{
printf("Card status = %x",((rHM1_RSPREG0>>9)&0xf));
return 0;
}
else
{
if(((rHM1_RSPREG0>>9)&0xf) == 4)
{
printf("Card is transfer status\n");
return 1;
}
return 0;
}
}
void HostCtrlSpeedMode_CH1(U8 SpeedMode)
{
U8 ucSpeedMode;
ucSpeedMode = (SpeedMode == HIGH_CH1) ? 1 : 0;
rHM1_HOSTCTL &= ~(0x1<<2);
rHM1_HOSTCTL |= ucSpeedMode<<2;
}
void ClockConfig_CH1(U32 Clksrc, U32 Divisior)
{
U32 SrcFreq, WorkingFreq;
U32 RealDivisor;
if (Clksrc == SD_HCLK_CH1)
SrcFreq = HCLK;
else if (Clksrc == SD_EPLL_CH1)//Epll Out 48MHz
SrcFreq = 100000000;
else
Clksrc = HCLK;
if (Divisior !=0)
{
WorkingFreq = SrcFreq/(Divisior*2);
printf("HCLK = %d, SD WorkingFreq = %dMHz\n",HCLK,WorkingFreq/(1000000));
}
else
{
WorkingFreq = SrcFreq;
printf("WorkingFreq = %dMHz\n",WorkingFreq/(1000000));
}
if (ThisIsMmc_ch1)
{
if (m_ucMMCSpecVer_ch1==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_CH1(HIGH_CH1);
printf("\nSet MMC High speed mode OK!!\n");
}
else
{
setmmcspeedmode_CH1(NORMAL_CH1);
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_CH1();
if (SDSpecVer_ch1==1||SDSpecVer_ch1==2 )
{
if (WorkingFreq>25000000)
{
SetSDSpeedMode_CH1(HIGH_CH1);//Higher than 25MHz, should use high speed mode. Max 50MHz and 25MB/sec
printf("\nSet SD High speed mode OK!!\n");
}
else
{
SetSDSpeedMode_CH1(NORMAL_CH1);
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_CH1(HIGH_CH1);
}
else
{
HostCtrlSpeedMode_CH1(NORMAL_CH1);
}
ClockOnOff_CH1(0); // when change the sd clock frequency, need to stop sd clock.
SetClock_CH1(Clksrc, Divisior);
}
void HS_MMC_Irq_CH1(void)
{
pISR_SDI_1 = (int)HS_CARD_DETECT_INT_CH1; // Set interrupt service routine.
rINTMSK &= ~(BIT_SDI1);
}
void HS_MMC_Reset_CH1(void)
{
rHM1_SWRST = 0x3;
}
void HS_MMC_SETGPIO_CH1(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_CH1(U32 MultiBlk,U32 DataDirection, U32 AutoCmd12En,U32 BlockCntEn,U32 DmaEn)
{
rHM1_TRNMOD = (rHM1_TRNMOD & ~(0xffff)) | (MultiBlk<<5)|(DataDirection<<4)|(AutoCmd12En<<2)|(BlockCntEn<<1)|(DmaEn<<0);
}
void SetArgumentReg_CH1(U32 uArg)
{
rHM1_ARGUMENT = uArg;
}
void SetBlockCountReg_CH1(U16 uBlkCnt)
{
rHM1_BLKCNT = uBlkCnt;
}
void SetSystemAddressReg_CH1(U32 SysAddr)
{
rHM1_SYSAD = SysAddr;
}
void SetBlockSizeReg_CH1(U16 uDmaBufBoundary, U16 uBlkSize)
{
rHM1_BLKSIZE = (uDmaBufBoundary<<12)|(uBlkSize);
}
void ClockOnOff_CH1(int OnOff)
{
if (OnOff == 0)
{
rHM1_CLKCON &=~(0x1<<2);
}
else
{
rHM1_CLKCON|=(0x1<<2);
while (1)
{
if (rHM1_CLKCON&(0x1<<3)) // SD_CLKSRC is Stable
break;
}
}
}
void ClearCommandCompleteStatus_CH1(void)
{
rHM1_NORINTSTS=(1<<0);
while (rHM1_NORINTSTS&0x1)
{
rHM1_NORINTSTS=(1<<0);
}
}
void ClearTransferCompleteStatus_CH1(void)
{
rHM1_NORINTSTS = (1<<1);
while (rHM1_NORINTSTS&0x2)
{
rHM1_NORINTSTS = (1<<1);
}
}
void ClearBufferWriteReadyStatus_CH1(void)
{
rHM1_NORINTSTS = (1<<4);
while (rHM1_NORINTSTS & 0x10)
rHM1_NORINTSTS = (1<<4);
}
void ClearBufferReadReadyStatus_CH1(void)
{
rHM1_NORINTSTS = (1<<5);
while (rHM1_NORINTSTS & 0x20)
rHM1_NORINTSTS = (1<<5);
}
void ClearErrInterruptStatus_CH1(void)
{
while (rHM1_NORINTSTS&(0x1<<15))
{
rHM1_NORINTSTS =rHM1_NORINTSTS;
rHM1_ERRINTSTS =rHM1_ERRINTSTS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -