?? sdhal.c
字號:
MCIClear = CmdRespStatus | MCI_CMD_RESP_END;
break; /* 響應已成功接收到,退出循環 */
}
else if ((CmdRespStatus & MCI_CMD_SENT) && (ExpectResp == EXPECT_NO_RESP))
{ /* 該命令無須響應 */
MCIClear = MCI_CMD_SENT;
return SD_NO_ERR; /* 返回命令*/
}
}
if ((MCIRespCmd & 0x3F) != ExpectCmdData)
{
/* 響應為非R1, 而是R2或R3, 則無須檢查響應命令是否與發送的相符合 */
if ((ExpectCmdData != SEND_OP_COND) && (ExpectCmdData != SEND_APP_OP_COND)
&& (ExpectCmdData != ALL_SEND_CID) && (ExpectCmdData != SEND_CSD))
{
return SD_ERR_CMD_RESP; /* 返回響應錯誤 */
}
}
/* 下面讀取短響應內容及長響應內容 */
if ((ExpectResp == EXPECT_SHORT_RESP) && (resplen == 1))
{
*CmdResp = MCIResponse0; /* 讀取短響應內容 */
}
else if ((ExpectResp == EXPECT_LONG_RESP) && (resplen == 4))
{
*CmdResp = MCIResponse0; /* 讀取長響應內容 */
*(CmdResp+1) = MCIResponse1;
*(CmdResp+2) = MCIResponse2;
*(CmdResp+3) = MCIResponse3;
}
return SD_NO_ERR; /* 響應正確. */
}
/**********************************
下面部分為 MCI 中斷處理相關函數
***********************************/
/*******************************************************************************************************************
** 函數名稱: MCI_DataEndProcess()
**
** 功能描述: MCI 數據結束處理函數
********************************************************************************************************************/
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 接收塊數據成功 */
}
else
{
while ( !(DMACRawIntTCStatus & 0x02) );
DMACIntTCClear |= 0x02;
lpc_mci.RxTxFlag = SD_NO_ERR; /* DMA 發送塊數據成功 */
}
#if SD_UCOSII_EN
OSSemPost(lpc_mci.psds->pSemSdmmcRW); /* 使等待函數就緒 */
#endif
#else
MCIClear |= MCI_DATA_BLK_END;
if ((lpc_mci.SendCnt >= SD_BLOCKSIZE) ||
(lpc_mci.RecCnt >= SD_BLOCKSIZE))
{ /* 塊數據已收/發成功 */
lpc_mci.RxTxFlag = SD_NO_ERR;
#if SD_UCOSII_EN
OSSemPost(lpc_mci.psds->pSemSdmmcRW);
#endif
}
#endif
MCIDataCtrl = 0; /* 數據控制寄存器清0 */
}
/*******************************************************************************************************************
** 函數名稱: MCI_TxActiveProcess()
**
** 功能描述: MCI 發送數據處理函數
********************************************************************************************************************/
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)
{ /* 循環向FIFO中寫入數據 */
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位的數據 */
lpc_mci.SendCnt += 4;
if (lpc_mci.SendCnt >= (SD_BLOCKSIZE))
break; /* 已發送完一個數據塊 */
}
}
}
/*******************************************************************************************************************
** 函數名稱: MCI_RxActiveProcess()
**
** 功能描述: MCI 接收數據處理函數
********************************************************************************************************************/
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 )
{ /* 循環從FIFO中讀取數據 */
while (!((Status = MCIStatus) & MCI_RX_DATA_AVAIL))
{
if ((Status & MCI_RX_OVERRUN) != 0) /* 判斷是否發生FIFO下溢錯誤 */
{
MCIDataCtrl = 0;
MCIClear = 0x7FF;
MCIMask0 = 0;
MCIMask1 = 0;
lpc_mci.RxTxFlag = SD_ERR_HARDWARE;
return;
}
}
DataWord = MCIFIFO; /* 從FIFO中讀取一個32位的數據 */
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; /* 計數器計數 */
if (lpc_mci.RecCnt >= (SD_BLOCKSIZE))
break;
}
}
}
/*******************************************************************************************************************
** 函數名稱: MCI_DataInterruptProcess()
**
** 功能描述: 這部分是處理讀寫卡的關鍵部分. 對于FIFO中斷沒有處理, 本函數主要使用 TX_ACTIVE 和 RX_ACTIVE 處理塊讀寫.
********************************************************************************************************************/
void MCI_DataInterruptProcess( void )
{
INT32U Status = MCIStatus;
if (Status & MCI_DATA_END) /* 數據結束中斷 */
MCIClear = Status | MCI_DATA_END;
if (Status & MCI_DATA_BLK_END) /* 數據塊結束中斷 */
{
MCI_DataEndProcess();
return;
}
#if !LPC23xx_MCI_DMA_EN
if (MCIStatus & MCI_TX_ACTIVE)
MCI_TxActiveProcess(); /* 發送數據中斷處理 */
if (MCIStatus & MCI_RX_ACTIVE)
MCI_RxActiveProcess(); /* 接收數據中斷處理 */
#endif
}
/*******************************************************************************************************************
** 函數名稱: MCI_DataErrorProcess()
**
** 功能描述: MCI 錯誤處理函數: 當MCI有錯誤產生時, 該函數被調用
********************************************************************************************************************/
void MCI_DataErrorProcess( void )
{
INT32U Status = MCIStatus;
if (Status & MCI_DATA_CRC_FAIL)
lpc_mci.RxTxFlag = SD_ERR_DATA_CRC16; /* 收/發數據塊時發生CRC校驗錯誤 */
if (Status & MCI_DATA_TIMEOUT)
{
if (lpc_mci.CurTran == MCI_CUR_SEND)
lpc_mci.RxTxFlag = SD_ERR_TIMEOUT_WRITE; /* 發送數據超時錯誤 */
else
lpc_mci.RxTxFlag = SD_ERR_TIMEOUT_READ; /* 接收數據超時錯誤 */
}
if (Status & MCI_TX_UNDERRUN) /* 發送數據時FIFO下溢錯誤 */
lpc_mci.RxTxFlag = SD_ERR_HARDWARE;
if (Status & MCI_RX_OVERRUN) /* 接收數據時FIFO上溢錯誤 */
lpc_mci.RxTxFlag = SD_ERR_HARDWARE;
if ( Status & MCI_START_BIT_ERR ) /* 寬總線模式下所有數據信號線上沒有檢測到起始位 */
lpc_mci.RxTxFlag = SD_ERR_DATA_STARTBIT;
#if SD_UCOSII_EN
OSSemPost(lpc_mci.psds->pSemSdmmcRW); /* 使等待函數就緒 */
#endif
}
/*******************************************************************************************************************
** 函數名稱: MCI_Exception 或 MCI_Handler
**
** 功能描述: MCI 中斷處理函數
********************************************************************************************************************/
#if SD_UCOSII_EN
void MCI_Exception(void)
#else
void __irq MCI_Handler(void)
#endif
{
INT32U Status = MCIStatus; /* 讀取MCI當前狀態 */
if (Status & CMD_INT_MASK)
{ /* 命令中斷處理 */
MCIClear = Status & CMD_INT_MASK;
}
else if (MCIStatus & DATA_ERR_INT_MASK)
{ /* 數據錯誤中斷處理 */
MCI_DataErrorProcess();
MCIClear |= DATA_ERR_INT_MASK; /* 清除數據錯誤中斷位 */
}
else if (MCIStatus & DATA_INT_MASK)
{ /* 數據中斷處理 */
MCI_DataInterruptProcess();
//MCIClear |= DATA_INT_MASK;
}
else if (MCIStatus & FIFO_INT_MASK)
{
;
}
VICVectAddr = 0; /* 應答中斷控制器 */
}
/*************************
LPC23xx DMA 初始化函數
**************************/
#if LPC23xx_MCI_DMA_EN
/*******************************************************************************************************************
** 函數名稱: 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -