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

📄 sd.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:
	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();
	
	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, 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)	
	
	// 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++;
		}
	}
	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
*

⌨️ 快捷键说明

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