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

📄 sd.c

📁 SDIO实现底层驱动文件.非常有用.经典!
💻 C
📖 第 1 页 / 共 5 页
字号:
	
	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);	
	if((status = SD_Send_Cmd(SDC_CMD_CMD18,data_adrs))!=NO_ERROR)
		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;
	
	if(gSD.mWPEnabled)
		return ERR_WRITE_PROTECT;
	EnableMSDC_DMA();
	count = MSDC_SD_BLOCK_SIZE;	
	MSDC_DMATransferFirst((kal_uint32)txbuffer,count,KAL_TRUE);	
	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;
	
	if(gSD.mWPEnabled)
		return ERR_WRITE_PROTECT;
	EnableMSDC_DMA();	
	count = MSDC_SD_BLOCK_SIZE;	
	MSDC_DMATransferFirst((kal_uint32)txbuffer,count,KAL_TRUE);	
	if((status = SD_Send_Cmd(SDC_CMD_CMD25,address))!=NO_ERROR)
		goto ERR_Exit;
	// read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		goto ERR_Exit;
	
   
#if 0	
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#else
{
	kal_uint32 j;
	
	for(j=0;j<num;j++)
	{
		if(gMSDC_Handle.mIsInitialized == KAL_FALSE)
		{
			status = ERR_CARD_NOT_PRESENT;
			goto ERR_Exit;		
		}
		if(j!=0)			
			MSDC_DMATransferFirst((kal_uint32)txbuffer,count,KAL_TRUE);			
		status = MSDC_DMATransferFinal();
		if(status != NO_ERROR)
			goto ERR_Exit;		
		txbuffer += count;
		if((status = SD_WaitDatRdyOrTo())!=NO_ERROR)	
			goto ERR_Exit;
	}
}
#endif

	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;

	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)	
	
	// failed to use DMA with burst mode
	MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
	for(i=0;i<2;)
	{	
		if(!gMSDC_Handle.mIsPresent)
			return ERR_CARD_NOT_PRESENT;
		if(gMSDC_Handle.is_timeout)
			break;
		if(!MSDC_IS_FIFO_EMPTY)
		{
			*(kal_uint32*)(scr+i) = *(volatile kal_uint32*)MSDC_DAT;
			i++;
		}
	}
	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

	// restore block length
	if((status = SD_SetBlength(blklen))!=NO_ERROR)
		return status;

	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;
	//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);		
	if((status = SD_Send_Cmd(SDC_CMD_CMD8_MMC40,SDC_NO_ARG))!=NO_ERROR)
		return status;
	//read R1
	if((status = SD_CheckStatus())!=NO_ERROR)
		return status;		
	// read the block	of 512 bytes (make sure the rxbuffer is 4 byte aligned)
	EnableMSDC_DMA();
	status = MSDC_DMATransferFinal();	
	if(status != NO_ERROR)
		goto ERR_Exit;			

⌨️ 快捷键说明

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