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

📄 sd.c

📁 一个复杂控制SD卡的例子,可以参考应用到手机上.
💻 C
📖 第 1 页 / 共 5 页
字号:
		return ERR_DAT_CRCERR;                     
	}
	else if(sdc_datsta & SDC_DATSTA_BLKDONE)       
		return NO_ERROR;                                     
   }                                	
#else
	{
	volatile kal_uint16 sdc_datsta;	
	kal_uint32 t1;

	t1 = drv_get_current_time();
#ifndef DRV_LSD
	while(!(sdc_datsta = *(volatile kal_uint16*)SDC_DATSTA)
#else
	while(!(sdc_datsta = LSD_Reg32(SDC_DATSTA))
#endif
		&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
	{
		if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
			gMSDC_Handle->is_timeout = KAL_TRUE;		
	};
	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;                                     
	}
	if(gMSDC_Handle->is_timeout)
		return MSDC_GPT_TIMEOUT_ERR;
#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)
{
	kal_uint32 t1;

	t1 = drv_get_current_time();
	MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
#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)
	{
		if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
			gMSDC_Handle->is_timeout = KAL_TRUE;
	};
	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;
	kal_uint32 t1;

	t1 = drv_get_current_time();
	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)
		{
			if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
				gMSDC_Handle->is_timeout = KAL_TRUE;
		}
	}
	else
	{
		while(SD_IS_CMD_BUSY && MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
		{
			if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
				gMSDC_Handle->is_timeout = KAL_TRUE;
		}
	}
	MSDC_STOP_TIMER();
	if(gMSDC_Handle->is_timeout)
		return MSDC_GPT_TIMEOUT_ERR;
	
	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
*
* GLOBALS AFFECTED
*	
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Cmd55(kal_uint16 rca)
{
	SDC_CMD_STATUS status;

	if((status = SD_Send_Cmd(SDC_CMD_CMD55,(kal_uint32)rca<<16))!=NO_ERROR)
		return status;
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;
	//check APP_CMD bit in status register
	MSDC_ReadReg32(SDC_RESP0,&status);
	if(!(status & R1_APP_CMD_5))
		return ERR_APPCMD_FAILED;

	return NO_ERROR;	
}
/*************************************************************************
* FUNCTION
*  SD_Cmd8
*
* DESCRIPTION
*	1. Sends SD Memory Card interface conditions for support larger than 2G cards
*	2. check if the card is compliant to SD2.0 or higher
*	3. only performed while at IDLE state.
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*	gSD->mIsCMD8
*
*************************************************************************/
void SD_Cmd8(void)
{
	kal_uint32 resp;

	if(SD_Send_Cmd(SDC_CMD_CMD8,SDC_CMD8_ARG)!=NO_ERROR)
	{
		dbg_print("SD_Cmd8 fail \r\n");
		SD_Reset();
		gSD->mCMD8Resp = SD_CMD8_RESP_NORESP;
		return;
	}
	MSDC_ReadReg32(SDC_RESP0,&resp);
	if(resp == SDC_CMD8_ARG)
		gSD->mCMD8Resp = SD_CMD8_RESP_VALID;
	else
		gSD->mCMD8Resp = SD_CMD8_RESP_INVALID;
}

/*************************************************************************
* FUNCTION
*  SD_Cmd1_MMC
*
* DESCRIPTION
*	 asks all cards in idle state to send their OCR in the response on the CMD line
*
* PARAMETERS
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	gSD
*
* NOTE
*	only works for MMC
*
*************************************************************************/
SDC_CMD_STATUS SD_Cmd1_MMC(void)
{
	SDC_CMD_STATUS status;
	kal_uint32 _ocr, ocr_i, t1, t2;

	#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
	if(gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
		return ERR_CMD8_INVALID;
	ocr_i = (SDC_OCR_DEFAULT|MMC_HIGH_DESITY_CHECK_BIT);
	#else
	ocr_i = SDC_OCR_DEFAULT;
	#endif

	if(gMSDC_Handle->is_init_timeout == KAL_TRUE)
		return ERR_R3_OCR_BUSY;
	t2 = drv_get_current_time();
	do{
		t1 = drv_get_current_time();
		MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
		while((MSDC_IS_BUSY)
			&& MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
		{
			if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
				gMSDC_Handle->is_timeout = KAL_TRUE;
		};
		MSDC_STOP_TIMER();		
		if(gMSDC_Handle->is_timeout)
			return MSDC_GPT_TIMEOUT_ERR;		
		MSDC_WriteReg32(SDC_ARG,ocr_i);
		MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD1);
		if((status = SD_WaitCmdRdyOrTo())  != NO_ERROR)
		{
			return status;
		}		
		MSDC_ReadReg32(SDC_RESP0, &_ocr);
		if((_ocr & SDC_OCR_DEFAULT) == 0)
			return ERR_OCR_NOT_SUPPORT;
		if(!gMSDC_Handle->mIsPresent)
			return MSDC_CARD_NOT_PRESENT;
		
		if(!(_ocr&SDC_OCR_BUSY))		
		{
			if(drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
			{
				gMSDC_Handle->is_init_timeout = KAL_TRUE;			
				break;
			}					
			if((kal_query_systemInit() == KAL_TRUE) 
#ifdef  __TST_WRITE_TO_FILE_ONLY__ 			/*error recording: considering error recording additionally*/
				|| (KAL_TRUE == INT_QueryExceptionStatus())
#endif
			)
				GPTI_BusyWait(30);
			else
				kal_sleep_task(7);
				
		}
		else
			break;		
	}while(1);

	if(gMSDC_Handle->is_init_timeout)
		return ERR_CMD_TIMEOUT;

	#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
	if((_ocr & MMC_HIGH_DESITY_CHECK_MSK) == MMC_HIGH_DESITY_CHECK_BIT)
	{
		gSD->flags |= SD_FLAG_HCS_SUPPORT;
		gMSDC_Handle->mMSDC_type = MMC42_CARD;
		kal_print("MMC4.2 or higher");
	}
	else
	#endif
	gMSDC_Handle->mMSDC_type = MMC_CARD;
	gSD->mInactive = KAL_FALSE;
	gSD->mSDC_ocr = _ocr;
	gSD->mState = READY_STA;
	
	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_Acmd41_SD
*
* DESCRIPTION
*	asks all cards in idle state to send their OCR in the response on the CMD line
*	OCR: Operation Condition Register
*
* PARAMETERS
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	gSD
*
* NOTE
*	only works for SD
*
*************************************************************************/
SDC_CMD_STATUS SD_Acmd41_SD(void)
{

	SDC_CMD_STATUS		status;
	kal_uint32			_ocr = 0, ocr_i, t1, t2;
	
#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)	
	if(gSD->mCMD8Resp == SD_CMD8_RESP_NORESP)
		ocr_i = SDC_OCR_DEFAULT;
	else if(gSD->mCMD8Resp == SD_CMD8_RESP_VALID)
		ocr_i = (SDC_OCR_DEFAULT|SD_ACMD41_HCS);
	else if(gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
		return ERR_CMD8_INVALID;	
#else	
	ocr_i = SDC_OCR_DEFAULT;
#endif	

	gMSDC_Handle->is_init_timeout = KAL_FALSE;
	t2 = drv_get_current_time();
	do{
		t1 = drv_get_current_time();		
		MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
		while((MSDC_IS_BUSY)
			&& 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();
		if(gMSDC_Handle->is_timeout)
			return MSDC_GPT_TIMEOUT_ERR;		
		status=SD_Cmd55(SDC_RCA_DEFAULT);
		if(status != NO_ERROR)
		{
			return status;
		}
		MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
		t1 = drv_get_current_time();
		while((MSDC_IS_BUSY)
			&& 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();
		if(gMSDC_Handle->is_timeout)
			return MSDC_GPT_TIMEOUT_ERR;		
		MSDC_WriteReg32(SDC_ARG,ocr_i);
		MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD41_SD);
		if((status = SD_WaitCmdRdyOrTo())  != NO_ERROR)
		{
			return status;
		}		
		MSDC_ReadReg32(SDC_RESP0, &_ocr);
		if((_ocr & SDC_OCR_DEFAULT) == 0)
			return ERR_OCR_NOT_SUPPORT;
		if(!gMSDC_Handle->mIsPresent)
			return ERR_CARD_NOT_PRESENT;	
		if(!(_ocr&SDC_OCR_BUSY))		
		{
			if(drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
			{
				gMSDC_Handle->is_init_timeout = KAL_TRUE;			
				break;
			}					
			if((kal_query_systemInit() == KAL_TRUE) 
#ifdef  __TST_WRITE_TO_FILE_ONLY__ 			/*error recording: considering error recording additionally*/
				|| (KAL_TRUE == INT_QueryExceptionStatus())
#endif
			)
				GPTI_BusyWait(30);
			else
				kal_sleep_task(7);
		}
		else
			break;		
	}
	while(1);

	if(gMSDC_Handle->is_init_timeout)
		return ERR_R3_OCR_BUSY;

	gSD->mInactive = KAL_FALSE;
	gSD->mSDC_ocr = _ocr;
	#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
	gSD->flags |= SD_FLAG_SD_TYPE_CARD;	
	if(_ocr & SD_ACMD41_HCS)
	{
		gSD->flags |= SD_FLAG_HCS_SUPPORT;
		gMSDC_Handle->mMSDC_type = SD20_HCS_CARD;
		kal_print("SD2.0 or higher");
	}
	else if(gSD->mCMD8Resp == SD_CMD8_RESP_VALID)
		gMSDC_Handle->mMSDC_type = SD20_LCS_CARD;
	else
	#endif
		gMSDC_Handle->mMSDC_type = SD_CARD;
	gSD->mState = READY_STA;

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_GetCID
*
* DESCRIPTION
*	Read Card Identification.
*
* PARAMETERS
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	gSD
*
* NOTE
*	
*
*************************************************************************/

// Get CID(CMD2)
SDC_CMD_STATUS SD_GetCID(kal_uint32 Cid[4])
{
	int i;
	SDC_CMD_STATUS status;

	if((status = SD_Send_Cmd(SDC_CMD_CMD2,SDC_NO_ARG))!=NO_ERROR)
		return status;
	//read R2
	for(i=0;i<4;i++)
		MSDC_ReadReg32((SDC_RESP0+i*sizeof(kal_uint32)), &Cid[i]);
	SD_AnalysisCID(Cid);
	gSD->mState = IDENT_STA;
	
	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_ValidateRCA
*
* DESCRIPTION
*	assing or read RCA
*
* PARAMETERS
*	pRca: used for input or output RCA
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	gSD
*
* NOTE
*	RCA is assinged to MMC card fixed to SDC_RCA_MMC(1)
*
*************************************************************************/

// assign or read RCA
SDC_CMD_STATUS SD_ValidateRCA(kal_uint16* pRca)
{
	SDC_CMD_STATUS status;
	kal_uint32 resp;
	kal_uint8  state;

	#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)

⌨️ 快捷键说明

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