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

📄 sd.c

📁 一个复杂控制SD卡的例子,可以参考应用到手机上.
💻 C
📖 第 1 页 / 共 5 页
字号:
	if(gSD->flags & SD_FLAG_SD_TYPE_CARD )
	#else
	if(gMSDC_Handle->mMSDC_type == SD_CARD)
	#endif
	{
		//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
	{
		//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;			
	}

	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++)
	{
	#ifndef DRV_LSD
		MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Csd[i]);
	#else
		MSDC_ReadReg32(SDC_RESP0+i, &Csd[i]);
	#endif
	}
	// 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++)
	{
	#ifndef DRV_LSD
		MSDC_ReadReg32((volatile kal_uint32 *)(SDC_RESP0+i*4), &Cid[i]);
	#else
		MSDC_ReadReg32(SDC_RESP0+i, &Cid[i]);
	#endif
	}
	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;
	kal_uint32 retry = 0;

	while(retry < 30)
	{
		if((status = SD_Send_Cmd(SDC_CMD_CMD12,SDC_NO_ARG))!=NO_ERROR)
		{
			retry ++;
		}
		else
		{
			break;
		}
	}
	if(retry >= 30)
	{
		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);
	#ifdef DRV_LSD
	LSD_HostSetBuffer((kal_uint8 *)rxbuffer);
	#endif
	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();
	
	return NO_ERROR;
ERR_Exit:
	{
		kal_uint32 tmp;
		
		#ifdef MSDC_USE_INT
		kal_set_eg_events(MSDC_Events, 0, KAL_AND);
		#endif
		DisableMSDC_DMA();
		RESET_MSDC();

		// SD_StopTrans(KAL_FALSE);		
		SD_GetStatus(gSD->mRCA,(kal_uint32*)&tmp);
		MSDC_ReadReg32(SDC_DATSTA,&tmp);
		MSDC_CLR_FIFO();		
		return status;
	}
	
}

/*************************************************************************
* FUNCTION
*  SD_ReadMultiBlock
*
* DESCRIPTION
*	read num of blocks into rxbuffer
*
* PARAMETERS
*	data_adrs: starting address to read
*	rxbuffer: as name
*	num: number of blocks to read
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_ReadMultiBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer, kal_uint32 num)
{
	SDC_CMD_STATUS status;
	kal_uint32 j, count;
	#ifndef MSDC_DMA
	kal_uint32 i;	
	#endif

	EnableMSDC_DMA();
	count = MSDC_SD_BLOCK_SIZE;	
	MSDC_DMATransferFirst((kal_uint32)rxbuffer,count*num,KAL_FALSE);	
	#ifndef DRV_LSD
	if((status = SD_Send_Cmd(SDC_CMD_CMD18,data_adrs))!=NO_ERROR)
	#else
	LSD_HostSetBuffer((kal_uint8 *)rxbuffer);
	if((status = SD_Send_Cmd(SDC_CMD_CMD18|(num<<20) ,data_adrs))!=NO_ERROR)
	#endif
		goto ERR_Exit;
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto ERR_Exit;	
	count = MSDC_SD_BLOCK_SIZE;	
	status = MSDC_DMATransferFinal();
	if(status != NO_ERROR)
			goto ERR_Exit;	

	if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
		goto ERR_Exit;
	
	
	MSDC_CLR_INT();
	DisableMSDC_DMA();

	if(gSD->flags & SD_FLAG_MMC_MRSW_FAIL)
	{
		kal_uint32 delay = 200;
		while(delay--);		
	}
	if((status = SD_StopTrans(KAL_FALSE))!=NO_ERROR)
	{
		//if((data_adrs/gSD->mBKLength + j) < gSD->mBKNum)			
			goto ERR_Exit;		
	}
	MSDC_CLR_FIFO();			
	return NO_ERROR;
	
ERR_Exit:

	#ifdef MSDC_USE_INT	
	kal_set_eg_events(MSDC_Events, 0, KAL_AND);
	#endif
	DisableMSDC_DMA();
	RESET_MSDC();		
	SD_StopTrans(KAL_FALSE);		
	SD_GetStatus(gSD->mRCA,(kal_uint32*)&j);
	MSDC_ReadReg32(SDC_DATSTA,&j);
	MSDC_CLR_FIFO();
	return status;
	
}

/*************************************************************************
* FUNCTION
*  SD_WriteSingleBlock
*
* DESCRIPTION
*	write a single block
*
* PARAMETERS
*	address: starting address to write
*	txbuffer: as name
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	block length is set by Set_Block_Length
*
*************************************************************************/
SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
{
	SDC_CMD_STATUS status;
	kal_uint32 count;
	kal_uint32 *ptr;	
#if defined(MT6225)
	kal_bool is_aligned;
	ECO_VERSION eco;
	eco = INT_ecoVersion();	
#endif

	if(gSD->mWPEnabled)
		return ERR_WRITE_PROTECT;
	EnableMSDC_DMA();
	count = MSDC_SD_BLOCK_SIZE;
	
	#if defined(MT6225)
	if(eco <= ECO_E3)
	{
		is_aligned = ((kal_uint32)txbuffer%4 == 0); 
		if(is_aligned)
		{
			ptr = txbuffer;
		}
		else
		{
			kal_mem_cpy(MSDC_Sector, txbuffer, 512);
			ptr = MSDC_Sector;
		}
	}
	else
	{
		ptr = txbuffer;
	}
	#else
	ptr = txbuffer;
	#endif
	
	EnableMSDC_DMA();
	count = MSDC_SD_BLOCK_SIZE;	
	MSDC_DMATransferFirst((kal_uint32)ptr,count,KAL_TRUE);	
	#ifdef DRV_LSD
	LSD_HostSetBuffer((kal_uint8 *)txbuffer);
	#endif
	if((status = SD_Send_Cmd(SDC_CMD_CMD24,address))!=NO_ERROR)
		goto ERR_Exit;
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto ERR_Exit;
	status = MSDC_DMATransferFinal();
	if(status != NO_ERROR)
		goto ERR_Exit;	
	// wait R1b interrupt because cmd24 is configured as R1b response but cmd25 needn't
	if((status = SD_WaitCardNotBusy())!=NO_ERROR)	
		 goto ERR_Exit;	
	DisableMSDC_DMA();
	if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
		goto ERR_Exit;
	

	return NO_ERROR;
ERR_Exit:
	{
		kal_uint32 tmp;
		
		#ifdef MSDC_USE_INT	
		kal_set_eg_events(MSDC_Events, 0, KAL_AND);
		#endif
		DisableMSDC_DMA();
		RESET_MSDC();
		//SD_StopTrans(KAL_TRUE);		
		SD_GetStatus(gSD->mRCA,(kal_uint32*)&tmp);
		MSDC_ReadReg32(SDC_DATSTA,&tmp);
		return status;
	}
	
}

/*************************************************************************
* FUNCTION
*	SD_WriteMultiBlock
*
* DESCRIPTION
*	write num blocks starting at address
*
* PARAMETERS
*	address: starting address to write
*	txbuffer: as name
*	num: number of blocks to write
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	block length is set by Set_Block_Length
*
*************************************************************************/
SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num)
{
	SDC_CMD_STATUS status;
	kal_uint32 count;
	kal_uint32 *ptr;
	#if defined(MT6225)
	kal_bool is_aligned, dma_issue;
	ECO_VERSION eco;
	eco = INT_ecoVersion();	
	if(eco <= ECO_E3) 
		dma_issue = KAL_TRUE;
	#endif
		
	if(gSD->mWPEnabled)
		return ERR_WRITE_PROTECT;
	EnableMSDC_DMA();	
	count = MSDC_SD_BLOCK_SIZE;	
	#if defined(MT6225)
	if(dma_issue)
	{
		is_aligned = ((kal_uint32)txbuffer%4 == 0); 
		if(is_aligned)
		{
			MSDC_DMATransferFirst((kal_uint32)txbuffer,count*num,KAL_TRUE);	
		}
		else

⌨️ 快捷键说明

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