📄 sd.c
字号:
#endif
}
void SD_Use13M_Clock(void)
{
#ifndef DRV_LSD
MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_CLKSRC);
gMSDC_Handle->msdc_clock = MSDC_CLOCK;
MSDC_SetClock(MSDC_OP_CLOCK);
gSD->flags &= ~SD_FLAG_USE_USB_CLK;
#else
LSD_HostSetClock(LSD_SPEED_52M);
#endif
}
/*************************************************************************
* FUNCTION
* SD_Initialize
*
* DESCRIPTION
* Initial SD controller and card
*
* PARAMETERS
*
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
SDC_CMD_STATUS SD_Initialize(void)
{
kal_uint32 cid[4],csd[4],scr[4];
kal_uint16 rca, iocon;
SDC_CMD_STATUS status;
if(gMSDC_Handle->mIsInitialized == KAL_TRUE)
{
return NO_ERROR;
}
// reset the events
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
// reset msdc
#ifndef DRV_LSD
if(*(volatile kal_uint32*)MSDC_CFG & MSDC_CFG_RST)
#else
ASSERT(LSD_Support());
if(LSD_Reg32(MSDC_CFG) & MSDC_CFG_RST)
#endif
{
MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_RST);
}
else
{
RESET_MSDC();
}
//#if defined(MT6225)
#if defined(DRV_MSDC_MT6225_SERIES)
MSDC_SET_BIT32(MSDC_CFG,MSDC_CFG_CRED);
#endif
// set the output driving capability from customization interface
#if defined(__SIM_PLUS__)
MSDC_WriteReg16(MSDC_IOCON,0x2DB);
#else
iocon = *(volatile kal_uint16*)MSDC_IOCON;
iocon &= ~(0xff);
iocon |= MSDC_GetIOCtrlParam();
MSDC_WriteReg16(MSDC_IOCON,(kal_uint16)iocon);
#endif
// set pull up the data and cmd
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)2,MSDC_CFG_PRCFG0);
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)2,MSDC_CFG_PRCFG1);
BitFieldWrite32((kal_uint32*)MSDC_CFG,(kal_uint32)2,MSDC_CFG_PRCFG2);
// set read timeout x5ms
BitFieldWrite32((kal_uint32*)SDC_CFG,(kal_uint32)40,SDC_CFG_DTOC);
//set clock of serial clcok for initialization
#ifndef DRV_LSD
MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_CLKSRC);
gMSDC_Handle->msdc_clock = MSDC_CLOCK;
MSDC_SetClock(MSDC_INI_CLOCK);
#else
LSD_HostSetClock(LSD_SPEED_INIT);
#endif
// disable 4-bit
MSDC_CLR_BIT32(SDC_CFG,SDC_CFG_MDLEN);
// initial global sturctures
SD_SetDefault();
#if defined(__SIM_PLUS__)
// turn on the power of the MMC of the SIM+
if(INT_USBBoot() == KAL_TRUE && current_card == SD_SIM)
{
static kal_bool is_first = KAL_TRUE;
if(is_first)
{
is_first = KAL_FALSE;
GPIO_WriteIO(1, GPIO_LDO_SWITCH);
GPTI_BusyWait(300);
}
}
#endif
#ifdef DRV_LSD
LSD_Host74TCMDHigh();
#endif
// send the card to IDLE state
if((status = SD_Reset())!=NO_ERROR)
{
goto err;
}
// and validate the OCR (CMD0,CMD1 or ADMD41)
if(SD_CheckSDorMMC() == UNKNOWN_CARD)
{
status = ERR_STATUS;
goto err;
}
// get CID(CMD2)
if((status = SD_GetCID(cid))!=NO_ERROR)
{
goto err;
}
// get or set RCA(CMD3)
if((status = SD_ValidateRCA(&rca))!=NO_ERROR)
{
goto err;
}
// get CSD and analysis the CSD(CMD9)
if((status = SD_GetCSD(gSD->mRCA,csd))!=NO_ERROR)
{
goto err;
}
// Set driver stage register DSR to default value (0x0404)(CMD4)
if(gSD->mCSD.dsr_imp)
if((status = SD_SetDSR())!=NO_ERROR)
{
//dbg_print("6\r\n");
goto err;
}
#ifndef DRV_LSD
#if !defined(__MSDC_NO_WRITE_PROTECT__)
// check write proctect switch(WP at SDC_STA)
#if defined(__SIM_PLUS__)
if(current_card == SD_EXT)
#endif
{
if((*(volatile kal_uint16*)SDC_STA & SDC_STA_WP))
gSD->mWPEnabled = KAL_TRUE;
}
#endif
#endif
// select the card (CMD7) ,maybe locked
status = SD_SelectCard(gSD->mRCA);
if(status == CARD_IS_LOCKED)
gSD->mIsLocked = KAL_TRUE;
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
if(gSD->flags & SD_FLAG_SD_TYPE_CARD)
#else
if(gMSDC_Handle->mMSDC_type == SD_CARD)
#endif
{
#if defined(MSDC_USE_USB_CLK) && !defined(__SIM_PLUS__)
SD_Use24M_Clock();
#else
/*JRD SIM+ issue on 2007_03_08, JRD data line signal not stable, we can't use 24M even without SIM+ existence*/
if((!MSDC_Blk[SD_SIM].mIsInitialized) && (MSDC_24M == MSDC_GetClockWithoutSIMPlus()))
SD_Use24M_Clock();
else
SD_Use13M_Clock();
#endif
if((status = SD_ReadSCR(scr))!=NO_ERROR)
{
goto err;
}
#if defined(MSDC_SD_BITS4_BUS)
if((status = SD_SetBusWidth(BIT_4W))!=NO_ERROR)
{
goto err;
}
#endif
#if !defined(__MSDC_TFLASH_DAT3_1BIT_HOT_PLUG__)
if((status = SD_Acmd42(KAL_FALSE))!=NO_ERROR)
{
goto err;
}
#endif
if(gSD->flags & SD_FLAG_CMD6_SUPPORT)
{
status = SD_SelectHighSpeed_SD11();
if(status == NO_ERROR)
{
dbg_print("SD_SelectHighSpeed_SD11 fail\r\n");
gSD->flags |= SD_FLAG_HS_ENABLED;
//1 NEED to Modify such as using 48M clock
MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_CLKSRC);
gMSDC_Handle->msdc_clock = MSDC_CLOCK;
MSDC_SetClock(26000);
}
}
}
else
{
#if defined(MSDC_MMC40_SUPPORT)
if((gMSDC_Handle->mMSDC_type == MMC_CARD || gMSDC_Handle->mMSDC_type == MMC42_CARD) && gSD->mCSD.spec_ver >= 4)
{
if(gMSDC_Handle->mMSDC_type == MMC_CARD)/*we don't need to change MMC42_CARD to MMC40_CARD*/
gMSDC_Handle->mMSDC_type = MMC40_CARD;
if((status = SD_SetMMC40_bus_high_speed())!= NO_ERROR)
goto err;
}
else
#endif
{
SD_Use13M_Clock();
}
}
// set block length (CMD16)
status = SD_SetBlength(512);
err:
if(status != NO_ERROR)
{
kal_print("SD mount fail!");
SD_SetDefault();
gMSDC_Handle->mIsInitialized = KAL_FALSE;
}
else
{
kal_print("SD mount ok!");
gMSDC_Handle->mIsInitialized = KAL_TRUE;
}
kal_set_eg_events(MSDC_Events, 0, KAL_AND);
return status ;
}
void SD_InvertN(kal_uint8 *dest, kal_uint8 *src, kal_uint8 len)
{
int i;
for(i=0; i<len; i++)
*(dest+len-1-i) = *(src+i);
}
/*************************************************************************
* FUNCTION
* power2
*
* DESCRIPTION
* Calculate the power of 2
*
* PARAMETERS
* num:
*
* RETURNS
* 2^num
*
* GLOBALS AFFECTED
*
*************************************************************************/
static kal_uint32 power2(kal_uint32 num)
{
return 1 << num;
}
/*************************************************************************
* FUNCTION
* SD_AnalysisCSD
*
* DESCRIPTION
* Analysis Card Specific Data and store in the member of gSD
*
* PARAMETERS
* csd: input csd for analysis
* RETURNS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
void SD_AnalysisCSD(kal_uint32* csd)
{
kal_uint8 *ptr;
kal_uint32 c_mult,c_size;
ptr = (kal_uint8*)csd;
c_mult = c_size = 0;
// these offsets refer to the spec. of SD and MMC
GetBitFieldN((kal_uint8*)&gSD->mCSD.csd_ver, ptr, 126,2);
GetBitFieldN((kal_uint8*)&gSD->mCSD.tacc,ptr,112,8);
GetBitFieldN((kal_uint8*)&gSD->mCSD.nsac,ptr,104,8);
GetBitFieldN((kal_uint8*)&gSD->mCSD.tran_speed,ptr,96,8);
GetBitFieldN((kal_uint8*)&gSD->mCSD.ccc,ptr,84,12);
GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_len,ptr,80,4);
gSD->mCSD.r_blk_len = power2(gSD->mCSD.r_blk_len);
GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_part,ptr,79,1);
GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_misali,ptr,78,1);
GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_misali,ptr,77,1);
GetBitFieldN((kal_uint8*)&gSD->mCSD.dsr_imp,ptr,76,1);
GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_part,ptr,21,1);
GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_len,ptr,22,4);
gSD->mCSD.w_blk_len = power2(gSD->mCSD.w_blk_len);
GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_grp_enable,ptr,31,1);
// there are some difference of CSD between SD and MMC
if(gMSDC_Handle->mMSDC_type == MMC_CARD || gMSDC_Handle->mMSDC_type == MMC42_CARD)
{
GetBitFieldN((kal_uint8*)&gSD->mCSD.spec_ver, ptr, 122,4);
GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_sec_size_mmc,ptr,42,5);
gSD->mCSD.erase_sec_size_mmc = (gSD->mCSD.erase_sec_size_mmc+1)*gSD->mCSD.w_blk_len;
GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_grp_size_mmc,ptr,37,5);
gSD->mCSD.erase_grp_size_mmc = (gSD->mCSD.erase_grp_size_mmc+1)*gSD->mCSD.erase_sec_size_mmc;
GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_grp_size_mmc,ptr,32,5);
gSD->mCSD.wp_grp_size_mmc = (gSD->mCSD.wp_grp_size_mmc + 1)*gSD->mCSD.erase_grp_size_mmc;
}
else // SD_CARD
{
GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_sec_size_sd,ptr,39,7);
gSD->mCSD.erase_sec_size_sd += 1;
GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_prg_size_sd,ptr,32,7);
gSD->mCSD.wp_prg_size_sd = (gSD->mCSD.wp_prg_size_sd+1) * gSD->mCSD.erase_sec_size_sd;
GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_blk_en_sd,ptr,46,1);
}
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
if(gMSDC_Handle->mMSDC_type == SD20_HCS_CARD && gSD->mCSD.csd_ver >= SD_CSD_VER_20)
{
GetBitFieldN((kal_uint8*)&c_size,ptr,48,22);
gSD->mBKNum = (c_size+1);
gSD->mCSD.capacity = (kal_uint64)gSD->mBKNum*512*1024;
}
else
#endif
{
GetBitFieldN((kal_uint8*)&c_mult,ptr,47,3);
c_mult = power2(c_mult+2);
GetBitFieldN((kal_uint8*)&c_size,ptr,62,12);
gSD->mBKNum = (c_size+1)*c_mult;
gSD->mCSD.capacity = (c_size+1)*c_mult*gSD->mCSD.r_blk_len;
}
}
/*************************************************************************
* FUNCTION
* SD_AnalysisCID
*
* DESCRIPTION
* Analysis Card Identificaton and store in the member of gSD
*
* PARAMETERS
* cid: input of card ID for analysis
* RETURNS
*
* GLOBALS AFFECTED
* gSD
*
*************************************************************************/
void SD_AnalysisCID(kal_uint32* cid)
{
kal_uint8 i;
kal_uint8* pcid;
pcid = (kal_uint8*)cid;
if(gMSDC_Handle->mMSDC_type == MMC_CARD || MMC42_CARD == gMSDC_Handle->mMSDC_type)
{
GetBitFieldN((kal_uint8*)&gSD->mCID.year,pcid,8,4);
gSD->mCID.year += 1997;
GetBitFieldN((kal_uint8*)&gSD->mCID.month,pcid,12,4);
GetBitFieldN((kal_uint8*)&gSD->mCID.psn,pcid,16,32);
GetBitFieldN((kal_uint8*)&gSD->mCID.prv,pcid,48,8);
for(i=0;i<6;i++)
gSD->mCID.pnm[i] = *(pcid+7+i);
GetBitFieldN((kal_uint8*)&gSD->mCID.oid,pcid,104,16);
GetBitFieldN((kal_uint8*)&gSD->mCID.mid,pcid,120,8);
// special case handling
{
kal_uint8 pnm[] = {0xFF,0xFF,0xFF,0xFF,0x36,0x31};
if(gSD->mCID.mid == 6 && gSD->mCID.oid == 0 &&
!kal_mem_cmp(gSD->mCID.pnm,pnm,6))
{
gSD->flags |= SD_FLAG_MMC_MRSW_FAIL;
}
}
}
else // SD_CARD
{
gSD->mCID.mid = *(pcid+15);
gSD->mCID.oid = *(pcid+13) + 256*(*(pcid+14));
for(i=0;i<5;i++)
gSD->mCID.pnm[i] = *(pcid+8+i);
gSD->mCID.prv = *(pcid+7);
gSD->mCID.psn = *(kal_uint32*)(pcid+3);
gSD->mCID.month = (kal_uint8)GET_BIT(*(pcid+1),0,BIT_MASK_4);
gSD->mCID.year = GET_BIT(*(pcid+1),4,BIT_MASK_4)+16*GET_BIT(*(pcid+2),0,BIT_MASK_4) + 2000;
}
}
/*************************************************************************
* FUNCTION
* SD_AnalysisSCR
*
* DESCRIPTION
* Analysis SD Card Configuration Register and store in the member of gSD
*
* PARAMETERS
* scr: input of scr for analysis
* RETURNS
*
* GLOBALS AFFECTED
* gSD
*
* NOTE
* Only for SD card.
*
*************************************************************************/
void SD_AnalysisSCR(kal_uint32* scr)
{
kal_uint8 *pscr;
pscr = (kal_uint8*)scr;
gSD->mSCR.spec_ver = (kal_uint8)GET_BIT(*(pscr),0,BIT_MASK_4);
if(gSD->mSCR.spec_ver > SD_SPEC_101)
gSD->flags |= SD_FLAG_CMD6_SUPPORT;
gSD->mSCR.dat_after_erase = (kal_uint8)GET_BIT(*(pscr+1),7,BIT_MASK_1);
gSD->mSCR.security = (kal_uint8)GET_BIT(*(pscr+1),4,BIT_MASK_3);
gSD->mSCR.bus_width = (kal_uint8)GET_BIT(*(pscr+1),0,BIT_MASK_4);
}
/*************************************************************************
* FUNCTION
* SD_WaitCmdRdyOrTo
*
* DESCRIPTION
* Wait until command ready or timeout
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Interrupt driven and polling are both implemented
*
*************************************************************************/
SDC_CMD_STATUS SD_WaitCmdRdyOrTo(void)
{
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
#ifdef MSDC_USE_INT
{
kal_uint32 flags = 0;
kal_uint16 sdc_cmdsta = 0;
if(!gMSDC_Handle->mIsPresent)
return ERR_CARD_NOT_PRESENT;
kal_retrieve_eg_events(MSDC_Events,EVENT_SDCMDIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
MSDC_STOP_TIMER();
sdc_cmdsta = *(volatile kal_uint16*)SDC_CMDSTA;
gMSDC_Handle->cmd_sta = sdc_cmdsta;
if(sdc_cmdsta & SDC_CMDSTA_CMDTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd timeout");
return ERR_CMD_TIMEOUT;
}
else if(sdc_cmdsta & SDC_CMDSTA_RSPCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd crc");
return ERR_CMD_RSPCRCERR;
}
else if(sdc_cmdsta & SDC_CMDSTA_CMDRDY)
return NO_ERROR;
}
#else
{
volatile kal_uint16 sdc_cmdsta;
kal_uint32 t1;
t1 = drv_get_current_time();
#ifndef DRV_LSD
while(!(sdc_cmdsta = *(volatile kal_uint16*)SDC_CMDSTA)
#else
while(!(sdc_cmdsta = LSD_Reg32(SDC_CMDSTA))
#endif
&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
{
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_CMD*11)
gMSDC_Handle->is_timeout = KAL_TRUE;
}
MSDC_STOP_TIMER();
MSDC_CLR_INT();
gMSDC_Handle->cmd_sta = sdc_cmdsta;
if(sdc_cmdsta & SDC_CMDSTA_CMDTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd timeout");
return ERR_CMD_TIMEOUT;
}
else if(sdc_cmdsta & SDC_CMDSTA_RSPCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:cmd crc");
return ERR_CMD_RSPCRCERR;
}
else if(sdc_cmdsta & SDC_CMDSTA_CMDRDY)
return NO_ERROR;
}
if(gMSDC_Handle->is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
#endif
return NO_ERROR;
}
/*************************************************************************
* FUNCTION
* SD_WaitDatRdyOrTo
*
* DESCRIPTION
* Wait until data ready or timeout
*
* PARAMETERS
*
* RETURNS
* SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Interrupt driven and polling are both implemented
*
*************************************************************************/
SDC_CMD_STATUS SD_WaitDatRdyOrTo(void)
{
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
#ifdef MSDC_USE_INT
{
kal_uint16 sdc_datsta = 0;
kal_uint32 flags = 0;
if(!gMSDC_Handle->mIsPresent)
return ERR_CARD_NOT_PRESENT;
kal_retrieve_eg_events(MSDC_Events,EVENT_SDDATIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
MSDC_STOP_TIMER();
sdc_datsta = *(volatile kal_uint16*)SDC_DATSTA;
gMSDC_Handle->dat_sta = sdc_datsta;
if(sdc_datsta & SDC_DATSTA_DATTO)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:dat timeout");
return ERR_DAT_TIMEOUT;
}
else if(sdc_datsta & SDC_DATSTA_DATCRCERR)
{
kal_prompt_trace(MOD_MSDC_HISR,"[MSDC]:dat crc");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -