📄 ms.c
字号:
*************************************************************************/
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 + -