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

📄 sd.c

📁 SDIO实现底层驱动文件.非常有用.经典!
💻 C
📖 第 1 页 / 共 5 页
字号:
* 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_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)
{
	kal_uint8 counter,timeout;
	kal_uint32 _ocr;
	// Fill out the OCR into SDC_ARG
	// VDD voltage window range form 2.8~3.1
	counter = 0;
	do{
		MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
		while((MSDC_IS_BUSY)
			&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
		MSDC_STOP_TIMER();				
		MSDC_WriteReg32(SDC_ARG,SDC_OCR_DEFAULT);
		// launch the command 1
		MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD1);
		// wait until response arrives
		// polling SDC_STA to make sure response is received or timeout
		if(SD_WaitCmdRdyOrTo() == ERR_CMD_TIMEOUT)
		{
			timeout = KAL_TRUE;
			continue;
		}		
		timeout = KAL_FALSE;
		//read the R3 response which contains card's OCR
		MSDC_ReadReg32(SDC_RESP0, &_ocr);
		if(!gMSDC_Handle.mIsPresent)
			return MSDC_CARD_NOT_PRESENT;
		if(!(_ocr&SDC_OCR_BUSY))		
		kal_sleep_task(10);

		// check card power up status bit
	}while(!(_ocr&SDC_OCR_BUSY) && (counter++ < TRY_OCR));

	if(timeout)
		return ERR_CMD_TIMEOUT;
	if(counter == TRY_OCR +1)
		return ERR_R3_OCR_BUSY;	
	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_uint8			counter, timeout;
	kal_uint32			_ocr = 0, ocr_i;

	counter = 0;
	ocr_i = SDC_OCR_QUERY;
	do{
		//dbg_print("OCR %d \r\n",counter);
		MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
		while((MSDC_IS_BUSY)
			&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
		MSDC_STOP_TIMER();		
		status=SD_Cmd55(SDC_RCA_DEFAULT);
		if(status != NO_ERROR)
		{
			SD_Reset();
			continue;
		}
		// send CMD41
		MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
		while((MSDC_IS_BUSY)
			&& MSDC_Check_Card_Present() && !gMSDC_Handle.is_timeout);
		MSDC_STOP_TIMER();
		MSDC_WriteReg32(SDC_ARG,ocr_i);
		MSDC_WriteReg32(SDC_CMD,SDC_CMD_CMD41_SD);
		// polling SDC_STA to make sure response is received or timeout
		if(SD_WaitCmdRdyOrTo() == ERR_CMD_TIMEOUT)
		{
			timeout = KAL_TRUE;
			continue;
		}		
		timeout = KAL_FALSE;
		MSDC_ReadReg32(SDC_RESP0, &_ocr);
		if((_ocr & SDC_OCR_DEFAULT) == 0)
			return ERR_OCR_NOT_SUPPORT;
		ocr_i = SDC_OCR_DEFAULT;
		if(!gMSDC_Handle.mIsPresent)
			return ERR_CARD_NOT_PRESENT;		
		//delay for card busy 
		if(!(_ocr&SDC_OCR_BUSY))		
		{
			if(kal_query_systemInit()==KAL_TRUE)
				GPTI_BusyWait(10);
			else
				kal_sleep_task(10);
		}
	}while(!(_ocr&SDC_OCR_BUSY) && (counter++ < TRY_OCR));

	if(timeout)
		return ERR_CMD_TIMEOUT;

	if(counter == TRY_OCR +1)
		return ERR_R3_OCR_BUSY;

	gMSDC_Handle.mMSDC_type = SD_CARD;
	gSD.mInactive = KAL_FALSE;
	gSD.mSDC_ocr = _ocr;
	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(gMSDC_Handle.mMSDC_type == SD_CARD)
	{
		//read RCA form card
		if((status = SD_Send_Cmd(SDC_CMD_CMD3_SD,SDC_NO_ARG))!=NO_ERROR)
			return status;
		//read R6
		MSDC_ReadReg32(SDC_RESP0, &resp);
		*pRca = resp >>  16;
		gSD.mRCA =*pRca;
		
	}
	else if(gMSDC_Handle.mMSDC_type == MMC_CARD)// MMC card Cmd3
	{
		//assign RCA to card
		if((status = SD_Send_Cmd(SDC_CMD_CMD3_MMC,(kal_uint32)SDC_RCA_MMC<<16))!=NO_ERROR)
			return status;

		//read R1
		MSDC_ReadReg32(SDC_RESP0, &resp);
		SD_GetStatus(SDC_RCA_MMC,&resp);
		state = 0;
		GetBitFieldN((kal_uint8*)&state,(kal_uint8*)&resp,9,4);
		if(STBY_STA != state)
			return ERR_RCA_FAIL;		
		*pRca = gSD.mRCA = SDC_RCA_MMC;			
	}
	else
		return ERR_INVALID_CARD;

	gSD.mState = STBY_STA;
	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_SetDSR
*
* DESCRIPTION
*	set default value to the DSR
*
* PARAMETERS
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	SDC_DSR_DEFAULT(0x404)
*
*************************************************************************/
SDC_CMD_STATUS SD_SetDSR(void)
{
	return SD_Send_Cmd(SDC_CMD_CMD4,(kal_uint32)SDC_DSR_DEFAULT<<16);
}

/*************************************************************************
* FUNCTION
*  SD_SelectCard
*
* DESCRIPTION
*	select/deselect card
*
* PARAMETERS
*	rca: relative card address
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SelectCard(kal_uint16 rca)
{
	SDC_CMD_STATUS status;

	if((status = SD_Send_Cmd(SDC_CMD_CMD7,(kal_uint32)rca<<16))!=NO_ERROR)
		return status;
		
	//read R1b
	if((status = SD_WaitCardNotBusy())!=NO_ERROR)	
		return status;
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_GetCSD
*
* DESCRIPTION
*	Get CSD from addressed card
*
* PARAMETERS
*	rca: relative card address
*	Csd: used for containing read CSD
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_GetCSD(kal_uint16 rca, kal_uint32 Csd[4])
{
	SDC_CMD_STATUS status;
	kal_uint32 i;

	if((status = SD_Send_Cmd(SDC_CMD_CMD9,(kal_uint32)rca<<16))!=NO_ERROR)
		return status;
	// read R2
	for(i=0;i<4;i++)
		MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Csd[i]);
	// analysis CSD...
	SD_AnalysisCSD(Csd);

	return NO_ERROR;
}

// addressed send CID
SDC_CMD_STATUS SD_GetAddressedCID(kal_uint16 rca, kal_uint32 Cid[4])
{
	SDC_CMD_STATUS status;
	kal_uint32 i;

	if((status = SD_Send_Cmd(SDC_CMD_CMD10,(kal_uint32)rca<<16))!=NO_ERROR)
		return status;

	// read R2
	for(i=0;i<4;i++)
		MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Cid[i]);

	return NO_ERROR;
}


/*************************************************************************
* FUNCTION
*  SD_StopTrans
*
* DESCRIPTION
*	Stop Muli-Block operation
*
* PARAMETERS
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*	definition of SD_STOP_SLOW is used for some erroneous card
*************************************************************************/
SDC_CMD_STATUS SD_StopTrans(kal_bool isTx)
{
	SDC_CMD_STATUS status;
	
	if((status = SD_Send_Cmd(SDC_CMD_CMD12,SDC_NO_ARG))!=NO_ERROR)
		return status;

	if(isTx)
		SD_WaitCardNotBusy();
	

#ifdef SD_STOP_SLOW 	
		while(*(volatile kal_uint16*)(SDC_STA) & SDC_STA_R1BSY);
		do{	
		SD_GetStatus(gSD.mRCA,(kal_uint32*)&status);
			}while((status & R1_CUR_STATE) >> 9 !=  TRAN_STA);
#endif

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_GetStatus
*
* DESCRIPTION
*	addressed send status
*
* PARAMETERS
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_GetStatus(kal_uint16 rca, kal_uint32* resp)
{
	SDC_CMD_STATUS status;

	if((status = SD_Send_Cmd(SDC_CMD_CMD13,(kal_uint32)rca <<16))!=NO_ERROR)
		return status;

	MSDC_ReadReg32(SDC_RESP0,resp);

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*  SD_SetBlength
*
* DESCRIPTION
*	set block length
*
* PARAMETERS
*	BKLength: block length u want to set
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*	gSD.mBKLength
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SetBlength(kal_uint32 BKLength)
{
	SDC_CMD_STATUS status;

	// maximal value of block length is 2048
	if(BKLength > SDC_MAX_BKLENGTH)
		return ERR_INVALID_BKLENGTH;
	if(!gSD.mCSD.r_blk_part && BKLength < gSD.mCSD.max_r_blk_len )
		return ERR_INVALID_BKLENGTH;		
	if((status = SD_Send_Cmd(SDC_CMD_CMD16,BKLength))!=NO_ERROR)
		return status;
	//read R1
	status = SD_CheckStatus();		
	// 2. configure the controller
	gSD.mBKLength = BKLength;
	BitFieldWrite32((kal_uint32*)SDC_CFG,BKLength,SDC_CFG_BLKLEN);

	return NO_ERROR;
}


/*************************************************************************
* FUNCTION
*  SD_ReadSingleBlock
*
* DESCRIPTION
*	1. read a single block form data_adrs of card to the rxbuffer
*	2. the block length is set by set block length
*
* PARAMETERS
*	data_adrs: starting address to read
*	rxbuffer: as name
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	the size of rxbuffer should be 4*n (n : integer)
*
*************************************************************************/
SDC_CMD_STATUS SD_ReadSingleBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer)
{
	kal_uint32 count;
	SDC_CMD_STATUS status;

	
	EnableMSDC_DMA();
	count = MSDC_SD_BLOCK_SIZE;
	MSDC_DMATransferFirst((kal_uint32)rxbuffer,count,KAL_FALSE);
	if((status = SD_Send_Cmd(SDC_CMD_CMD17,data_adrs))!=NO_ERROR)	
		goto ERR_Exit;
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto ERR_Exit;
	status = MSDC_DMATransferFinal();
	if(status != NO_ERROR)
	{
		goto ERR_Exit;			
	}		
	if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
		goto ERR_Exit;
	
	DisableMSDC_DMA();
	MSDC_CLR_FIFO();

⌨️ 快捷键说明

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