📄 sdhal.c
字号:
{
if (SD_INSERT_STATUS() != 0)
return 0; /* 未完全插入 */
else
return 1; /* 完全插入 */
}
/*******************************************************************************************************************
** 函数名称: SdHal_CheckCardWP()
**
** 功能描述: 检测卡写保护
**
** 输 入: sd_struct *sds: 卡信息结构体
**
** 输 出: 1: 卡已写保护 0: 卡未写保护
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_CheckCardWP(sd_struct *sds)
{
if (SD_WP_STATUS() != 0)
return 1; /* 写保护 */
else
return 0; /* 未写保护 */
}
/*******************************************************************************************************************
** 函数名称: SdHal_BeforeReadBlock()
**
** 功能描述: 在发送读单块命令之前, 给硬件控制器做一些事情的机会
**
** 输 入: sd_struct *sds : 卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_BeforeReadBlock(sd_struct *sds)
{
MCIMask0 |= (DATA_RX_INT_MASK) | (FIFO_INT_MASK); /* 仅使能接收中断 */
MCIMask1 = MCIMask0;
MCIClear = 0x7FF; /* 清空清零寄存器的所有标志 */
MCIDataCtrl = 0; /* 数据控制寄存器清0 */
MCIDataTimer = sds->timeout_read; /* 超时值 */
MCIDataLength = SD_BLOCKSIZE; /* 块长度 */
MCIFifoCnt = 0;
lpc_mci.RecCnt = 0;
lpc_mci.RxTxFlag = MCI_RESET_FLAG;
lpc_mci.psds = sds;
lpc_mci.CurTran = MCI_CUR_REC;
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: SdHal_ReadBlock()
**
** 功能描述: 在发送读单块命令之后, 由硬件控制器实现读取数据
**
** 输 入: sd_struct *sds : 卡信息结构体
**
** 输 出: INT8U *recbuf: 接收缓冲区, 大小为512字节
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_ReadBlock(sd_struct *sds, INT8U *recbuf)
{
INT32U DataCtrl = 0;
INT8U ret;
lpc_mci.pRecBuf = recbuf;
#if MCI_DMA_ENABLED
// DMA 控制器初始化
DMA_Init(1, P2M);
DMACC1Configuration |= 0x10001 | (0x04 << 1) | (0x00 << 6) | (0x06 << 11);
// 设置数据控制寄存器: 读,块传输,DMA传输,块长度
DataCtrl |= ((1 << 0) | (1 << 1) | (1 << 3) | (SD_BLOCKSIZE_NBITS << 4));
#else
// 设置数据控制寄存器: 读,块传输,块长度
DataCtrl |= ((1 << 0) | (1 << 1) | (SD_BLOCKSIZE_NBITS << 4));
#endif
#if SD_UCOSII_EN
OS_ENTER_CRITICAL();
MCIDataCtrl = DataCtrl; /* 启动数据传输 */
OSSemPend(sds->pSemSdmmcRW, sds->timeout_read_os, &ret); /* 进入等待状态 */
if (ret == OS_NO_ERR)
ret = lpc_mci.RxTxFlag; /* 返回数据接收结果 */
else if (ret == OS_TIMEOUT)
ret = SD_ERR_TIMEOUT_READ; /* 接收数据超时 */
else
ret = SD_ERR_WAIT_WRSEM; /* 等待信号量失败 */
OS_EXIT_CRITICAL();
#else
MCIDataCtrl = DataCtrl; /* 启动数据传输 */
do
{ /* 等待数据接收 */
if (lpc_mci.RxTxFlag == SD_NO_ERR)
break; /* 数据接收成功 */
}while (lpc_mci.RxTxFlag == MCI_RESET_FLAG);
ret = lpc_mci.RxTxFlag; /* 返回接收结果 */
#endif
MCIMask0 &= ~((DATA_RX_INT_MASK) | (FIFO_INT_MASK)); /* 仅禁止接收中断 */
MCIMask1 = MCIMask0;
#if MCI_DMA_ENABLED
src_addr = (INT32U *)DMA_SRC; /* 取得 DMA 源地址 */
dest_addr = (INT32U *)DMA_DST; /* 取得 DMA 目标地址 */
if (ret == SD_NO_ERR)
memcpy(recbuf, dest_addr, 512); /* 返回接收到的数据 */
#endif
return ret;
}
/*******************************************************************************************************************
** 函数名称: SdHal_BeforeWriteBlock()
**
** 功能描述: 在发送写单块命令之前, 给硬件控制器做一些事情的机会
**
** 输 入: 无
**
** 输 出: INT8U *recbuf: 接收缓冲区, 大小为512字节
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_BeforeWriteBlock(sd_struct *sds)
{
MCIMask0 = DATA_TX_INT_MASK | (FIFO_INT_MASK); /* 仅使能TX中断 */
MCIMask1 = MCIMask0;
MCIClear = 0x7FF; /* 清空清零寄存器的所有标志 */
MCIDataCtrl = 0; /* 数据控制寄存器清0 */
MCIDataTimer = sds->timeout_write; /* 超时值 */
MCIDataLength = SD_BLOCKSIZE; /* 块长度 */
MCIFifoCnt = 0;
lpc_mci.psds = sds; /* 初始化lpc_mci结构体变量 */
lpc_mci.RxTxFlag = MCI_RESET_FLAG;
lpc_mci.SendCnt = 0;
lpc_mci.CurTran = MCI_CUR_SEND;
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: SdHal_WriteBlock()
**
** 功能描述: 在发送写单块命令之后, 由硬件控制器向卡发送数据
**
** 输 入: 无
**
** 输 出: INT8U *recbuf: 接收缓冲区, 大小为512字节
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_WriteBlock(sd_struct *sds, INT8U *sendbuf)
{
INT32U DataCtrl = 0;
INT8U ret;
#if MCI_DMA_ENABLED
src_addr = (INT32U *)DMA_SRC;
dest_addr = (INT32U *)DMA_DST;
//memcpy(sendbuf, src_addr, 512);
memcpy(src_addr, sendbuf, 512); /* 复制要写入的数据到DMA源地址 */
DMA_Init(0, M2P); /* DMA控制器初始化 */
DMACC0Configuration |= 0x00001 | (0x00 << 1) | (0x04 << 6) | (0x05 << 11);
/* 设置数据控制寄存器: 写, 块传输, DMA, 数据长度 */
DataCtrl |= ((1 << 0) | (1 << 3) | (SD_BLOCKSIZE_NBITS << 4));
#else
lpc_mci.pSendBuf = sendbuf;
/* 设置数据控制寄存器: 读, 块传输, 数据长度 */
DataCtrl |= ((1 << 0) | (SD_BLOCKSIZE_NBITS << 4));
#endif
#if SD_UCOSII_EN
OS_ENTER_CRITICAL();
MCIDataCtrl = DataCtrl; /* 启动数据传输 */
OSSemPend(sds->pSemSdmmcRW, sds->timeout_write_os, &ret); /* 进入等待状态 */
if (ret == OS_NO_ERR)
ret = lpc_mci.RxTxFlag; /* 返回写块数据结果 */
else if (ret == OS_TIMEOUT)
ret = SD_ERR_TIMEOUT_WRITE; /* 返回等待超时 */
else
ret = SD_ERR_WAIT_WRSEM; /* OSSemPend()执行失败 */
OS_EXIT_CRITICAL();
#else
MCIDataCtrl = DataCtrl; /* 启动数据传输 */
do
{
if (lpc_mci.RxTxFlag == SD_NO_ERR)
break; /* 发送数据成功 */
}while (lpc_mci.RxTxFlag == MCI_RESET_FLAG);
ret = lpc_mci.RxTxFlag; /* 返回发送数据执行结果 */
#endif
MCIMask0 &= ~(DATA_TX_INT_MASK | FIFO_INT_MASK); /* 仅禁止TX中断 */
MCIMask1 = MCIMask0;
return ret;
}
/*******************************************************************************************************************
** 函数名称: SDMMC_WaitReadyforData()
**
** 功能描述: 等待卡可接收数据, 即等待卡状态寄存器的 bit8 为1, 大约为2次循环
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_WaitReadyforData(sd_struct *sds)
{
INT8U ret;
INT32U status;
do
{
ret = SdCmd_Send_Status(sds, &status); /* 读取卡的状态 */
if (ret != SD_NO_ERR)
return ret;
if (!SdHal_CheckCard(sds)) /* 检测卡是否拔出 */
return SD_ERR_NO_CARD;
}while((status & CARD_STATUS_RDY_DATA) == 0);
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: SdHal_WaitBusy()
**
** 功能描述: 等待卡编程结束, 即等待卡状态由编程状态变为传输状态: prg --> tran
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_WaitBusy(sd_struct *sds)
{
INT8U ret;
INT32U status;
do
{
ret = SdCmd_Send_Status(sds, &status); /* 读取卡的状态 */
if (ret != SD_NO_ERR)
return ret;
if (!SdHal_CheckCard(sds)) /* 检测卡是否拔出 */
return SD_ERR_NO_CARD;
}while((status & 0x1F00) != 0x900);
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: MCI_Delay()
**
** 功能描述: 延时函数
**
** 输 入: INT16U val: 延时值, 1大约相当于5ms
**
** 输 出: 无
**
** 返 回 值: 无
********************************************************************************************************************/
void MCI_Delay(INT16U val)
{
#if !SD_UCOSII_EN
INT16U i,j;
for (i = 0; i < val; i++)
for (j = 0; j < 0xC000; j++);
#else
OSTimeDly(val);
#endif
}
/*******************************************************************************************************************
** 函数名称: MCI_SendCmd()
**
** 功能描述: 发送命令给卡, 但不获取响应
**
** 输 入: INT32U CmdIndex : 命令索引
** INT32U Argument : 命令参数
** INT32U ExpectResp : 期望得到的回复
** INT32U AllowTimeout: 是否允许超时
**
** 输 出: 无
**
** 返 回 值: 无
********************************************************************************************************************/
void MCI_SendCmd(INT32U CmdIndex, INT32U Argument, INT32U ExpectResp, INT32U AllowTimeout)
{
INT32U CmdData = 0, i;
INT32U CmdStatus;
while ((CmdStatus = MCIStatus) & MCI_CMD_ACTIVE) /* 命令正在处理中 */
{
MCICommand = 0;
MCIClear = CmdStatus | MCI_CMD_ACTIVE; /* 清除相关状态 */
for(i = 0; i < 0x20; i++);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -