⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 一个复杂控制SD卡的例子,可以参考应用到手机上.
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 + -