📄 sddriver.c
字号:
INT8U SdSpi_ActiveInit(sd_struct *sds);
/*******************************************************************************************************************
** 函数名称: SD_Initialize()
**
** 功能描述: SD/MMC 卡初始化: 复位卡,识别卡,获取卡相关信息,使卡进入数据传输模式
**
** 输 入: sd_struct *sds: SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SD_Initialize(sd_struct *sds)
{
INT32U ocr;
INT8U 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);
SdSpiHal_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;
}
SdSpiHal_CSAssert(sds); /* 1. 置CS为低 assert CS */
SdSpi_Delay(sds, 25); /* 2. 至少延时 74 clock delay more than 74 clock */
SdSpiHal_CSDeassert(sds); /* 3. 置CS为高 dessert CS */
SdSpi_Delay(sds, 2); /* 4. 延时2(8 clock) delay 2(8 clock) */
ret = SpiCmd_Go_Idle_State(sds); /* 5. 发出CMDO命令复位SD卡 send CMD0 command to reset sd card */
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SdSpi_ActiveInit(sds); /* 6. 激活卡进入初始化过程. active card initialize process */
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SpiCmd_ReadOCR(sds, &ocr); /* 7. 读OCR寄存器,查询卡支持的电压值 read OCR register,get the supported voltage */
if (ret != SD_NO_ERR)
goto SD_ERR;
if ((ocr & MSK_OCR_33) != MSK_OCR_33)
{
ret = SD_ERR_VOL_NOTSUSP; /* 不支持3.3V,返回错误码 not support 3.3V,return error code */
goto SD_ERR;
}
SdSpiHal_SetMCIClock(sds, SD_RATE_NORMAL); /* 8. 设置访问卡的clock为标准clock */
#if SD_CRC_EN
ret = SpiCmd_CRC_ON_OFF(sds, 1); /* 使能CRC校验 enable CRC check */
#else
ret = SpiCmd_CRC_ON_OFF(sds, 0); /* 禁止CRC校验 disable CRC check */
#endif
if (ret != SD_NO_ERR)
goto SD_ERR;
ret = SpiCmd_Set_BlockLen(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;
}
/*******************************************************************************************************************
** 函数名称: SD_ReadBlock()
**
** 功能描述: SPI模式下, 从SD/MMC卡中读出一个数据块
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT32U blockaddr: 以块为单位的块地址, 例如, 卡开始的0 ~ 511字节为块地址0, 512 ~ 1023字节的块地址为1
**
** 输 出: INT8U *recbuf : 接收缓冲区,长度固定为 512 字节
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
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 = SpiCmd_Read_Single_Block(sds, blockaddr); /* 读单块命令 read single blocks command */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
ret = SdSpi_ReadBlockData(sds, SD_BLOCKSIZE, recbuf); /* 读出数据 read data from sd card */
SD_ReleaseOSSem(sds); /* 归还访问卡信号量 return semaphore acessed SD/MMC to OS */
return ret;
}
/*******************************************************************************************************************
** 函数名称: SD_ReadMultiBlock()
**
** 功能描述: SPI模式下, 从SD/MMC卡中读出多个数据块
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT32U blockaddr: 以块为单位的块地址
** INT32U blocknum : 要读取的块的个数
**
** 输 出: INT8U *recbuf : 接收缓冲区, 长度512 * blocknum 字节
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
#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 = SpiCmd_Read_Multiple_Block(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 = SdSpi_ReadBlockData(sds, SD_BLOCKSIZE, recbuf);
if (ret == SD_NO_ERR)
recbuf = recbuf + SD_BLOCKSIZE;
else
{
SD_ReleaseOSSem(sds);
return ret;
}
}
ret = SpiCmd_Stop_Transmission(sds); /* 结束数据传输 stop transmission operation */
SD_ReleaseOSSem(sds);
return ret;
}
#endif
/*******************************************************************************************************************
** 函数名称: SD_WriteBlock()
**
** 功能描述: SPI模式下, 向SD/MMC卡中写入一个块
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT32U blockaddr: 以块为单位的块地址, 例如, 卡开始的0 ~ 511字节为块地址0, 512 ~ 1023字节的块地址为1
** INT8U *sendbuf : 发送缓冲区,长度固定为 512 字节
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
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 = SpiCmd_Write_Single_Block(sds, blockaddr); /* 写单块命令 write single block */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
ret = SdSpi_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 = SpiCmd_Send_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 */
}
/*******************************************************************************************************************
** 函数名称: SD_WriteMultiBlock()
**
** 功能描述: SPI模式下, 向SD/MMC卡中写入多个数据块
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT32U blockaddr: 以块为单位的块地址
** INT32U blocknum : 要写入的块的个数
** INT8U *sendbuf : 发送缓冲区, 长度 512 * blocknum 字节
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
#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 = SpiCmd_Write_Multiple_Block(sds, blockaddr); /* 写多块命令 write multiple blocks command */
if (ret != SD_NO_ERR)
{
SD_ReleaseOSSem(sds);
return ret;
}
for (i = 0; i < blocknum; i++)
{
ret = SdSpi_WriteBlockData(sds, 1, SD_BLOCKSIZE, sendbuf); /* 写入数据 write data */
if (ret == SD_NO_ERR)
sendbuf = sendbuf + SD_BLOCKSIZE;
else
{ /* 写失败 write fail */
SpiCmd_Stop_Transmission(sds); /* 停止数据传输 stop data transmission */
SdSpi_WaitBusy(sds, SD_WAIT_WRITE); /* 等待 waiting */
SD_ReleaseOSSem(sds);
return ret;
}
}
SdSpi_StopMultiToken(sds); /* 发送数据停止令牌 send data stop token */
ret = SdSpi_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 = SpiCmd_Send_Num_WR_Blcoks(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 = SpiCmd_Send_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
/*****************************************************************
下面为子程序
*****************************************************************/
/*******************************************************************************************************************
** 函数名称: SdSpi_ActiveInit()
**
** 功能描述: SPI模式下, 激活卡,并获得卡型
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 函数说明: SpiCmd_Send_OP_Cond()不断重复发送CMD0到卡,直到响应R1的Bit0(Idle)位为0,表示卡内部初始化处理完成。
当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
最大次数为宏定义SD_IDLE_WAIT_MAX.
********************************************************************************************************************/
INT8U SdSpi_ActiveInit(sd_struct *sds)
{
INT8U param[4] = {0,0,0,0},resp[5],ret;
ret = SpiCmd_Send_OP_Cond(sds); /* 激活卡进入初始化过程, 使卡退出Idle状态 */
if (ret != SD_NO_ERR)
return ret;
ret = SdSpi_SendCmd(sds, CMD55, param, CMD55_R, resp);
if (ret != SD_NO_ERR)
return ret;
ret = SdSpi_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 + -