📄 sdhal.c
字号:
CmdData |= (CmdIndex & 0x3F); /* 命令索引只有bit0 ~ bit5 有效 */
if (ExpectResp == EXPECT_NO_RESP) /* 无响应类型 */
{
CmdData &= ~((1 << 6) | (1 << 7)); /* 清除短响应和长响应位 */
}
else if (ExpectResp == EXPECT_SHORT_RESP) /* 希望得到短响应 */
{
CmdData |= (1 << 6);
}
else if (ExpectResp == EXPECT_LONG_RESP) /* 希望得到长响应 */
{
CmdData |= (1 << 6) | (1 << 7);
}
if (AllowTimeout) /* 是否允许超时中断 */
CmdData |= (1 << 8);
else
CmdData &= ~(1 << 8);
CmdData |= (1 << 10); /* 使能发送命令 */
MCIArgument = Argument; /* 命令参数 */
MCICommand = CmdData; /* 启动命令发送 */
}
/*******************************************************************************************************************
** 函数名称: MCI_GetCmdResp()
**
** 功能描述: 从卡获取响应, 该函数与MCI_SendCmd()成对使用
**
** 输 入: INT32U ExpectCmdData: SD/MMC 命令码
** INT32U ExpectResp : 希望的响应, 取值为: EXPECT_NO_RESP, EXPECT_SHORT_RESP, EXPECT_LONG_RESP
** INT8U resplen : 响应长度
**
**
** 输 出: INT32U *CmdResp : 响应内容, 长度为resplen
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U MCI_GetCmdResp(INT32U ExpectCmdData, INT32U ExpectResp, INT8U resplen, INT32U *CmdResp)
{
INT32U LastCmdIndex;
INT32U CmdRespStatus = 0;
while (1)
{ /* 不断循环等待卡的响应 */
CmdRespStatus = MCIStatus;
if (CmdRespStatus & (MCI_CMD_TIMEOUT))
{ /* 超时错误, 超时周期固定为64个MCICLK时钟周期 */
MCIClear = CmdRespStatus | MCI_CMD_TIMEOUT;
MCICommand = 0; /* 清空命令寄存器及参数寄存器 */
MCIArgument = 0xFFFFFFFF;
return SD_ERR_CMD_TIMEOUT; /* 返回响应命令超时错误 */
}
if (CmdRespStatus & MCI_CMD_CRC_FAIL)
{ /* CRC校验失败错误 */
MCIClear = CmdRespStatus | MCI_CMD_CRC_FAIL;
LastCmdIndex = MCICommand & 0x003F;
if ((LastCmdIndex == SEND_OP_COND) || (LastCmdIndex == SEND_APP_OP_COND)
|| (LastCmdIndex == STOP_TRANSMISSION))
{ /* 忽略命令 SEND_OP_COND和STOP_TRANSMISSION的CRC校验 */
MCICommand = 0;
MCIArgument = 0xFFFFFFFF;
break;
}
else
return SD_ERR_CMD_RESPCRC; /* 返回响应命令CRC校验失败错误 */
}
else if (CmdRespStatus & MCI_CMD_RESP_END)
{
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 MCI_DMA_ENABLED
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;
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 (!(MCIStatus & MCI_RX_DATA_AVAIL));
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 !MCI_DMA_ENABLED
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
__irq __arm void 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; /* 应答中断控制器 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -