📄 sdhal.c
字号:
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 LPC24xx_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 == 0) || ((Status & MCI_RX_OVERRUN) != 0))
{ /* 判断是否发生FIFO下溢错误 */
MCIDataCtrl = 0;
MCIClear = 0x7FF;
MCIMask0 = 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 !LPC24xx_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; /* 应答中断控制器 */
}
/*************************
LPC24xx DMA 初始化函数
**************************/
#if LPC24xx_MCI_DMA_EN
/*******************************************************************************************************************
** 函数名称: DMA_Init()
**
** 功能描述: LPC24xx 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 + -