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

📄 msdc.c

📁 一个复杂控制SD卡的例子,可以参考应用到手机上.
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef DRV_LSD	
	#if defined(__MSDC_NOT_SUPPORT_HOT_PLUG__)
	gMSDC_Handle->mIsPresent = KAL_TRUE; 
	#else
	// enable card detection
	*(volatile kal_uint32*)MSDC_PS = MSDC_PS_CDEN|MSDC_PS_PIEN0|MSDC_PS_POEN0;		
	if(*(volatile kal_uint16*)MSDC_PS & MSDC_PS_PIN0)
	{
		if(gMSDC_Handle->ins_level == MSDC_IOCTRL_PULL_UP)
			gMSDC_Handle->mIsPresent = KAL_FALSE;	
		else
			gMSDC_Handle->mIsPresent = KAL_TRUE;	
	}
	else
	{
		if(gMSDC_Handle->ins_level == MSDC_IOCTRL_PULL_UP)
			gMSDC_Handle->mIsPresent = KAL_TRUE;
		else
			gMSDC_Handle->mIsPresent = KAL_FALSE;	
	}
	#endif //__MSDC_NOT_SUPPORT_HOT_PLUG__
#else
	gMSDC_Handle->mIsPresent = KAL_TRUE;
#endif
	
	#if defined(__SIM_PLUS__)
	/*bewlow comes after JRD SIM+ issue on 2007_03_08, give power, this should be temperary solution for jrd*/
	if(MSDC_NO_EXT_LDO != GPIO_EXT_SD_LDO_SWITCH){
		if(KAL_TRUE == gMSDC_Handle->mIsPresent)
			GPIO_WriteIO(1, GPIO_EXT_SD_LDO_SWITCH);
		else if(KAL_FALSE == gMSDC_Handle->mIsPresent)
			GPIO_WriteIO(0, GPIO_EXT_SD_LDO_SWITCH);
	}
	/*end of changes of JRD SIM+ issue on 2007_03_08*/
	#endif
	
	#if !defined(__MSDC_NOT_SUPPORT_HOT_PLUG__) && !defined(USE_INT26_CARD_DETECTION)
	MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_PINEN);	
	#endif
			
	#ifdef MSDC_INT
	MSDC_INT_Init();	
	#endif	// end of MSDC_INT
	#ifdef MSDC_DMA
	MSDC_DMAInit();
	#endif	
	#ifdef __MULTI_BOOT__
	if(stack_query_boot_mode() != NORMAL_BOOT)
		send_ilm = KAL_FALSE;
	else
		send_ilm = KAL_TRUE;
	#else
		send_ilm = KAL_FALSE;
	#endif
		
#ifndef DRV_LSD
#ifndef __SDC_SPI_INTERFACE__
	DRVPDN_Enable(DRVPDN_CON1,DRVPDN_CON1_MSDC,PDN_MSDC);	
#else
       //DRVPDN_Enable(DRVPDN_CON1,DRVPDN_CON1_UART3,PDN_UART3);
#endif
#else
	LSD_PDNControl(KAL_TRUE);
#endif
}

#ifdef  __TST_WRITE_TO_FILE_ONLY__
/*error recording: add this function to do MSDC reset when error recording*/
void MSDC_ErrorRecordingReset(){
	MSDC_ErrorRecordingBlk.gpt_handle = gMSDC_Handle->gpt_handle;
	gMSDC_Handle = &MSDC_ErrorRecordingBlk;
	MSDC_Initialize();
}
#endif

#ifndef DRV_LSD
/*************************************************************************
* FUNCTION
*  BitFieldWrite32
*
* DESCRIPTION
*	Write src to dest at mask position
*
* PARAMETERS
*	dest: destination to be update
*	src: value to be written
*	mask: bit mask
* RETURNS
*
* GLOBALS AFFECTED
*	
*
*************************************************************************/
// Note: mask must be a continuous area during 32bits. eg,
// dest : 00A30000 , src : BF, mask : 0000BF00.
// after BitFieldCpy, dest : 00A3BF00, copy src to dest at mask position.
void BitFieldWrite32(kal_uint32 * dest, kal_uint32 src, kal_uint32 mask)
{
	kal_uint8 bit_pos;
	kal_uint32 tmp;
	
	bit_pos = 0;
	tmp = *(kal_uint32 *)dest;
	// get bit positoin
	while(!((mask >> bit_pos++) & 1));	
	//use mask clear the corresponding area	
	tmp &= ~mask;
	//shift src to the corresponding positiion
	src <<= (bit_pos - 1);
	//copy src into destination	
	tmp |= src;
	*(kal_uint32 *)dest = tmp;	
}
#endif
/*************************************************************************
* FUNCTION
*  BitFieldRead32
*
* DESCRIPTION
*	read src to dest at mask position
*
* PARAMETERS
*	dest: destination to store
*	src: value to be written
*	mask: bit mask
* RETURNS
*
* GLOBALS AFFECTED
*	
*
*************************************************************************/

// Note: mask must ve continuous area during 32 bits.eg, 
// src : 00A3BF00, mask : 00FF0000
// after BitFieldRead, dest : A3
void BitFieldRead32(kal_uint32 * dest, kal_uint32 src, kal_uint32 mask)
{
	kal_uint8 bit_pos = 0;
	
	while(!((mask >> bit_pos++) & 1));
	src &= mask;
	*(kal_uint32 *)dest = src >> (bit_pos - 1);
}
// get the bit field value of start_bit with width bits
// note 1) start_bit start from bit 0
//		2) prepare dest with initialized with zeros
//		3) width must less than 32 if using the retrun value as a result
// eg,
// src:00110110, start_bit:2,width:3 => dest:101 
kal_uint32 GetBitFieldN(kal_uint8* dest, kal_uint8* src, kal_uint16 start_bit, kal_uint16 width)
{
	int i;
	kal_uint16 bytes, bits;

	kal_mem_set(dest,0,width/8+1);
	for( i = 0; i < width; i++)
	{	
		bytes = (start_bit+i)/8;
		bits  = (start_bit+i)%8;		
		*(dest+i/8) |= (kal_uint8)(((*(src+bytes) >> bits) & 1) << (i%8));		
	}
	return *(kal_uint32*)dest;
}

void MSDC_SetIOCONRegDLT(void)
{
	kal_uint32 factor;
	/*set DLT field according to SCLKF seeting*/
	factor = gMSDC_Handle->msdc_clock/gMSDC_Handle->op_clock;
#if defined(DRV_MSDC_MT6225_SERIES)
	BitFieldWrite32((kal_uint32*)MSDC_IOCON,(kal_uint32)(factor/2),MSDC_IOCON_DLT);
#endif
}

#ifdef MSDC_DMA 
extern kal_uint8 DMA_GetChannel(DMA_Master DMA_CODE);
/*************************************************************************
* FUNCTION
*  MSDC_DMAInit
*
* DESCRIPTION
*	Initialize MSDC's DMA
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*	
*
*************************************************************************/
void MSDC_DMAInit(void)
{
#ifdef  __TST_WRITE_TO_FILE_ONLY__
	/*error recording: it mens this functions is called twice, just return*/
	if(KAL_TRUE == INT_QueryExceptionStatus())
   		return;
#endif	
	msdc_dmaport = DMA_GetChannel(DMA_MSDC);
	msdc_menu.TMOD.burst_mode = KAL_TRUE;
	msdc_menu.TMOD.cycle = 0x4;
	msdc_menu.master = DMA_MSDC;
	msdc_menu.addr = NULL;

	msdc_input.type = DMA_HWRX;
	msdc_input.size = DMA_LONG;
	msdc_input.count = 0;
	msdc_input.menu = &msdc_menu;
	//msdc_input.callback = MSDC_DMA_Callback;	
}
/*************************************************************************
* FUNCTION
*  MSDC_DMATransfer
*
* DESCRIPTION
*	MSDC using DAM for data transfer 
*
* PARAMETERS
*	adrs: data buffer
*	count: bytes to be transfered
*	isTx: ture for move data from MSDC to data buffer and vise versa
*
* RETURNS
*
* GLOBALS AFFECTED
*	
*
*************************************************************************/
void MSDC_DMATransferFirst(kal_uint32 adrs,kal_uint32 count, kal_bool isTx)
{
#ifndef DRV_LSD
	kal_uint32 total_count;
	kal_bool is_aligned, is_poll;

	DMA_Stop(msdc_dmaport);	
	msdc_menu.addr = adrs;
	
	
	if(isTx)
	{
		gMSDC_Handle->timeout_period = (50 + (count>>5));
		msdc_input.type = DMA_HWTX;		
		if(count <= MSDC_WRITE_THD_POLL)
		//if(0)
		{
			msdc_input.callback = NULL;
			is_poll = KAL_TRUE;			
		}
		else
		{
			msdc_input.callback = MSDC_DMA_Callback;
			is_poll = KAL_FALSE;
		}
	}
	else
	{
	    gMSDC_Handle->timeout_period = (50 + (count>>7));
		msdc_input.type = DMA_HWRX;	
		if(count <= MSDC_READ_THD_POLL)
		//if(0)
		{
			msdc_input.callback = NULL;
			is_poll = KAL_TRUE;
		}
		else
		{
			msdc_input.callback = MSDC_DMA_Callback;
			is_poll = KAL_FALSE;
		}
	}

	if(kal_query_systemInit() == KAL_TRUE 
#ifdef  __TST_WRITE_TO_FILE_ONLY__	/*error recording: considering error recording additionally*/
		|| (KAL_TRUE == INT_QueryExceptionStatus())
#endif
	)
	{
		msdc_input.callback = NULL;
		is_poll = KAL_TRUE;
	}	
	if(adrs%4 == 0)
	{
		is_aligned = KAL_TRUE;
		total_count = count;
	}
	else
	{
		is_aligned = KAL_FALSE;
		total_count = count<<2;
	}
	gMSDC_Handle->total_count = total_count;
	gMSDC_Handle->is_poll = is_poll;
	gMSDC_Handle->is_aligned = is_aligned;
	{
		if(is_aligned)
		{
			#if defined(USE_DMA_BURST)
			MSDC_SET_FIFO(4);
			#else
			msdc_menu.TMOD.burst_mode = KAL_FALSE;
			#endif
			
			msdc_input.count = (total_count > 65024)?(65024):(total_count);
			msdc_input.size = DMA_LONG;		
			DMA_Config_B2W(msdc_dmaport,&msdc_input,KAL_TRUE,KAL_FALSE);
			msdc_menu.addr += msdc_input.count*4;
		}
		else
		{
			#if defined(USE_DMA_BURST)
			MSDC_SET_FIFO(1);
			#else
			
			msdc_menu.TMOD.burst_mode = KAL_TRUE;
			#endif
			msdc_input.count = (total_count > 65024)?(65024):(total_count);
			msdc_input.size = DMA_BYTE;
			DMA_Config_B2W(msdc_dmaport,&msdc_input,KAL_TRUE,KAL_TRUE);
			msdc_menu.addr += msdc_input.count;
		}
		
	}
#endif
}
kal_uint32 MSDC_DMATransferFinal(void)
{
#ifndef DRV_LSD
	kal_uint32 total_count = gMSDC_Handle->total_count, t1;
	kal_bool is_poll = gMSDC_Handle->is_poll;
	kal_bool is_aligned = gMSDC_Handle->is_aligned;

	t1 = drv_get_current_time();
	if(gMSDC_Handle->timeout_period > MSDC_TIMEOUT_PERIOD_DAT)
		gMSDC_Handle->timeout_period = MSDC_TIMEOUT_PERIOD_DAT;
	MSDC_START_TIMER(gMSDC_Handle->timeout_period);
	if(is_poll)
	{
		while(IS_MSDC_DMA_RUN && MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
		{
			if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
				gMSDC_Handle->is_timeout = KAL_TRUE;
		}
	}
	else
	{
		kal_uint32 flags;
		kal_retrieve_eg_events(MSDC_Events,(EVENT_DMAIRQ),KAL_OR_CONSUME,&flags,KAL_SUSPEND);				
	}				
	MSDC_STOP_TIMER();
	if(IS_MSDC_DMA_RUN && gMSDC_Handle->is_timeout)
		return MSDC_GPT_TIMEOUT_ERR;
	
	total_count -= msdc_input.count;
	if(total_count == 0)
		return MSDC_NOERROR;
	
	while(1)
	{
		if(is_aligned)
		{
			#if defined(USE_DMA_BURST)
			MSDC_SET_FIFO(4);
			#else
			msdc_menu.TMOD.burst_mode = KAL_FALSE;
			#endif
			
			msdc_input.count = (total_count > 65024)?(65024):(total_count);
			msdc_input.size = DMA_LONG;		
			DMA_Config_B2W(msdc_dmaport,&msdc_input,KAL_TRUE,KAL_FALSE);
			msdc_menu.addr += msdc_input.count*4;
			gMSDC_Handle->timeout_period = 1 + (msdc_input.count>>7);
		}
		else
		{
			#if defined(USE_DMA_BURST)
			MSDC_SET_FIFO(1);
			#else
			msdc_menu.TMOD.burst_mode = KAL_TRUE;
			#endif
			msdc_input.count = (total_count > 65024)?(65024):(total_count);
			msdc_input.size = DMA_BYTE;
			DMA_Config_B2W(msdc_dmaport,&msdc_input,KAL_TRUE,KAL_TRUE);
			msdc_menu.addr += msdc_input.count;
			gMSDC_Handle->timeout_period = 1 + (msdc_input.count>>9);
		}
		
		// wait until running bit clr
		if(msdc_input.type == DMA_HWTX)
			gMSDC_Handle->timeout_period <<= 2 ;
		if(gMSDC_Handle->mMSDC_type == MMC_CARD)
			gMSDC_Handle->timeout_period <<= 1;
		
		t1 = drv_get_current_time();
		MSDC_START_TIMER(gMSDC_Handle->timeout_period);
		if(is_poll)
		{
			while(IS_MSDC_DMA_RUN && MSDC_Check_Card_Present() && !gMSDC_Handle->is_timeout)
			{
				if(drv_get_duration_ms(t1) > gMSDC_Handle->timeout_period*11)
					gMSDC_Handle->is_timeout = KAL_TRUE;				
			}
		}
		else
		{
			kal_uint32 flags;
			kal_retrieve_eg_events(MSDC_Events,(EVENT_DMAIRQ),KAL_OR_CONSUME,&flags,KAL_SUSPEND);				
		}				
		MSDC_STOP_TIMER();
		if(IS_MSDC_DMA_RUN && gMSDC_Handle->is_timeout)
			return MSDC_GPT_TIMEOUT_ERR;
		total_count -= msdc_input.count;
		if(total_count == 0)
			break;		
	}
	
	return MSDC_NOERROR;
#else
	return MSDC_NOERROR;
#endif
}

#endif // DMA

#ifdef MSDC_INT

#ifdef USE_INT26_CARD_DETECTION
void MSDC_CardDetect_LISR(void)
{
	IRQMask(IRQ_MSDC_CD_CODE);
	gMSDC_Handle->mIsChanged = KAL_TRUE;
	drv_active_hisr(DRV_MSDC_HISR_ID);
}
#endif //USE_INT26_CARD_DETECTION


#ifdef DRV_LSD
kal_uint32 MSDC_CARD_INSERT_COUNTER, MSDC_CARD_REMOVE_COUNTER;

void MSDC_LSD_HISR(void)
{
	static kal_bool pre_IsPresent = KAL_TRUE; // it works only at first time

	if(pre_IsPresent)
			pre_IsPresent = gMSDC_Handle->mIsPresent;

	if(LSD_cardInsertion == LSD_cardDetection())
	{
		gMSDC_Handle->mIsPresent = KAL_TRUE;	
		MSDC_CARD_INSERT_COUNTER ++;
	}
	else if(LSD_cardRemoval == LSD_cardDetection())
	{
		gMSDC_Handle->mIsPresent = KAL_FALSE;
		MSDC_CARD_REMOVE_COUNTER++;
	}
	else
		ASSERT(0);

	// if the card is present during power on, then the 
	// card detection interrup of INT26 will always generated. This interrupt should be ignored.		
	if(pre_IsPresent && gMSDC_Handle->mIsPresent && gMSDC_Handle->mIsInitialized )
	{			
		pre_IsPresent = KAL_FALSE;
		gMSDC_Handle->mIsInitialized = KAL_TRUE;		
		return;			
	}
	else
		gMSDC_Handle->mIsInitialized = KAL_FALSE;

	if(gMSDC_Handle->mIsPresent == KAL_FALSE)
	{

⌨️ 快捷键说明

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