📄 sdcmd.c
字号:
#include "sdconfig.h"
#include "sdhal.h"
#include "sdcrc.h"
#include "sdcmd.h"
#include "sddriver.h"
#include <csl_gpio.h>
#include <csl_gpiohal.h>
#include <csl_stdinc.h>
extern Uint8 clk;
extern GPIO_Handle hGpio;
/********************************************************************************************************************
** 函数名称: INT8U SD_ResetSD() Name: INT8U SD_ResetSD()
** 功能描述: 复位SD卡 Function: reset sd card
** 输 入: 无 Input: NULL
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
Uint8 SD_ResetSD(void)
{
Uint8 param[4] = {0,0,0,0},resp;
return (SD_SendCmd(CMD0, param, CMD0_R, &resp)); /* 复位命令 command that reset sd card */
}
/********************************************************************************************************************
** 函数名称: void SD_SPIDelay() Name: void SD_SPIDelay()
** 功能描述: SPI总线延时 Function: SPI Bus delay
** 输 入: INT8U value: 延时值,不超过255 Input: INT8U value : delay value,do not beyond 255
** 输 出: 无 Output: NULL
*********************************************************************************************************************/
void SD_SPIDelay(Uint8 value)
{
Uint8 i;
for (i = 0; i < value; i++)
SPI_SendByte(0xFF); /* 发送0xFF clock out 0xFF */
}
/********************************************************************************************************************
** 函数名称: INT8U SD_SendCmd() Name: INT8U SD_SendCmd()
** 功能描述: 向卡发送命令,并取得响应 Function: send command to the card,and get a response
** 输 入: INT8U cmd : 命令字 Input: INT8U cmd : command byte
INT8U *param : 命令参数,长度为4字节 INT8U *param : command parameter,length is 4 bytes
INT8U resptype : 响应类型 INT8U resptype: response type
INT8U *resp : 响应,长度为1-5字节 INT8U *resp : response,length is 1-5 bytes
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
********************************************************************************************************************/
Uint8 SD_SendCmd(Uint8 cmd, Uint8 *param, Uint8 resptype, Uint8 *resp)
{
int i,rlen;
Uint8 tmp;
/**********************SPI_CS_Assert();*****************************/
GPIO_pinWrite(hGpio,GPIO_PIN3,0x0);
if(!clk)
EVMDM642_waitusec(10000);
else
EVMDM642_waitusec(5);
SPI_SendByte((cmd & 0x3F) | 0x40); /* 发送命令头和命令字 send command header and word */
for (i = 3; i >= 0; i--)
SPI_SendByte(param[i]); /* 发送参数 send parameters */
#if SD_CRC_EN
tmp = SD_GetCmdByte6((cmd & 0x3F) | 0x40, param);
SPI_SendByte(tmp);
#else
SPI_SendByte(0x95); /* CRC校验码,只用于第1个命令 CRC,only used for the first command */
#endif
//EVMDM642_waitusec(10);
rlen = 0;
switch (resptype) /* 根据不同的命令,得到不同的响应长度 */
{ /* according various command,get the various response length */
case R1:
case R1B: rlen = 1; break;
case R2: rlen = 2; break;
case R3: rlen = 5; break;
default: SPI_SendByte(0xFF);
GPIO_pinWrite(hGpio,GPIO_PIN3,0x1);
return SD_ERR_CMD_RESPTYPE; /* 返回命令响应类型错误 return error of command response type */
break;
}
i = 0;
do /* 等待响应,响应的开始位为0 */
{ /* Wait for a response,a response is a start bit(zero) */
tmp = SPI_RecByte();
i++;
}while (((tmp & 0x80) != 0) && (i < SD_CMD_TIMEOUT));
if (i >= SD_CMD_TIMEOUT)
{
GPIO_pinWrite(hGpio,GPIO_PIN3,0x1);
return SD_ERR_CMD_TIMEOUT; /* 返回命令超时 return response timeout of command */
}
for (i = rlen - 1; i >= 0; i--)
{
/*if(i = rlen - 1)
do
{*/
resp[i] = tmp;
tmp = SPI_RecByte(); /* 循环的最后发送8clock at the last recycle,clock out 8 clock */
}
GPIO_pinWrite(hGpio,GPIO_PIN3,0x1);
return SD_NO_ERR; /* 返回执行成功 return perform sucessfully */
}
/*********************************************************************************************************************
** 函数名称: INT8U SD_ReadOCR() Name: INT8U SD_ReadOCR()
** 功能描述: 读操作条件寄存器OCR Function: read OCR register of sd card
** 输 入: INT8U ocrlen : 寄存器长度(固定为4) Input: INT8U ocrlen : len of register (fixed,is 4)
INT8U *recbuf : 接收缓冲区 INT8U *recbuf : recbuffer
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
**********************************************************************************************************************/
Uint8 SD_ReadOCR(Uint8 ocrlen, Uint8 *recbuf)
{
Uint8 param[4] = {0,0,0,0},resp[5],tmp;
tmp = SD_SendCmd(CMD58, param, CMD58_R, resp); /* 读 OCR 寄存器命令 */
if (tmp != SD_NO_ERR) /* read OCR register command */
return tmp;
if (resp[0] != 0)
return SD_ERR_CMD_RESP; /* 响应错误 response is error */
for (tmp = 0; tmp < 4; tmp++)
recbuf[tmp] = resp[tmp + 1]; /* 复制OCR寄存器内容到接收缓冲区 */
return SD_NO_ERR;
}
/********************************************************************************************************************
** 函数名称: INT8U SD_EnableCRC() Name: INT8U SD_EnableCRC()
** 功能描述: 使能SD卡的CRC校验功能 Function: enable crc check of SD Card
** 输 入: INT8U bEnable : 1:使能 0:禁止 Input: INT8U bEnable : 1:enable 0: disable
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
#if SD_CRC_EN
Uint8 SD_EnableCRC(Uint8 bEnable)
{
Uint8 param[4],resp,ret;
if (bEnable == 1)
param[0] = 1; /* 使能crc enable crc */
else
param[1] = 0; /* 禁止crc disalbe crc */
// for(;;)
ret = SD_SendCmd(CMD59, param, CMD59_R, &resp); /* "使能/禁止CRC"命令 enable/disable crc command */
if (ret != SD_NO_ERR)
return ret;
if (resp != 0)
return SD_ERR_CMD_RESP; /* 响应错误 response is error */
return SD_NO_ERR;
}
#endif
/********************************************************************************************************************
** 函数名称: INT8U Sd_SetBlockLen() Name: INT8U Sd_SetBlockLen()
** 功能描述: 设置一个块的长度 Function: set a block len of sd card
** 输 入: INT32U length : 块的长度值 Input: INT32U length : the length of a block
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
Uint8 SD_SetBlockLen(Uint32 length)
{
Uint8 param[4],resp,ret;
SD_PackParam(param, length); /* 将参数转化为字节形式 change the parameter to bytes form */
ret = SD_SendCmd(CMD16, param, CMD16_R, &resp);
if (ret != SD_NO_ERR)
return ret; /* 设置块的长度为length失败 set the length of block to length fail */
if (resp != 0)
return SD_ERR_CMD_RESP; /* 响应错误 response is error */
return SD_NO_ERR; /* 返回执行成功 return perform sucessfully */
}
/********************************************************************************************************************
** 函数名称: void SD_PackParam() Name: void SD_PackParam()
** 功能描述: 将32位的参数转为字节形式 Function: change 32bit parameter to bytes form
** 输 入: INT8U *parameter: 字节参数缓冲区 Input: INT8U *parameter: the buffer of bytes parameter
INT32U value : 32位参数 INT32U value : 32bit parameter
** 输 出: 无 Output: NULL
*********************************************************************************************************************/
void SD_PackParam(Uint8 *parameter, Uint32 value)
{
parameter[3] = (Uint8)(value >> 24);
parameter[2] = (Uint8)(value >> 16);
parameter[1] = (Uint8)(value >> 8);
parameter[0] = (Uint8)(value);
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadCSD() Name: INT8U SD_ReadCSD()
** 功能描述: 读SD卡的CSD寄存器 Function: read CSD register of sd card
** 输 入: INT8U csdlen : 寄存器长度(固定为16) INT8U csdlen : len of register (fixed,is 16)
INT8U *recbuf : 接收缓冲区 INT8U *recbuf : recbuffer
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
Uint8 SD_ReadCSD(Uint8 csdlen, Uint8 *recbuf)
{
Uint8 param[4] = {0,0,0,0},resp,ret;
ret = SD_SendCmd(CMD9, param, CMD9_R, &resp); /* 读CSD寄存器命令 command that read CSD register */
if (ret != SD_NO_ERR)
return ret;
if (resp != 0)
return SD_ERR_CMD_RESP; /* 响应错误 response is error */
return (SD_ReadRegister(csdlen, recbuf));
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadRegister() Name: INT8U SD_ReadRegister()
** 功能描述: 从SD卡读取数据 Function: read data from SD card
** 输 入: INT32U len : 长度 Input: INT32U len : length
INT8U *recbuf: 接收缓冲区 INT8U *recbuf: receive buffer
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
Uint8 SD_ReadRegister(Uint32 len, Uint8 *recbuf)
{
Uint32 i = 0;
Uint8 resp;
GPIO_pinWrite(hGpio,GPIO_PIN3,0x0);
do{ /* 等待数据起始令牌 wait for data start token */
resp = SPI_RecByte();
i++;
}while((resp == 0xFF) && (i < SD_READREG_TIMEOUT));
if (i >= SD_READREG_TIMEOUT)
{
GPIO_pinWrite(hGpio,GPIO_PIN3,0x1);
return SD_ERR_TIMEOUT_READ; /* 超时, 返回错误 timeout, return error */
}
if (resp != SD_TOK_READ_STARTBLOCK)
{ /* 不是收到数据起始令牌 not receive data start token */
recbuf[0] = resp;
i = 1; /* 还有len - 1个字节要接收 still len - 1 bytes will be received */
}
else
i = 0; /* 收到数据起始令牌,还有len个字节要接收 received data start token,still len bytes will be received */
for (; i < len; i++)
recbuf[i] = SPI_RecByte(); /* 接收数据 receive data */
i = SPI_RecByte();
i = (i << 8) + SPI_RecByte(); /* 读取16位CRC get 16-bit CRC */
#if SD_CRC_EN
if (i != SD_GetCRC16(recbuf, len))
{ /* CRC校验错误 CRC check is error */
GPIO_pinWrite(hGpio,GPIO_PIN3,0x1);
SPI_SendByte(0xFF);
return SD_ERR_DATA_CRC16; /* 返回RCR16错误 return error of CRC16 */
}
#endif
SPI_SendByte(0xFF); /* 返回之前发送8个clock clock out 8 clk before return */
GPIO_pinWrite(hGpio,GPIO_PIN3,0x1);
return SD_NO_ERR;
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadSingleBlock() Name: INT8U SD_ReadSingleBlock()
** 功能描述: 读单块命令 Function: read single block command
** 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: block address
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
Uint8 SD_ReadSingleBlock(Uint32 blockaddr)
{
return (SD_BlockCommand(CMD17, CMD17_R, blockaddr)); /* 读单块命令 command that read single block */
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadMultipleBlock() Name: INT8U SD_ReadMultipleBlock()
** 功能描述: 读多块命令 Function: read multiple block command
** 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: block address
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
Uint8 SD_ReadMultipleBlock(Uint32 blockaddr)
{
return (SD_BlockCommand(CMD18, CMD18_R, blockaddr)); /* 读多块命令 command that read multiple block */
}
/********************************************************************************************************************
** 函数名称: INT8U SD_WriteSingleBlock() Name: INT8U SD_WriteSingleBlock()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -