📄 mspro.c
字号:
kal_uint32 flags;
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
kal_retrieve_eg_events(MSDC_Events,EVENT_MSRDYIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
MSDC_STOP_TIMER();
#else
{
kal_uint32 t1;
t1 = drv_get_current_time();
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
while(!MSDC_IS_INT && 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;
}
MSDC_STOP_TIMER();
MSDC_CLR_INT();
}
#endif
msc_sta = *(volatile kal_uint16*)MSC_STA;
if(msc_sta & MSC_STA_CRCERR)
return MSP_ERR_CRCERR;
else if(msc_sta & MSC_STA_TOER)
return MSP_ERR_TIMEOUT;
else if(msc_sta & MSC_STA_RDY)
return MSP_NOERROR;
if(gMSDC_Handle.is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
return MSP_NOERROR;
}
/*************************************************************************
* FUNCTION
* MSP_WaitCard_INT
*
* DESCRIPTION
* wait for MS card producing INT signal and retreive result of the INT
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static MSP_STATUS MSP_WaitCard_INT(kal_uint16 *msc_sta)
{
#ifdef MSDC_USE_INT
kal_uint32 flags;
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_CMD);
kal_retrieve_eg_events(MSDC_Events,EVENT_MSIFIRQ,KAL_AND_CONSUME,&flags,KAL_SUSPEND);
MSDC_STOP_TIMER();
*msc_sta = *(volatile kal_uint16*)MSC_STA;
#else
kal_uint32 t1;
t1 = drv_get_current_time();
MSDC_START_TIMER(MSDC_TIMEOUT_PERIOD_DAT);
while(!((*msc_sta = *(volatile kal_uint16*)MSC_STA)&MSC_STA_SIF)
&& 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;
}
MSDC_STOP_TIMER();
MSDC_CLR_INT();
if((*msc_sta = *(volatile kal_uint16*)MSC_STA)&MSC_STA_SIF)
return MSP_NOERROR;
if(gMSDC_Handle.is_timeout)
return MSDC_GPT_TIMEOUT_ERR;
#endif
if(gMSP.mode == MSP_SERIAL)
{
MSP_STATUS status;
kal_uint8 reg[4];
status = MSP_TPC_GetInt((kal_uint32*)reg);
if(reg[0] & INT_BREQ)
*msc_sta |= MSC_STA_BREQ;
if(reg[0] & INT_CED)
*msc_sta |= MSC_STA_CED;
if(reg[0]& INT_CMDNK)
*msc_sta |= MSC_STA_CMDNK;
if((reg[0] & INT_ERR) || (status != MSP_NOERROR))
*msc_sta |= MSC_STA_ERR;
}
return MSP_NOERROR;
}
/*************************************************************************
* FUNCTION
* MSP_TPCs
*
* DESCRIPTION
* send TPC with data transfer
*
* PARAMETERS
* buffer: data buffer for read or write
* size: size of data to read or write(bytes)
* tpc: TPC code
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static MSP_STATUS MSP_TPCs(kal_uint32* buffer, kal_uint16 size, kal_uint8 tpc)
{
MSP_STATUS status;
kal_uint32 i, count;
kal_bool IsWrite;
// check handshake ready produced by card
//direction 0: read, 1: write
IsWrite = (tpc & 0x8)?KAL_TRUE:KAL_FALSE;
// data transfer
if(size == 512)
{
EnableMSDC_DMA();
MSDC_DMATransferFirst((kal_uint32)buffer,512/4,IsWrite);
// send TPC
MSP_SendTPC(tpc,size);
status = MSDC_DMATransferFinal();
status = MSP_WaitCmdRdyOrTo();
DisableMSDC_DMA();
if(status != MSP_NOERROR)
goto err_exit; // maybe timeout, crc err.
}
else
{
kal_uint32 t1;
MSP_SendTPC(tpc,size);
count = (size+3)/4;
t1 = drv_get_current_time();
if(!IsWrite) // read
{
for(i=0;i<count;)
{
if(!MSDC_IS_FIFO_EMPTY)
{
*(buffer+i) = *(volatile kal_uint32*)MSDC_DAT;
i++;
}
else if(MS_IS_TIMEOUT)
break;
else if(!gMSDC_Handle.mIsPresent)
break;
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
{
gMSDC_Handle.is_timeout = KAL_TRUE;
return MSDC_GPT_TIMEOUT_ERR;
}
}
}
else // write
{
for(i=0;i<count;)
{
if(!MSDC_IS_FIFO_FULL)
{
*(volatile kal_uint32*)MSDC_DAT = *(buffer+i);
i++;
}
else if(MS_IS_TIMEOUT)
break;
else if(!gMSDC_Handle.mIsPresent)
break;
if(drv_get_duration_ms(t1) > MSDC_TIMEOUT_PERIOD_DAT*11)
{
gMSDC_Handle.is_timeout = KAL_TRUE;
return MSDC_GPT_TIMEOUT_ERR;
}
}
// wait cmd ready or busy timeout
}
if((status = MSP_WaitCmdRdyOrTo()) != MSP_NOERROR)
return status;
}
return MSP_NOERROR;
err_exit:
#if defined(MSDC_USE_INT)
kal_set_eg_events(MSDC_Events,0,KAL_AND);
#endif
DisableMSDC_DMA();
MSP_CMD_Stop();
return status;
}
/*************************************************************************
* FUNCTION
* MSP_TPC_ReadLongData
*
* DESCRIPTION
* read data form pagebuffer in uints of page(512 bytes)
*
* PARAMETERS
* rxbuffer: data buffer for read
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static MSP_STATUS MSP_TPC_ReadLongData(kal_uint32* rxbuffer)
{
return MSP_TPCs(rxbuffer,512,TPC_READ_LONG_DATA);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_WriteLongData
*
* DESCRIPTION
* write data to pagebuffer in uints of page(512 bytes)
*
* PARAMETERS
* txbuffer: data buffer for read
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*
*************************************************************************/
// TPC for writing to PageBuffer in uints of page(512 bytes)
MSP_STATUS MSP_TPC_WriteLongData(kal_uint32* txbuffer)
{
return MSP_TPCs(txbuffer,512,TPC_WRITE_LONG_DATA);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_ReadReg
*
* DESCRIPTION
* TPC for reading form the register which address was set by TPC_SET_R/W_REG_ADRS.
*
* PARAMETERS
* buffer: data buffer for read
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Note: buffer must be prepared up to multiple of 4 ,ex.
* if length = 7 , u must prepare 8 bytes = 2x4 bytes as buffer
*
*************************************************************************/
static MSP_STATUS MSP_TPC_ReadReg(kal_uint32* buffer, kal_uint8 length)
{
return MSP_TPCs(buffer,(kal_uint16)length,TPC_READ_REG);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_WriteReg
*
* DESCRIPTION
* TPC for writing data into the register which address was set by TPC_SET_R/W_REG_ADRS.
*
* PARAMETERS
* buffer: data buffer for write
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
* Note: buffer must be prepared up to multiple of 4 ,ex.
* if length = 7 , u must prepare 8 bytes = 2x4 bytes as buffer
*
*************************************************************************/
static MSP_STATUS MSP_TPC_WriteReg(kal_uint32* buffer, kal_uint8 length)
{
return MSP_TPCs(buffer,(kal_uint16)length,TPC_WRITE_REG);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_SetRWAdrs
*
* DESCRIPTION
* TPC for setting values which determine the registers accessed by WRITE_REG and READ_REG
*
* PARAMETERS
* r_adrs: start address of register for ReadReg
* r_len: length for ReadReg
* w_adrs: start address of register for WriteReg
* w_len: length for WriteReg
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static MSP_STATUS MSP_TPC_SetRWAdrs(kal_uint8 r_adrs, kal_uint8 r_len, kal_uint8 w_adrs, kal_uint8 w_len)
{
kal_uint8 data[4];
data[0] = r_adrs;
data[1] = r_len;
data[2] = w_adrs;
data[3] = w_len;
return MSP_TPCs((kal_uint32*)data,(kal_uint16)4,TPC_SET_R_W_REG_ADRS);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_GetInt
*
* DESCRIPTION
* TPC for read 1 byte INT register
*
* PARAMETERS
* intreg: intreg contains the result of the INT register
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static MSP_STATUS MSP_TPC_GetInt(kal_uint32* intreg)
{
return MSP_TPCs(intreg,(kal_uint16)1,TPC_GET_INT);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_ReadShortData
*
* DESCRIPTION
* read data from data buffer in the size of (32, 64, 128 and 256 bytes)
*
* PARAMETERS
* buffer: data buffer for read
* length: enum of short data (32,64,128,256)
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
// read data from data buffer in the size of (32, 64, 128 and 256 bytes)
static MSP_STATUS MSP_TPC_ReadShortData(kal_uint32* buffer, ms_ShortData_enum length)
{
// set TPC parameter for short data length
MSP_TPC_SetRWAdrs(0,8,MSP_TPCPARA_REG,1);
MSP_TPC_WriteReg((kal_uint32*)&length,1);
return MSP_TPCs(buffer,(kal_uint16)(1 << (length+5)),TPC_READ_SHORT_DATA);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_WriteShortData
*
* DESCRIPTION
* write data into data buffer in the size of (32, 64, 128 and 256 bytes)
*
* PARAMETERS
* buffer: data buffer for write
* length: enum of short data (32,64,128,256)
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
MSP_STATUS MSP_TPC_WriteShortData(kal_uint32* buffer, ms_ShortData_enum length)
{
// set TPC parameter for short data length
MSP_TPC_SetRWAdrs(0,8,MSP_TPCPARA_REG,1);
MSP_TPC_WriteReg((kal_uint32*)&length,1);
return MSP_TPCs(buffer,(kal_uint16)length,TPC_WRITE_SHORT_DATA);
}
/*************************************************************************
* FUNCTION
* MSP_TPC_SetCmd
*
* DESCRIPTION
* send command to be executed by Memory I/F Sequencer
*
* PARAMETERS
* cmd: command code
* msc_stc: status after command is executed
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
MSP_STATUS MSP_TPC_SetCmd(kal_uint8 cmd, kal_uint16* msc_sta)
{
MSP_STATUS status;
// send the TPC (1 bytes data)
MSP_SendTPC(TPC_SET_CMD,1);
// write 1 byte data into fifo
*(volatile kal_uint8*)MSDC_DAT = cmd;
// TPC transaction complete
if((status = MSP_WaitCmdRdyOrTo()) != MSP_NOERROR)
return status;
// wait for INT signal
MSP_WaitCard_INT(msc_sta);
// cmd not accept
if(*msc_sta & (MSC_STA_CMDNK|MSC_STA_ERR))
return MSP_ERR_CMDFAIL;
return MSP_NOERROR;
}
/*************************************************************************
* FUNCTION
* MSP_TPC_ExSetCmd
*
* DESCRIPTION
* send command with data count and address to Memory I/F Sequencer
*
* PARAMETERS
* adrs: start address for data
* count: data count
* cmd: command code
* msc_sta: status after command is executed
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static MSP_STATUS MSP_TPC_ExSetCmd(kal_uint32 adrs, kal_uint16 count, kal_uint8 cmd, kal_uint16* msc_sta)
{
MSP_STATUS status;
kal_uint8 buffer[8] = {0};
// set parameter register (7 bytes = cmd x1 + count x2 + adrs x4 )
buffer[0] = cmd;
buffer[1] = count >> 8;
buffer[2] = (kal_uint8)count;
buffer[3] = adrs >> 24;
buffer[4] = adrs >> 16;
buffer[5] = adrs >> 8;
buffer[6] = (kal_uint8)adrs;
if((status = MSP_TPCs((kal_uint32*)buffer,7,TPC_EX_SET_CMD)) != MSP_NOERROR)
return status;
// wait for INT signal
MSP_WaitCard_INT(msc_sta);
// cmd not accept
if(*msc_sta & (MSC_STA_CMDNK|MSC_STA_ERR))
return MSP_ERR_CMDFAIL;
return MSP_NOERROR;
}
/*************************************************************************
* FUNCTION
* MSP_CMD_ReadWriteData
*
* DESCRIPTION
* read/write data in user area sequentially starting from the designated address.
*
* PARAMETERS
* 1. adrs: start address.
* 2. count: number of of sectors
* 3. buffer: data buffer
* 4. sectors: actually sectors accessed
* 5. IsWrite: indicating read or write data
*
* RETURNS
* MSP_STATUS
*
* GLOBALS AFFECTED
*
* NOTE
*
*************************************************************************/
MSP_STATUS MSP_CMD_ReadWriteData(kal_uint32 adrs, kal_uint16 count, kal_uint32* buffer, kal_uint16* sectors,msp_direction_enum IsWrite)
{
MSP_STATUS status;
kal_uint16 msc_sta;
kal_uint8 cmd,tpc;
*sectors = 0;
if(IsWrite == MSP_WRITE)
{
if(gMSP.is_wp)
return MSP_ERR_WRITE_PROTECT;
cmd = CMD_WRITE_DATA;
tpc = TPC_WRITE_LONG_DATA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -