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

📄 sd.c

📁 SDIO实现底层驱动文件.非常有用.经典!
💻 C
📖 第 1 页 / 共 5 页
字号:
		}	
		#if defined(MSDC_SD_BITS4_BUS)
		if((status = SD_SetBusWidth(BIT_4W))!=NO_ERROR)
		{
			goto err;
		}
		#endif
		if((status = SD_Acmd42(KAL_FALSE))!=NO_ERROR)
		{
			goto err;
		}		
	}
	else
	{
		#if defined(MSDC_MMC40_SUPPORT)
		if(gMSDC_Handle.mMSDC_type == MMC_CARD && gSD.mCSD.spec_ver >= 4)
		{
			gMSDC_Handle.mMSDC_type = MMC40_CARD;
			if((status = SD_SetMMC40_bus_high_speed())!= NO_ERROR)
				goto err;
		}	
		else
		#endif
		{
			MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_CLKSRC);
			gMSDC_Handle.msdc_clock = MSDC_CLOCK;
			MSDC_SetClock(MSDC_OP_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)
	{
		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);
	}

	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)
	{
		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.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;


	while(!(sdc_cmdsta = *(volatile kal_uint16*)SDC_CMDSTA)
		&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
	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;                                     	
	}
#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");
		return ERR_DAT_CRCERR;                     
	}
	else if(sdc_datsta & SDC_DATSTA_BLKDONE)       
		return NO_ERROR;                                     
   }                                	
#else
	{
	volatile kal_uint16 sdc_datsta;	

	while(!(sdc_datsta = *(volatile kal_uint16*)SDC_DATSTA)
		&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
	MSDC_STOP_TIMER();
	MSDC_CLR_INT();
	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");
		return ERR_DAT_CRCERR;                     
	}
	else if(sdc_datsta & SDC_DATSTA_BLKDONE)       
		return NO_ERROR;                                     
	}
#endif
	
	return NO_ERROR;
}
/*************************************************************************
* FUNCTION
*  SD_WaitCardNotBusy
*
* DESCRIPTION
*	Wait until card is not busy (R1b)
*
* PARAMETERS
*	
* RETURNS
*	void
*
* GLOBALS AFFECTED
*	
* NOTE
*	Interrupt driven and polling are both implemented
*
*************************************************************************/

SDC_CMD_STATUS SD_WaitCardNotBusy(void)
{
	MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
#ifdef MSDC_USE_INT
	{
	kal_uint32 	flags = 0;
	if(!gMSDC_Handle.mIsPresent)
		return;
	kal_retrieve_eg_events(MSDC_Events,EVENT_SDR1BIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);				
	}
#else	
	{
	while(SD_IS_R1B_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
	MSDC_CLR_INT();
	MSDC_STOP_TIMER();
	}
#endif

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_CheckStatus
*
* DESCRIPTION
*	Check command status
*
* PARAMETERS
*	
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_CheckStatus()
{
	kal_uint32 status;

	MSDC_ReadReg32(SDC_RESP0,&status);
	if((status & SDC_CSTA_MASK)==0 )
		return NO_ERROR;
	if(status &SDC_CARD_IS_LOCKED)
		return CARD_IS_LOCKED;

	return ERR_STATUS;
}

/*************************************************************************
* FUNCTION
*  SD_Send_Cmd
*
* DESCRIPTION
*	to launch the command packet to the card
*
* PARAMETERS
*	1. cmd: the content of SDC_CMD register
*	2. arg: the argument(if the command need no argument, fill it with 0)
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*	1. Check if controller is available  before launch any commands 
*	2. Maybe add check if card is busy (R1b)
*************************************************************************/
SDC_CMD_STATUS SD_Send_Cmd(kal_uint32 cmd, kal_uint32 arg)
{
	SDC_CMD_STATUS status;

	MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
	// check the controller is ready (stop transaction will fail)
	if(cmd != SDC_CMD_CMD12)		
		while(SD_IS_SDC_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
	else
		while(SD_IS_CMD_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);		
	MSDC_STOP_TIMER();
	MSDC_CLR_INT();
	// fill out the argument
	MSDC_WriteReg32(SDC_ARG,arg);
	// launch the command
	MSDC_WriteReg32(SDC_CMD,cmd);
	if((status = SD_WaitCmdRdyOrTo())!=NO_ERROR)
		return status; 

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_Reset
*
* DESCRIPTION
*	reset all cards to idle state
*
* PARAMETERS
*	1. cmd: the content of SDC_CMD register
*	2. arg: the argument(if the command need no argument, fill it with 0)
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Reset(void)
{
	SDC_CMD_STATUS status;

	status = SD_Send_Cmd(SDC_CMD_CMD0,SDC_NO_ARG);
	gSD.mState = IDLE_STA;

	return status;
}

/*************************************************************************
* FUNCTION
*  SD_Cmd55
*
* DESCRIPTION
*	APP_CMD: inidicate to the card that the next command is an application specified command
*			rather than a standard command
*
* PARAMETERS
*	rca: relative card address
*
* RETURNS
*	SDC_CMD_STATUS
*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -