?? sdhal.c
字號:
MCIClear = CmdRespStatus | MCI_CMD_RESP_END;
break; /* 響應(yīng)已成功接收到,退出循環(huán) */
}
else if ((CmdRespStatus & MCI_CMD_SENT) && (ExpectResp == EXPECT_NO_RESP))
{ /* 該命令無須響應(yīng) */
MCIClear = MCI_CMD_SENT;
return SD_NO_ERR; /* 返回命令*/
}
}
if ((MCIRespCmd & 0x3F) != ExpectCmdData)
{
/* 響應(yīng)為非R1, 而是R2或R3, 則無須檢查響應(yīng)命令是否與發(fā)送的相符合 */
if ((ExpectCmdData != SEND_OP_COND) && (ExpectCmdData != SEND_APP_OP_COND)
&& (ExpectCmdData != ALL_SEND_CID) && (ExpectCmdData != SEND_CSD))
{
return SD_ERR_CMD_RESP; /* 返回響應(yīng)錯誤 */
}
}
/* 下面讀取短響應(yīng)內(nèi)容及長響應(yīng)內(nèi)容 */
if ((ExpectResp == EXPECT_SHORT_RESP) && (resplen == 1))
{
*CmdResp = MCIResponse0; /* 讀取短響應(yīng)內(nèi)容 */
}
else if ((ExpectResp == EXPECT_LONG_RESP) && (resplen == 4))
{
*CmdResp = MCIResponse0; /* 讀取長響應(yīng)內(nèi)容 */
*(CmdResp+1) = MCIResponse1;
*(CmdResp+2) = MCIResponse2;
*(CmdResp+3) = MCIResponse3;
}
return SD_NO_ERR; /* 響應(yīng)正確. */
}
/**********************************
下面部分為 MCI 中斷處理相關(guān)函數(shù)
***********************************/
/*******************************************************************************************************************
** 函數(shù)名稱: MCI_DataEndProcess()
**
** 功能描述: MCI 數(shù)據(jù)結(jié)束處理函數(shù)
********************************************************************************************************************/
void MCI_DataEndProcess(void)
{
#if LPC23xx_MCI_DMA_EN
if (lpc_mci.CurTran == MCI_CUR_SEND)
{
while ( !(DMACRawIntTCStatus & 0x01) );
DMACIntTCClear |= 0x01;
lpc_mci.RxTxFlag = SD_NO_ERR; /* DMA 接收塊數(shù)據(jù)成功 */
}
else
{
while ( !(DMACRawIntTCStatus & 0x02) );
DMACIntTCClear |= 0x02;
lpc_mci.RxTxFlag = SD_NO_ERR; /* DMA 發(fā)送塊數(shù)據(jù)成功 */
}
#if SD_UCOSII_EN
OSSemPost(lpc_mci.psds->pSemSdmmcRW); /* 使等待函數(shù)就緒 */
#endif
#else
MCIClear |= MCI_DATA_BLK_END;
if ((lpc_mci.SendCnt >= SD_BLOCKSIZE) ||
(lpc_mci.RecCnt >= SD_BLOCKSIZE))
{ /* 塊數(shù)據(jù)已收/發(fā)成功 */
lpc_mci.RxTxFlag = SD_NO_ERR;
#if SD_UCOSII_EN
OSSemPost(lpc_mci.psds->pSemSdmmcRW);
#endif
}
#endif
MCIDataCtrl = 0; /* 數(shù)據(jù)控制寄存器清0 */
}
/*******************************************************************************************************************
** 函數(shù)名稱: MCI_TxActiveProcess()
**
** 功能描述: MCI 發(fā)送數(shù)據(jù)處理函數(shù)
********************************************************************************************************************/
void MCI_TxActiveProcess(void)
{
INT32U DataWord, blockSize,i;
MCIClear |= MCI_TX_ACTIVE;
if (lpc_mci.SendCnt < SD_BLOCKSIZE )
{
blockSize = 0;
if (MCIStatus & MCI_TX_FIFO_EMPTY) /* FIFO全空 */
blockSize = FIFO_SIZE * 4;
else if (MCIStatus & MCI_TX_HALF_EMPTY) /* FIFO半空 */
blockSize = (FIFO_SIZE / 2) * 4;
else if (!(MCIStatus & MCI_TX_FIFO_FULL)) /* FIFO全滿 */
blockSize = 1 * 4;
for (i = 0; i < blockSize; i += 4)
{ /* 循環(huán)向FIFO中寫入數(shù)據(jù) */
DataWord = ((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt]) +
(((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt + 1]) << 8) +
(((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt + 2]) << 16) +
(((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt + 3]) << 24);
MCIFIFO = DataWord; /* 向FIFO寫入一個32位的數(shù)據(jù) */
lpc_mci.SendCnt += 4;
if (lpc_mci.SendCnt >= (SD_BLOCKSIZE))
break; /* 已發(fā)送完一個數(shù)據(jù)塊 */
}
}
}
/*******************************************************************************************************************
** 函數(shù)名稱: MCI_RxActiveProcess()
**
** 功能描述: MCI 接收數(shù)據(jù)處理函數(shù)
********************************************************************************************************************/
void MCI_RxActiveProcess(void)
{
INT32U DataWord, blockSize, i;
INT32U Status;
if (lpc_mci.RecCnt < SD_BLOCKSIZE )
{
blockSize = 0;
if (!(MCIStatus & MCI_RX_FIFO_FULL)) /* FIFO全滿 */
blockSize = FIFO_SIZE * 4;
else if (MCIStatus & MCI_RX_HALF_FULL) /* FIFO半滿 */
blockSize = (FIFO_SIZE/2) * 4;
else if (MCIStatus & MCI_RX_FIFO_EMPTY) /* FIFO全空 */
blockSize = 1 * 4;
for ( i = 0; i < blockSize; i += 4 )
{ /* 循環(huán)從FIFO中讀取數(shù)據(jù) */
while (!((Status = MCIStatus) & MCI_RX_DATA_AVAIL))
{
if ((Status & MCI_RX_OVERRUN) != 0) /* 判斷是否發(fā)生FIFO下溢錯誤 */
{
MCIDataCtrl = 0;
MCIClear = 0x7FF;
MCIMask0 = 0;
MCIMask1 = 0;
lpc_mci.RxTxFlag = SD_ERR_HARDWARE;
return;
}
}
DataWord = MCIFIFO; /* 從FIFO中讀取一個32位的數(shù)據(jù) */
lpc_mci.pRecBuf[lpc_mci.RecCnt] = DataWord & 0xFF;
lpc_mci.pRecBuf[lpc_mci.RecCnt + 1] = (DataWord >> 8) & 0xFF;
lpc_mci.pRecBuf[lpc_mci.RecCnt + 2] = (DataWord >> 16) & 0xFF;
lpc_mci.pRecBuf[lpc_mci.RecCnt + 3] = (DataWord >> 24) & 0xFF;
lpc_mci.RecCnt += 4; /* 計數(shù)器計數(shù) */
if (lpc_mci.RecCnt >= (SD_BLOCKSIZE))
break;
}
}
}
/*******************************************************************************************************************
** 函數(shù)名稱: MCI_DataInterruptProcess()
**
** 功能描述: 這部分是處理讀寫卡的關(guān)鍵部分. 對于FIFO中斷沒有處理, 本函數(shù)主要使用 TX_ACTIVE 和 RX_ACTIVE 處理塊讀寫.
********************************************************************************************************************/
void MCI_DataInterruptProcess( void )
{
INT32U Status = MCIStatus;
if (Status & MCI_DATA_END) /* 數(shù)據(jù)結(jié)束中斷 */
MCIClear = Status | MCI_DATA_END;
if (Status & MCI_DATA_BLK_END) /* 數(shù)據(jù)塊結(jié)束中斷 */
{
MCI_DataEndProcess();
return;
}
#if !LPC23xx_MCI_DMA_EN
if (MCIStatus & MCI_TX_ACTIVE)
MCI_TxActiveProcess(); /* 發(fā)送數(shù)據(jù)中斷處理 */
if (MCIStatus & MCI_RX_ACTIVE)
MCI_RxActiveProcess(); /* 接收數(shù)據(jù)中斷處理 */
#endif
}
/*******************************************************************************************************************
** 函數(shù)名稱: MCI_DataErrorProcess()
**
** 功能描述: MCI 錯誤處理函數(shù): 當MCI有錯誤產(chǎn)生時, 該函數(shù)被調(diào)用
********************************************************************************************************************/
void MCI_DataErrorProcess( void )
{
INT32U Status = MCIStatus;
if (Status & MCI_DATA_CRC_FAIL)
lpc_mci.RxTxFlag = SD_ERR_DATA_CRC16; /* 收/發(fā)數(shù)據(jù)塊時發(fā)生CRC校驗錯誤 */
if (Status & MCI_DATA_TIMEOUT)
{
if (lpc_mci.CurTran == MCI_CUR_SEND)
lpc_mci.RxTxFlag = SD_ERR_TIMEOUT_WRITE; /* 發(fā)送數(shù)據(jù)超時錯誤 */
else
lpc_mci.RxTxFlag = SD_ERR_TIMEOUT_READ; /* 接收數(shù)據(jù)超時錯誤 */
}
if (Status & MCI_TX_UNDERRUN) /* 發(fā)送數(shù)據(jù)時FIFO下溢錯誤 */
lpc_mci.RxTxFlag = SD_ERR_HARDWARE;
if (Status & MCI_RX_OVERRUN) /* 接收數(shù)據(jù)時FIFO上溢錯誤 */
lpc_mci.RxTxFlag = SD_ERR_HARDWARE;
if ( Status & MCI_START_BIT_ERR ) /* 寬總線模式下所有數(shù)據(jù)信號線上沒有檢測到起始位 */
lpc_mci.RxTxFlag = SD_ERR_DATA_STARTBIT;
#if SD_UCOSII_EN
OSSemPost(lpc_mci.psds->pSemSdmmcRW); /* 使等待函數(shù)就緒 */
#endif
}
/*******************************************************************************************************************
** 函數(shù)名稱: MCI_Exception 或 MCI_Handler
**
** 功能描述: MCI 中斷處理函數(shù)
********************************************************************************************************************/
#if SD_UCOSII_EN
void MCI_Exception(void)
#else
void __irq MCI_Handler(void)
#endif
{
INT32U Status = MCIStatus; /* 讀取MCI當前狀態(tài) */
if (Status & CMD_INT_MASK)
{ /* 命令中斷處理 */
MCIClear = Status & CMD_INT_MASK;
}
else if (MCIStatus & DATA_ERR_INT_MASK)
{ /* 數(shù)據(jù)錯誤中斷處理 */
MCI_DataErrorProcess();
MCIClear |= DATA_ERR_INT_MASK; /* 清除數(shù)據(jù)錯誤中斷位 */
}
else if (MCIStatus & DATA_INT_MASK)
{ /* 數(shù)據(jù)中斷處理 */
MCI_DataInterruptProcess();
//MCIClear |= DATA_INT_MASK;
}
else if (MCIStatus & FIFO_INT_MASK)
{
;
}
VICVectAddr = 0; /* 應(yīng)答中斷控制器 */
}
/*************************
LPC23xx DMA 初始化函數(shù)
**************************/
#if LPC23xx_MCI_DMA_EN
/*******************************************************************************************************************
** 函數(shù)名稱: DMA_Init()
**
** 功能描述: LPC23xx DMA控制器初始化
**
** 輸 入: INT32U ChannelNum: DMA 控制器通道號
** INT32U DMAMode: DMA 模式
** 輸 出: 無
**
** 返 回 值: TRUE: 正確; FALSE: 錯誤
********************************************************************************************************************/
INT32U DMA_Init(INT32U ChannelNum, INT32U DMAMode)
{
/* USB RAM is used for test.
Please note, Ethernet has its own SRAM, but GPDMA can't access
that. GPDMA can access USB SRAM and IRAM. Ethernet DMA controller can
access both IRAM and Ethernet SRAM. */
if ( ChannelNum == 0 )
{
DMACIntErrClr = 0x01;
if ( DMAMode == M2M )
{
/* Ch0 is set for M2M tranfer from AHB1 to AHB2 SRAM */
DMACC0SrcAddr = DMA_SRC;
DMACC0DestAddr = DMA_DST;
/* Terminal Count Int enable */
DMACC0Control = (DMA_SIZE & 0x0FFF) | (0x04 << 12) | (0x04 << 15)
| (0x02 << 18) | (0x02 << 21) | (1 << 26) | (1 << 27) | 0x80000000;
}
else if ( DMAMode == M2P )
{
/* Ch0 set for M2P transfer from mempry to MCI FIFO. */
DMACC0SrcAddr = DMA_SRC;
DMACC0DestAddr = DMA_MCIFIFO;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC0Control = (DMA_SIZE & 0x0FFF) | (0x01 << 12) | (0x02 << 15)
| (0x02 << 18) | (0x02 << 21) | (1 << 26) | 0x80000000;
}
else if ( DMAMode == P2M )
{
/* Ch0 set for P2M transfer from MCI FIFO to memory. */
DMACC0SrcAddr = DMA_MCIFIFO;
DMACC0DestAddr = DMA_DST;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC0Control = (DMA_SIZE & 0x0FFF) | (0x04 << 12) | (0x04 << 15)
| (0x02 << 18) | (0x02 << 21) | (1 << 27) | 0x80000000;
}
else
{
return ( FALSE );
}
}
else if ( ChannelNum == 1 )
{
DMACIntErrClr = 0x02;
if ( DMAMode == M2M )
{
/* Ch1 is set for M2M tranfer */
DMACC1SrcAddr = DMA_SRC;
DMACC1DestAddr = DMA_DST;
/* Terminal Count Int enable */
DMACC1Control = (DMA_SIZE & 0x0FFF) | (0x04 << 12) | (0x04 << 15)
| (0x02 << 18) | (0x02 << 21) | (1 << 26) | (1 << 27) | 0x80000000;
}
else if ( DMAMode == M2P )
{
/* Ch1 set for M2P transfer from mempry to MCI FIFO. */
DMACC1SrcAddr = DMA_SRC;
DMACC1DestAddr = DMA_MCIFIFO;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC1Control = (DMA_SIZE & 0x0FFF) | (0x04 << 12) | (0x04 << 15)
| (0x02 << 18) | (0x02 << 21) | (1 << 26) | 0x80000000;
}
else if ( DMAMode == P2M )
{
/* Ch1 set for P2M transfer from MCI_FIFO to memory. */
DMACC1SrcAddr = DMA_MCIFIFO;
DMACC1DestAddr = DMA_DST;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC1Control = (DMA_SIZE & 0x0FFF) | (0x02 << 12) | (0x02 << 15)
| (0x02 << 18) | (0x02 << 21) | (1 << 27) | 0x80000000;
}
else
{
return ( FALSE );
}
}
else
{
return ( FALSE );
}
DMACConfiguration = 0x01; /* Enable DMA channels, little endian */
while ( !(DMACConfiguration & 0x01) );
return (TRUE);
}
#endif
#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -