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

📄 ms.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 4 页
字号:
*************************************************************************/
MS_STATUS MS_TPC_WritePage(kal_uint32 *txbuffer)
{
	MS_STATUS status;

	ASSERT((kal_uint32)txbuffer %4 == 0);
#ifdef MSDC_DMA
	EnableMSDC_DMA();
#if defined(MT6218)
	MSDC_DMATransferFirst((kal_uint32)txbuffer,MS_PAGE_SIZE/4,KAL_TRUE);
#else
	MSDC_DMATransferFirst((kal_uint32)txbuffer,MS_PAGE_SIZE/sizeof(kal_uint32),KAL_TRUE);
#endif
	MS_SendTPC(TPC_WRITE_PAGE_DATA,MS_PAGE_SIZE);
	// start DMA transfer
	#if defined(MT6218)
	status = MSDC_DMATransferFinal();
	#else
	status = MSDC_DMATransferFinal();
	#endif
	if(status != MS_NOERROR)
				goto ERR_Exit;				
#else	
{
	int i;

	MS_SendTPC(TPC_WRITE_PAGE_DATA,MS_PAGE_SIZE);
	// write data into fifo
	for(i=0;i<MS_PAGE_SIZE/sizeof(kal_uint32);)
	{
		if(!MSDC_IS_FIFO_FULL)
		{
			*(volatile kal_uint32*)MSDC_DAT = *(txbuffer+i);
			i++;
		}
	}
}
#endif
	DisableMSDC_DMA();
	if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
	{
		goto ERR_Exit;
	}	
	return MS_NOERROR;
	
ERR_Exit:
	#ifdef MSDC_USE_INT
	// reset the events
	kal_set_eg_events(MSDC_Events, 0, KAL_AND);
	#endif
	DisableMSDC_DMA();
	return status;	
}

/*************************************************************************
* FUNCTION
*  MS_TPC_ReadReg
*
* DESCRIPTION
*  1. TPC for reading registers which address is set by MS_TPC_SetRWAdrs 
*
* PARAMETERS
*	1. buffer: used for storing data read from registers
*	2. length: bytes of data to read
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
* 	buffer must be prepared up to multiple of 4 ,ex.
*  if length = 7 , u must prepare 8 bytes  = 2x4 bytes as buffer size
*
*************************************************************************/
MS_STATUS MS_TPC_ReadReg(kal_uint32 *buffer, kal_uint8 length)
{
	MS_STATUS status;
	kal_uint32 i,count;

	MS_SendTPC(TPC_READ_REG,length);
	// read data from fifo
	count = (length+sizeof(kal_uint32)-1)/sizeof(kal_uint32);
	for(i=0; i<count;)
	{
		if(!gMSDC_Handle.mIsPresent) 
			return MS_ERR_CARD_NOT_PRESENT;			
		if(!MSDC_IS_FIFO_EMPTY)
		{
			*(buffer+i) = *(volatile kal_uint32*)MSDC_DAT;
			i++;
		}
	}
	if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
		return status;

	return MS_NOERROR;	
}

/*************************************************************************
* FUNCTION
*  MS_TPC_WriteReg
*
* DESCRIPTION
*  1. TPC for writing registers which address is set by MS_TPC_SetRWAdrs 
*
* PARAMETERS
*	1. buffer: used for storing data written to registers
*	2. length: bytes of data to write
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
* 	buffer must be prepared up to multiple of 4 ,ex.
*  if length = 7 , u must prepare 8 bytes  = 2x4 bytes as buffer size
*
*************************************************************************/
//TPC for writing form the register which address was set.
MS_STATUS MS_TPC_WriteReg(kal_uint32 *buffer, kal_uint8 length)
{
	MS_STATUS status;
	kal_uint32 i,count;

	MS_SendTPC(TPC_WRITE_REG,length);
	count = (length+sizeof(kal_uint32)-1)/sizeof(kal_uint32);
	// write data into fifo
	for(i=0;i<count;)
	{
		if(!gMSDC_Handle.mIsPresent) 
			return MS_ERR_CARD_NOT_PRESENT;		
		if(!MSDC_IS_FIFO_FULL)
		{
			*(volatile kal_uint32*)MSDC_DAT = *(buffer+i);
			i++;
		}
	}
	if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
		return status;

	return MS_NOERROR;	
}

/*************************************************************************
* FUNCTION
*  MS_TPC_SetRWAdrs
*
* DESCRIPTION
*  TPC for setting values which determine the register accessed by WRITE_REG and READ_REG
*
* PARAMETERS
*	1. r_adrs: starting address for READ_REG
*	2. r_len: consecutive size for READ_REG
*	3. w_adrs: starting address for WRITE_REG
*	4. w_len: consecutive size for WRITE_REG
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
* 	buffer must be prepared up to multiple of 4 ,ex.
*  if length = 7 , u must prepare 8 bytes  = 2x4 bytes as buffer size
*
*************************************************************************/
MS_STATUS MS_TPC_SetRWAdrs(kal_uint8 r_adrs, kal_uint8 r_len, kal_uint8 w_adrs, kal_uint8 w_len)
{
	MS_STATUS status;
	kal_uint8 data[4];

	// send the TPC (4 bytes data)
	MS_SendTPC(TPC_SET_R_W_REG_ADRS,4);

	data[0] = r_adrs;
	data[1] = r_len;
	data[2] = w_adrs;
	data[3] = w_len;

	MSDC_CLR_FIFO();
	// write data into fifo
	*(volatile kal_uint32*)MSDC_DAT = *(kal_uint32 *)data;	
	// wait cmd ready or busy timeout
	if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
		return status;

	return MS_NOERROR;	
}

/*************************************************************************
* FUNCTION
*  MS_TPC_GetInt
*
* DESCRIPTION
*  TPC for reading 1 byte INT register
*
* PARAMETERS
*	1. intreg: storing the data read form INT register.
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
* 	buffer must be prepared up to multiple of 4 ,ex.
*  if length = 7 , u must prepare 8 bytes  = 2x4 bytes as buffer size
*
*************************************************************************/
// TPC for read 1 byte INT register
MS_STATUS MS_TPC_GetInt(kal_uint8 *intreg)
{
	MS_STATUS status;

	// the data length is 1 for INT register
	MS_SendTPC(TPC_GET_INT,1);
	// read 1 byte data from fifo
	while(MSDC_IS_FIFO_EMPTY && gMSDC_Handle.mIsPresent);
	*intreg = *(volatile kal_uint8*)MSDC_DAT;
	if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
		return status;

	return MS_NOERROR;	
}

/*************************************************************************
* FUNCTION
*  MS_TPC_SetCmd
*
* DESCRIPTION
*  1. TPC set CMD to be executed by Flash Memory Controller.
*	2. Always cause card to issue INT
*	3. Always enable auto GET_INT
*
* PARAMETERS
*	1. cmd: command code for Flash Controller.
*	2. intreg: after excuted cmd, get INT register
*
* RETURNS
*	MS_NOERROR
*	MS_ERR_CRCERR
*	MS_ERR_TIMEOUT
*	MS_ERR_CMDNK
*
* GLOBALS AFFECTED
*	
* NOTE
*
*************************************************************************/
MS_STATUS MS_TPC_SetCmd(kal_uint8 cmd, kal_uint8 *intreg)
{
	MS_STATUS status;

	// set ACMD
	MS_SetAcmd(TPC_GET_INT,1);
	// send the TPC (1 bytes data)
	MS_SendTPC(TPC_SET_CMD,1);
	// write 1 byte data into fifo
	while(MSDC_IS_FIFO_FULL && gMSDC_Handle.mIsPresent);
	*(volatile kal_uint8*)MSDC_DAT = cmd;
#ifndef MSDC_INT	
	// wait cmd ready or busy timeout
	while(!MSDC_IS_INT && gMSDC_Handle.mIsPresent);
#endif	
	if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
		return status;	
	while(MSDC_IS_FIFO_EMPTY && gMSDC_Handle.mIsPresent);
	// read fifo to get int register
	*intreg = *(volatile kal_uint8*)MSDC_DAT;
	// cmd not accept
	if(*intreg & INT_NMDNK)
		return MS_ERR_CMDNK;

	return MS_NOERROR;	
}

/*************************************************************************
* FUNCTION
*  MS_API_ReadSinglePage
*
* DESCRIPTION
*  Read single page with extra data from MS.
*
* PARAMETERS
*	1. blkadrs: physical block address.
*	2. page: page number of the block
*	3. rxbuffer: of size of 512bytes
*	4. extra: buffer for the extra data of the page, of size of 4 bytes.
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*	if extra == NULL, doesn't read the extra data.
*
*************************************************************************/
MS_STATUS MS_API_ReadSinglePage(kal_uint32 blkadrs, kal_uint8 page, kal_uint32 *rxbuffer, kal_uint32 *extra)
{
	MS_STATUS status;
	kal_uint8 data[5],intreg;

	// set parameters
	data[0] = (kal_uint8)(blkadrs >> 16);	// block address 2
	data[1] = (kal_uint8)(blkadrs >> 8);		// block address 1
	data[2] = (kal_uint8)blkadrs;				// block address 0
	data[3] = (kal_uint8)PAGE_MODE;			// access mode		
	data[4] = page;							// page number of the block

	if((status = MS_TPC_SetRWAdrs(MS_STA0_REG,2,MS_BLKADRS2_REG,5))!=MS_NOERROR)
		return status;
	if((status = MS_TPC_WriteReg((kal_uint32*)data,5))!=MS_NOERROR)
		return status;
	// send SET_CMD[BLOCK_READ] ~ page mode
	if((status = MS_TPC_SetCmd(CMD_BLOCK_READ,&intreg))!=MS_NOERROR)
		return status;		
	// read status0~1
	if((status = MS_TPC_ReadReg((kal_uint32*)data,2))!=MS_NOERROR)
		return status;								
	// uncorrectable errors	
	if((intreg & INT_ERR))
	{
		// chect the status1
		if(data[1] & (STA1_UCFG | STA1_UCEX | STA1_UCDT))
			return MS_ERR_UC;	
	}	
	// check int register
	if(intreg !=(INT_CED|INT_BREQ))
		return MS_ERRORS;

	// check MB and FB0 of status0
	if(data[0] & (STA0_MB | STA0_FB0))
		return MS_ERR_STABUSY;

	// data is ready at pagebuffer
	if(data[0] & STA0_BF)
	{
		// read extra data
		if(extra != NULL)
		{
			if((status = MS_TPC_SetRWAdrs(MS_OVERWRITE_REG,MS_EXTRA_RSIZE,0,0))!=MS_NOERROR)
				goto ERR_EXIT;
			if((status = MS_TPC_ReadReg(extra,MS_EXTRA_RSIZE))!=MS_NOERROR)
				goto ERR_EXIT;
		}
		// read data for pagebuffer
		if((status = MS_TPC_ReadPage(rxbuffer))!=MS_NOERROR)
			goto ERR_EXIT;		
	}else
		return MS_ERRORS;

	return MS_NOERROR;
	
ERR_EXIT:
	#ifdef MSDC_USE_INT
	// reset the events
	kal_set_eg_events(MSDC_Events, 0, KAL_AND);
	#endif
	MS_API_ResetFlash();
	MS_API_ClrBuffer();
	MSDC_CLR_FIFO();
	return status;
}

/*************************************************************************
* FUNCTION
*  MS_API_ReadBlock
*
* DESCRIPTION
*	1. read numpage pages form spage during a block or till the end of the block
*	2. if extra == NULL, doesn't read the extra data
*	3. only read extra data of the start page
*
* PARAMETERS
*		blkadrs:		physical block address
*		rxbuffer:	buffer for the read data
*		extra:		buffer for the extra data
*		spage:		start of the reading page number
*		numpage:		number of the pages to read
*		readpage:	pages really be read
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*	if extra == NULL, doesn't read the extra data.
*
*************************************************************************/
MS_STATUS MS_API_ReadBlock(kal_uint32 blkadrs, kal_uint32 *rxbuffer,kal_uint32 *extra, kal_uint8 spage, kal_uint8 numpage, kal_uint8 *readpage)
{
	MS_STATUS status;
	kal_uint8 data[8],i,lastpage,intreg;

	// set parameters                                                  
	data[0] = (kal_uint8)(blkadrs >> 16);	// block address 2             	
	data[1] = (kal_uint8)(blkadrs >> 8);	// block address 1             	
	data[2] = (kal_uint8)blkadrs;			// block address 0             	
	data[3] = (kal_uint8)BLOCK_MODE;		// access mode		           	
	data[4] = spage;					// page number of the block    	
	                                                                   
	if((status = MS_TPC_SetRWAdrs(MS_STA0_REG,2,MS_BLKADRS2_REG,5))!=MS_NOERROR)     	
		goto ERR_EXIT;                                                 	
	if((status = MS_TPC_WriteReg((kal_uint32*)data,5))!=MS_NOERROR)	
		goto ERR_EXIT;                                                 	
	// send SET_CMD[BLOCK_READ] ~ block mode
	if((status = MS_TPC_SetCmd(CMD_BLOCK_READ,&intreg))!=MS_NOERROR)
		goto ERR_EXIT;	
	// only read extra data of the start page
	if(extra != NULL)
	{
		if((status = MS_TPC_SetRWAdrs(MS_OVERWRITE_REG,MS_EXTRA_RSIZE,0,0))!=MS_NOERROR)
			goto ERR_EXIT;				
		if((status = MS_TPC_ReadReg(extra,MS_EXTRA_RSIZE))!=MS_NOERROR)
			goto ERR_EXIT;
		//extra++;
	}
	lastpage = 0;
	*readpage = 0;
	for( i = 0; i < numpage; i++)
	{ 			
		if(!gMSDC_Handle.mIsPresent) 
			return MS_ERR_CARD_NOT_PRESENT;		
 	   if((status = MS_TPC_SetRWAdrs(MS_STA0_REG,2,0,0))!=MS_NOERROR)
			goto ERR_EXIT;
				   
		// read status0~1
		if((status = MS_TPC_ReadReg((kal_uint32*)data,2))!=MS_NOERROR)
			goto ERR_EXIT;
		// uncorrectable flash read error
		if(data[1] & (STA1_UCDT | STA1_UCEX | STA1_UCFG))
			return MS_ERR_UC;
		// check if reach last page
		if(!(data[0] & STA0_MB) && (intreg & INT_CED))
			lastpage = 1;
		// data is ready at pagebuffer
		if(data[0] & STA0_BF)
		{			   		
			// set auto command again
			// note the last page will not incur  INT
			if(!lastpage)
			   MS_SetAcmd(TPC_GET_INT,1);				
			// read data for pagebuffer
			if((status = MS_TPC_ReadPage(rxbuffer))!=MS_NOERROR)
				goto ERR_EXIT;
				
			rxbuffer += MS_PAGE_SIZE/4;	
			(*readpage)++;
			// read extra data

		}else
			return MS_ERRORS;			
		if(lastpage)
			return (*readpage == numpage)?MS_NOERROR:MS_LASTPAGE;
				
#ifndef MSDC_INT
		// wait cmd ready for ACMD(TPC_GET_INT)		
		if((status = MS_WaitCmdRdyOrTo())!=MS_NOERROR)
			goto ERR_EXIT;
#endif			
		// read fifo to get int register
		while(MSDC_IS_FIFO_EMPTY && gMSDC_Handle.mIsPresent);
		intreg = *(volatile kal_uint8*)MSDC_DAT;	
									
	}	
	// reach the number of the numpage
	// send block end to stop the transmission (may be failed but don't care about it)
	MS_TPC_SetCmd(CMD_BLOCK_END,&intreg);
	if((status = MS_API_ClrBuffer())!=MS_NOERROR)
		goto ERR_EXIT;
	// clear the fifo
	MSDC_CLR_FIFO();			
	return MS_NOERROR;
	
ERR_EXIT:
	#ifdef MSDC_USE_INT
	// reset the events
	kal_set_eg_events(MSDC_Events, 0, KAL_AND);
	#endif
	MS_API_ResetFlash();
	MS_API_ClrBuffer();
	MSDC_CLR_FIFO();
	return status;	
}

/*************************************************************************
* FUNCTION
*  MS_API_WriteSinglePage
*
* DESCRIPTION
*  Read single page with extra data from MS.
*
* PARAMETERS
*	1. blkadrs: physical block address.
*	2. page: page number of the block
*	3. txbuffer: of size of 512bytes
*	4. extra: buffer for the extra data of the page, of size of 4 bytes.
*
* RETURNS
*	MS_STATUS
*
* GLOBALS AFFECTED
*	
* NOTE
*	extra should not be NULL, make sure extra data contains reasonable data
*
*************************************************************************/
MS_STATUS MS_API_WriteSinglePage(kal_uint32 blkadrs,  kal_uint8 page, kal_uint32 *txbuffer, kal_uint32 extra)
{
	MS_STATUS status;
	kal_uint8 data[10],intreg,*ptr;

	if(gMS.is_wp)	
		return MS_ERR_WP;
	ptr = (kal_uint8*)extra;
	// set parameters
	data[0] = MS_SYS_DEFAULT;
	data[1] = (kal_uint8)(blkadrs >> 16);	// block address 2
	data[2] = (kal_uint8)(blkadrs >> 8);	// block address 1
	data[3] = (kal_uint8)blkadrs;			// block address 0
	data[4] = (kal_uint8)PAGE_MODE;			// access mode		
	data[5] = page;						// page number of the block
	data[6] = *ptr;						// overwriteflag
	data[7] = *(ptr+1);					// managementflag
	data[8] = *(ptr+2);					// logical address 1
	data[9]	= *(ptr+3);					// logical address 0

⌨️ 快捷键说明

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