📄 sddriver.c
字号:
/*
*****************************************************************************************************************************************************
本软件包的 SPI 总线模式, 适用于LPC21xx, LPC22xx 微控制器
*****************************************************************************************************************************************************
*/
#if (!SDBUS_MODE_EN)
/*******************************************************************************************************************
** 函数名称: INT8U SD_Initialize() Name: INT8U SD_Initialize()
** 功能描述: 初始化SD/MMC卡 Function: initialize SD/MMC card
** 输 入: 无 Input: NULL
** 输 出: 0: 成功 >0: 错误码 Output: 0: right >0: error code
********************************************************************************************************************/
INT8U SD_Initialize(sd_struct *sds)
{
INT8U recbuf[4],ret;
#if SD_UCOSII_EN
if (sds->pSemSD == NULL)
{
sds->pSemSD = OSSemCreate(1); /* 创建访问SD/MMC卡信号量 create SD/MMC semaphore */
if (sds->pSemSD == NULL)
return SD_ERR_CREATE_SEMSD;
}
#endif
SD_RequestOSSem(sds);
SdHal_Initialize(sds); /* 初始化读写SD卡的硬件条件 Initialize the hardware that access SD Card */
if (!SdHal_CheckCard(sds)) /* 检查卡是否插入 check weather card is inserted */
{
ret = SD_ERR_NO_CARD;
goto SD_ERR;
}
SdHal_SPI_CSAssert(sds); /* 1. 置CS为低 assert CS */
SdHal_SPIDelay(sds, 25); /* 2. 至少延时 74 clock delay more than 74 clock */
SdHal_SPI_CSDeassert(sds); /* 3. 置CS为高 dessert CS */
SdHal_SPIDelay(sds, 2); /* 4. 延时2(8 clock) delay 2(8 clock) */
ret = SD_ResetSD(sds); /* 5. 发出CMDO命令复位SD卡 send CMD0 command to reset sd card */
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SD_ActiveInit(sds); /* 6. 激活卡进入初始化过程. active card initialize process */
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SD_ReadOCR(sds, 4, recbuf); /* 7. 读OCR寄存器,查询卡支持的电压值 read OCR register,get the supported voltage */
if (ret != SD_NO_ERR)
goto SD_ERR;
if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
{
ret = SD_ERR_VOL_NOTSUSP; /* 不支持3.3V,返回错误码 not support 3.3V,return error code */
goto SD_ERR;
}
SdHal_SetMCIClock(sds, SD_RATE_NORMAL); /* 8. 设置访问卡的clock为标准clock */
#if SD_CRC_EN
ret = SD_EnableCRC(sds, 1); /* 使能CRC校验 enable CRC check */
if (ret != SD_NO_ERR)
goto SD_ERR;
#endif
ret = SD_SetBlockLen(sds, SD_BLOCKSIZE); /* 9. 设置块的长度: 512Bytes Set the block length: 512Bytes */
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SDMMC_GetCardInfo(sds); /* 10. 读CSD寄存器,获取SD卡信息 read CSD register, get the information of SD card */
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SDMMC_CalTimeout(sds); /* 计算超时时间值 */
if (ret != SD_NO_ERR)
goto SD_ERR;
SD_ReleaseOSSem(sds);
return SD_NO_ERR; /* 初始化成功 initialize sucessfully */
SD_ERR:
SD_ReleaseOSSem(sds);
return ret;
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadBlock() Name: INT8U SD_ReadBlock()
** 功能描述: 从SD/MMC卡中读一个块 Function: read a single block from SD/MMC card
** 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: address of block
INT8U *recbuf : 接收缓冲区,长度512Bytes INT8U *recbuf : the buffer of receive,length is 512Bytes
** 输 出: 0: 成功 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
INT8U SD_ReadBlock(sd_struct *sds, INT32U blockaddr, INT8U *recbuf)
{
INT8U ret;
SD_RequestOSSem(sds); /* 向OS申请访问卡信号量 request semaphore acessed SD/MMC to OS */
if (!SdHal_CheckCard(sds))
{
SD_ReleaseOSSem(sds);
return SD_ERR_NO_CARD; /* 卡没完全插入卡中 card is not inserted entirely */
}
if (blockaddr > sds->block_num)
{
SD_ReleaseOSSem(sds);
return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
}
ret = SD_ReadSingleBlock(sds, blockaddr); /* 读单块命令 read single blocks command */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
ret = SdHal_ReadBlockData(sds, SD_BLOCKSIZE, recbuf); /* 读出数据 read data from sd card */
SD_ReleaseOSSem(sds); /* 归还访问卡信号量 return semaphore acessed SD/MMC to OS */
return ret;
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadMultiBlock() Name: INT8U SD_ReadMultiBlock()
** 功能描述: 从SD/MMC卡中读多个块 Function: read multi blocks from SD/MMC card
** 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: address of block
INT32U blocknum : 块数量 INT32U blocknum : the numbers of block
INT8U *recbuf : 接收缓冲区,每块512字节 INT8U *recbuf : the buffer of receive,each block length is 512Bytes
** 输 出: 0: 成功 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
#if SD_ReadMultiBlock_EN
INT8U SD_ReadMultiBlock(sd_struct *sds, INT32U blockaddr, INT32U blocknum, INT8U *recbuf)
{
INT32U i;
INT8U ret;
SD_RequestOSSem(sds); /* 向OS申请访问卡信号量 request semaphore acessed SD/MMC to OS */
if (!SdHal_CheckCard(sds))
{
SD_ReleaseOSSem(sds);
return SD_ERR_NO_CARD; /* 卡没完全插入卡中 card is not inserted entirely */
}
if ((blockaddr + blocknum) > sds->block_num)
{
SD_ReleaseOSSem(sds);
return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
}
ret = SD_ReadMultipleBlock(sds, blockaddr); /* 读多块命令 read multiple blocks command */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds); /* 归还访问卡信号量 return semaphore acessed SD/MMC to OS */
return ret;
}
for (i = 0; i < blocknum; i++)
{ /* 读出数据 read data from SD/MMC card */
ret = SdHal_ReadBlockData(sds, SD_BLOCKSIZE, recbuf);
if (ret == SD_NO_ERR)
recbuf = recbuf + SD_BLOCKSIZE;
else
{
SD_ReleaseOSSem(sds);
return ret;
}
}
ret = SD_StopTransmission(sds); /* 结束数据传输 stop transmission operation */
SD_ReleaseOSSem(sds);
return ret;
}
#endif
/********************************************************************************************************************
** 函数名称: INT8U SD_WriteBlock() Name: INT8U SD_WriteBlock()
** 功能描述: 向SD/MMC卡中写入一个块 Function: write a block to SD/MMC card
** 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: address of block
INT8U *sendbuf : 发送缓冲区,长度512Bytes INT8U *sendbuf : the buffer of send,length is 512Bytes
** 输 出: 0: 成功 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
INT8U SD_WriteBlock(sd_struct *sds, INT32U blockaddr, INT8U *sendbuf)
{
INT8U ret,tmp[2];
SD_RequestOSSem(sds); /* 向OS申请访问卡信号量 request semaphore acessed SD/MMC to OS */
if (!SdHal_CheckCard(sds))
{
SD_ReleaseOSSem(sds);
return SD_ERR_NO_CARD; /* 卡没完全插入卡中 card is not inserted entirely */
}
if (blockaddr > sds->block_num)
{
SD_ReleaseOSSem(sds);
return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
}
if (SdHal_CheckCardWP(sds))
{
SD_ReleaseOSSem(sds);
return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
}
ret = SD_WriteSingleBlock(sds, blockaddr); /* 写单块命令 write single block */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
ret = SdHal_WriteBlockData(sds, 0, SD_BLOCKSIZE, sendbuf); /* 写入数据 write data */
if (ret == SD_NO_ERR) /* 读Card Status寄存器, 检查写入是否成功 */
{ /* read Card Status register to check write wheather sucessfully */
ret = SD_ReadCard_Status(sds, 2, tmp);
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret; /* 读寄存器失败 read register fail */
}
if((tmp[0] != 0) || (tmp[1] != 0))
{
SD_ReleaseOSSem(sds);
ret = SD_ERR_WRITE_BLK; /* 响应指示写失败 response indicate write fail */
}
}
SD_ReleaseOSSem(sds);
return ret; /* 返回写入结果 return the result of writing */
}
/**********************************************************************************************************************
** 函数名称: INT8U SD_WriteMultiBlock() Name: INT8U SD_WriteMultiBlock()
** 功能描述: 向SD/MMC卡中写入多个块 Function: write multi blocks to SD/MMC card
** 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: address of block
INT32U blocknum : 块数量 INT32U blocknum : the numbers of block
INT8U *sendbuf : 发送缓冲区每块512字节 INT8U *sendbuf : the send buffer,each block length is 512Bytes
** 输 出: 0: 成功 >0: 错误码 Output: 0: right >0: error code
***********************************************************************************************************************/
#if SD_WriteMultiBlock_EN
INT8U SD_WriteMultiBlock(sd_struct *sds, INT32U blockaddr, INT32U blocknum, INT8U *sendbuf)
{
INT32U i;
INT8U ret,tmp[2];
SD_RequestOSSem(sds); /* 向OS申请访问卡信号量 request semaphore acessed SD/MMC to OS */
if (!SdHal_CheckCard(sds))
{
SD_ReleaseOSSem(sds);
return SD_ERR_NO_CARD; /* 卡没完全插入卡中 card is not inserted entirely */
}
if ((blockaddr + blocknum) > sds->block_num)
{
SD_ReleaseOSSem(sds);
return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
}
if (SdHal_CheckCardWP(sds))
{
SD_ReleaseOSSem(sds);
return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
}
ret = SD_WriteMultipleBlock(sds, blockaddr); /* 写多块命令 write multiple blocks command */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
for (i = 0; i < blocknum; i++)
{
ret = SdHal_WriteBlockData(sds, 1, SD_BLOCKSIZE, sendbuf); /* 写入数据 write data */
if (ret == SD_NO_ERR)
sendbuf = sendbuf + SD_BLOCKSIZE;
else
{ /* 写失败 write fail */
SD_StopTransmission(sds); /* 停止数据传输 stop data transmission */
SdHal_WaitBusy(sds, SD_WAIT_WRITE); /* 等待 waiting */
SD_ReleaseOSSem(sds);
return ret;
}
}
SdHal_StopMultiToken(sds); /* 发送数据停止令牌 send data stop token */
ret = SdHal_WaitBusy(sds, SD_WAIT_WRITE); /* 等待写入的完成 wait for finishing writing */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return SD_ERR_TIMEOUT_WRITE;
}
if (sds->card_type == CARDTYPE_SD)
{
ret = SD_GetNumWRBlcoks(sds, &i); /* 读正确写入的块数 read the blocks that be written correctly */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
if(i != blocknum)
ret = SD_ERR_WRITE_BLKNUMS; /* 正确写入块数错误 the blocks that be written correctly is error */
}
else
{
ret = SD_ReadCard_Status(sds, 2, tmp);
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret; /* 读寄存器失败 read register fail */
}
if((tmp[0] != 0) || (tmp[1] != 0))
ret = SD_ERR_WRITE_BLK; /* 响应指示写失败 response indicate write fail */
}
SD_ReleaseOSSem(sds);
return ret; /* 返回写入成功 return write sucessfully */
}
#endif
/*****************************************************************
下面为子程序
*****************************************************************/
/*******************************************************************************************************************
** 函数名称: INT8U SD_ActiveInit() Name: INT8U SD_ActiveInit()
** 功能描述: 激活卡,并获得卡型 Function: active card, and get the card type
** 输 入: 无 Input: NULL
** 输 出: 0: 成功 >0: 错误码 Output: 0: right >0: error code
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
INT8U SD_ActiveInit(sd_struct *sds)
{
INT8U param[4] = {0,0,0,0},resp[5],ret;
INT32U i = 0;
do
{ /* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */
ret = SdHal_SendCmd(sds, CMD1, param, CMD1_R, resp);
if (ret != SD_NO_ERR)
return ret;
i ++;
}while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i <= SD_IDLE_WAIT_MAX));
/* 如果响应R1的最低位Idle位为1,则继续循环 */
/* if response R1 Idle bit is 1,continue recycle */
if (i >= SD_IDLE_WAIT_MAX)
return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误 time out,return error */
ret = SdHal_SendCmd(sds, CMD55, param, CMD55_R, resp);
if (ret != SD_NO_ERR)
return ret;
ret = SdHal_SendCmd(sds, ACMD41, param, ACMD41_R, resp); /* 激活内部初始化命令 active card to initialize process internal */
if (ret != SD_NO_ERR)
return SD_ERR_UNKNOWN_CARD;
if ((resp[0] & 0xFE) == 0)
sds->card_type = CARDTYPE_SD; /* 是SD卡 the card is SD card */
else
sds->card_type = CARDTYPE_MMC; /* 是MMC卡 the card is MMC card */
return SD_NO_ERR;
}
#endif //end of #if (!SDBUS_MODE_EN)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -