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

📄 sd.c

📁 一个复杂控制SD卡的例子,可以参考应用到手机上.
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
			kal_mem_cpy(MSDC_Sector, txbuffer, 512);
			ptr = txbuffer;
			MSDC_DMATransferFirst((kal_uint32)MSDC_Sector,count,KAL_TRUE);
		}
	}
	else
	{
		MSDC_DMATransferFirst((kal_uint32)txbuffer,count*num,KAL_TRUE);	
	}
	#elif defined(MSDC_MULTI_BLOCK_WRITE)
	MSDC_DMATransferFirst((kal_uint32)txbuffer,count*num,KAL_TRUE);
	#else
	ptr = txbuffer;
	MSDC_DMATransferFirst((kal_uint32)ptr,count,KAL_TRUE);
	#endif
#ifndef DRV_LSD
	if((status = SD_Send_Cmd(SDC_CMD_CMD25,address))!=NO_ERROR)
#else
	LSD_HostSetBuffer((kal_uint8 *)txbuffer);
	if((status = SD_Send_Cmd(SDC_CMD_CMD25|(num<<20) ,address))!=NO_ERROR)
#endif
		goto ERR_Exit;
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto ERR_Exit;
	   
	#if defined(MT6225)
	if(dma_issue)
	{
		if(is_aligned)
		{
			status = MSDC_DMATransferFinal();
			if(status != NO_ERROR)
				goto ERR_Exit;
			if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
				goto ERR_Exit;		
		}
		else
		{
			kal_uint32 j;
			
			for(j=0;j<num;j++)
			{
				if(gMSDC_Handle->mIsPresent  == KAL_FALSE)
				{
					status = ERR_CARD_NOT_PRESENT;
					goto ERR_Exit;		
				}
				if(j!=0)
				{
					kal_mem_cpy(MSDC_Sector, ptr, 512);
					MSDC_DMATransferFirst((kal_uint32)MSDC_Sector,count,KAL_TRUE);
				}
				status = MSDC_DMATransferFinal();
				ptr += MSDC_SD_BLOCK_SIZE; 
				if(status != NO_ERROR)
					goto ERR_Exit;		
				if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)	
					goto ERR_Exit;
			}	
		}	
	}
	else
	{
		status = MSDC_DMATransferFinal();
		if(status != NO_ERROR)
			goto ERR_Exit;
		if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
			goto ERR_Exit;		
	}
	#elif defined(MSDC_MULTI_BLOCK_WRITE)
		status = MSDC_DMATransferFinal();
		if(status != NO_ERROR)
			goto ERR_Exit;
		if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
			goto ERR_Exit;			
	#else // not MT6225
	{
		kal_uint32 j;
		
		for(j=0;j<num;j++)
		{
			if(gMSDC_Handle->mIsPresent  == KAL_FALSE)
			{
				status = ERR_CARD_NOT_PRESENT;
				goto ERR_Exit;		
			}
			if(j!=0)
			{
				MSDC_DMATransferFirst((kal_uint32)ptr,count,KAL_TRUE);
			}
			status = MSDC_DMATransferFinal();
			ptr += MSDC_SD_BLOCK_SIZE; 
			if(status != NO_ERROR)
				goto ERR_Exit;		
			if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)	
				goto ERR_Exit;
		}
	
	}	
	#endif // MT6225

	DisableMSDC_DMA();
	if((status = SD_StopTrans(KAL_TRUE))!=NO_ERROR)
		goto ERR_Exit;
	
	MSDC_CLR_INT();
	#ifdef MSDC_USE_INT	
	kal_set_eg_events(MSDC_Events, 0, KAL_AND);
	#endif
	
	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_SetBusWidth
*
* DESCRIPTION
*	ACMD6: set the data width 00 for 1 bit, 10 for 4 bits
*
* PARAMETERS
*	width: indicate the bus width
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	Not every card support 4-bits bus
*	only for SD
*
*************************************************************************/
SDC_CMD_STATUS SD_SetBusWidth(SD_BITWIDTH width)
{
	SDC_CMD_STATUS status;

	// check if card support 4 bits bus
	if((width == BIT_4W) && !(gSD->mSCR.bus_width&0x04))
		return ERR_NOT_SUPPORT_4BITS;
	// send APP_CMD
	if((status = SD_Cmd55(gSD->mRCA))!=NO_ERROR)
		return status;
	// send cmd6
	if((status = SD_Send_Cmd(SDC_CMD_ACMD6,width))!=NO_ERROR)
		return status;
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;	
	// set the controler MDLEN to enalbe 4bits bus width
	MSDC_SET_BIT32(SDC_CFG,SDC_CFG_MDLEN);
	gSD->bus_width = 4;
	
	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*	SD_ReadSCR
*
* DESCRIPTION
*	ACMD51: read the SD Configuration Register(8bytes block read)
*
* PARAMETERS
*	scr: used for store SCR
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	Make sure the size of SCR is 8 bytes 
*
*************************************************************************/
SDC_CMD_STATUS SD_ReadSCR(kal_uint32* scr)
{
	SDC_CMD_STATUS status;
	kal_uint32 blklen,i, t1;

	ASSERT((kal_uint32)scr % 4  == 0);
	// save the original block length 
	blklen = gSD->mBKLength;
	// set block length(MSDC_CFG)
	if((status = SD_SetBlength(8))!=NO_ERROR)
		return status;
	// send APP_CMD
	if((status = SD_Cmd55(gSD->mRCA))!=NO_ERROR)
		return status;
	// send command
	if((status = SD_Send_Cmd(SDC_CMD_ACMD51,SDC_NO_ARG))!=NO_ERROR)
		return status;
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;	
	// read data(8bytes)	
#ifndef DRV_LSD
	// failed to use DMA with burst mode
	t1 = drv_get_current_time();
	MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
	for(i=0;i<2;)
	{	
		if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
			gMSDC_Handle->is_timeout = KAL_TRUE;		
		if(!gMSDC_Handle->mIsPresent)
			return ERR_CARD_NOT_PRESENT;
		if(gMSDC_Handle->is_timeout)
			return MSDC_GPT_TIMEOUT_ERR;
		if(!MSDC_IS_FIFO_EMPTY)
		{
			*(kal_uint32*)(scr+i) = *(volatile kal_uint32*)MSDC_DAT;
			i++;
		}
	}
#else
	LSD_readFIFO(scr ,2);
	
#endif
	MSDC_STOP_TIMER();
	// analysis scr
	SD_AnalysisSCR(scr);
	// clean EVENT_SDDATIRQ
	#ifdef MSDC_USE_INT	
	kal_set_eg_events(MSDC_Events, 0, KAL_AND);
	#endif
	MSDC_CLR_FIFO();
	return NO_ERROR;
	
}

/*************************************************************************
* FUNCTION
*	SD_SetPreEraseBlk
*
* DESCRIPTION
*	ACMD23: set the number of write blocksto be pre-erased before writing
*	used for faster multiple Block Write
*
* PARAMETERS
*	num: used for storing number of blocks during multi-block operation
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SetPreEraseBlk(kal_uint32 num)
{
	SDC_CMD_STATUS status;

	//[22:0] number of blocks 
	num &= 0x003FFF;
	// send APP_CMD
	if((status = SD_Cmd55(gSD->mRCA))!=NO_ERROR)
		return status;
	// send CMD23
	if((status = SD_Send_Cmd(SDC_CMD_ACMD23,num))!=NO_ERROR)
		return status;
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;	

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*	SD_EraseCmdClass
*
* DESCRIPTION
*	groups of erase commands including CMD32 ~CMD38
*
* PARAMETERS
*	cmd: indicate which command to execute
*	address: starting address wiht write protection
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*	CMD34~CMD37 are only for MMC
*
*************************************************************************/
SDC_CMD_STATUS SD_EraseCmdClass(kal_uint32 cmd ,kal_uint32 address)
{
	SDC_CMD_STATUS status;

	if(cmd != SDC_CMD_CMD38)
	{
		if((status = SD_Send_Cmd(cmd,address))!=NO_ERROR)
			return status;
	}
	else if((status = SD_Send_Cmd(cmd,SDC_NO_ARG))!=NO_ERROR)
			return status;

	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;

	if(cmd == SDC_CMD_CMD38)
	{
		SD_WaitCardNotBusy();
		do{	
		SD_GetStatus(gSD->mRCA,(kal_uint32*)&status);
		if(gMSDC_Handle->mIsPresent == KAL_FALSE)
			break;
			}while(CurState(status)!=  TRAN_STA);
	}
	
	return NO_ERROR;
}
/*************************************************************************
* FUNCTION
*	SD_Switch_MMC40
*
* DESCRIPTION
*	CMD6: set the command set or write to the EXT_CSD (for MMC4.0)
*
* PARAMETERS
*	access: access mode
*	index: index to EXT_CSD
*  value: value to write to EXT_CSD
*	set:	selected command set 
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Switch_MMC40(kal_uint8 access, kal_uint8 index, kal_uint8 value, kal_uint8 set)
{
	SDC_CMD_STATUS status;
	kal_uint32 arg = 0;
	
	arg = (access<<24)|(index<<16)|(value<<8)|set;
	// send command
	if((status = SD_Send_Cmd(SDC_CMD_CMD6_MMC40,arg))!=NO_ERROR)
		return status;
#ifdef DRV_LSD
	//read R1b
	if((status = SD_WaitCardNotBusy())!=NO_ERROR)	
		return status;
#endif
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;

	return NO_ERROR;
}

/*************************************************************************
* FUNCTION
*	SD_SendEXTCSD_MMC40
*
* DESCRIPTION
*	CMD8: read the content of EXT_CSD register
*
* PARAMETERS
*	kal: access mode
*	index: index to EXT_CSD
*  value: value to write to EXT_CSD
*	set:	selected command set 
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SendEXTCSD_MMC40(kal_uint32* rxbuffer)
{
	SDC_CMD_STATUS status;
	kal_bool retry_4bit = KAL_FALSE;

start:
	// read the block	of 512 bytes (make sure the rxbuffer is 4 byte aligned)
	EnableMSDC_DMA();
	MSDC_DMATransferFirst((kal_uint32)rxbuffer,128,KAL_FALSE);		
#ifdef DRV_LSD
	LSD_HostSetBuffer((kal_uint8 *)rxbuffer);
#endif
	if((status = SD_Send_Cmd(SDC_CMD_CMD8_MMC40,SDC_NO_ARG))!=NO_ERROR)
		goto ERR_Exit;
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto ERR_Exit;		
	// read the block	of 512 bytes (make sure the rxbuffer is 4 byte aligned)
	status = MSDC_DMATransferFinal();	
	if(status != NO_ERROR)
		goto ERR_Exit;			
	if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)
		goto ERR_Exit;
	
	DisableMSDC_DMA();
	MSDC_CLR_FIFO();	
	gSD->mCSD.ext_csd = (T_EXT_CSD_MMC40 *)rxbuffer;
	return NO_ERROR;	
	
ERR_Exit:

	if(retry_4bit == KAL_FALSE)
	{
		retry_4bit = KAL_TRUE;
		MSDC_SET_BIT32(SDC_CFG,SDC_CFG_MDLEN);
		gSD->bus_width = 4;
		goto start;
	}
	MSDC_CLR_BIT32(SDC_CFG,SDC_CFG_MDLEN);
	gSD->bus_width = 1;
	DisableMSDC_DMA();
	MSDC_CLR_FIFO();	
	RESET_MSDC();

	return status;
}

/*************************************************************************
* FUNCTION
*	SD_Switch_SD11
*
* DESCRIPTION
*	CMD6: switch command to query and select the specific functions. (SD1.1 or later)
* PARAMETERS
*	arg: argument
*	resp: buffer to contain the ther 64 bytes status information
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_Switch_SD11(kal_uint32 arg, T_SWITCH_STATUS* info)
{
	SDC_CMD_STATUS status = NO_ERROR;
	
	BitFieldWrite32((kal_uint32*)SDC_CFG,SD_CMD6_RESP_LEN,SDC_CFG_BLKLEN);	
	EnableMSDC_DMA();
	MSDC_DMATransferFirst((kal_uint32)info,(SD_CMD6_RESP_LEN>>2),KAL_FALSE);	
	if((status = SD_Send_Cmd(SDC_CMD_CMD6_SD11,arg))!=NO_ERROR)
		goto exit;
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto exit;
	status = MSDC_DMATransferFinal();	
	
exit:	
	DisableMSDC_DMA();	
	return status;
}

/*************************************************************************
* FUNCTION
*	SD_Switch_SD11
*
* DESCRIPTION
*	Enable the high speed interface to support up to 50M Hz clock 
*
* PARAMETERS
*	arg: argument
*	resp: buffer to contain the ther 64 bytes status information
*
* RETURNS
*	SDC_CMD_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
SDC_CMD_STATUS SD_SelectHighSpeed_SD11(void)
{
	SDC_CMD_STATUS status;
	T_SWITCH_STATUS *p = (T_SWITCH_STATUS*)MSDC_Sector;
	
	if((status = SD_Switch_SD11(SD_CMD6_QUERY_HIGH_SPEED, p))!=NO_ERROR)
		return status;
	if(p->max_current == 0)
		return ERR_SD_HS_FAIL;
	if((p->group1_info & (1 << SD_FUNC_HIGH_SPEED)) && 
		(p->group1_result == SD_FUNC_HIGH_SPEED))
	{
		if((status = SD_Switch_SD11(SD_CMD6_SELECT_HIGH_SPEED, p))!=NO_ERROR)
				return status;
		if(p->max_current == 0)
			return ERR_SD_HS_FAIL;
		if(p->group1_result == SD_FUNC_HIGH_SPEED)
			gSD->flags |= SD_FLAG_HS_SUPPORT;
	}	
	else
		return ERR_SD_HS_FAIL;


	return NO_ERROR;
}

SDC_CMD_STATUS SD_GoInactive(kal_uint16 rca)
{
	SDC_CMD_STATUS status;

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

	return NO_ERROR;
}

SDC_CMD_STATUS SD_ReadStream_MMC(kal_uint32 address, kal_uint32* rxbuffer, kal_uint32 bytes)
{
	SDC_CMD_STATUS status;
	kal_uint32 i,count;

	MSDC_CLR_FIFO();
	count = (bytes%4)?(bytes/4+1):(bytes/4);
#ifdef MSDC_DMA
	EnableMSDC_DMA();
	MSDC_DMATransferFirst((kal_uint32)rxbuffer,count,KAL_FALSE);
#endif
	//launch stream read command
	if((status = SD_Send_Cmd(SDC_CMD_CMD11_MMC,address)) != NO_ERROR)
	{
		goto ERR_Exit;
	}
	//read R1
	if((status = SD_CheckStatus())!= NO_ERROR)
	{		
		SD_WaitDatRdyOrTo();
		goto ERR_Exit;
	}
	

#ifdef MSDC_DMA
	status = MSDC_DMATransferFinal();
	if(status != NO_ERROR)
	{
		goto ERR_Exit;			
	}		
#else		
	//size assumed to be multiple of 4
	for(

⌨️ 快捷键说明

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