⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdcmd.c

📁 SmartARM2400系列开发板全套资料
💻 C
📖 第 1 页 / 共 5 页
字号:
********************************************************************************************************************/
#if SD_CRC_EN
INT8U SpiCmd_CRC_ON_OFF(sd_struct *sds, INT8U bEnable)
{
	INT8U param[4],resp,ret;
		
	if (bEnable == 1)
		param[0] = 1;											/* 使能crc enable crc */
	else
		param[0] = 0; 											/* 禁止crc disalbe crc */

	ret = SdSpi_SendCmd(sds, 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


/********
  ACMD13
*********/
/*******************************************************************************************************************
** 函数名称: SpiCmd_ReadSD_Status()				
**
** 功能描述: 读SD卡的SD Status 寄存器(MMC卡没有该命令)
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**           INT8U sdslen  	  : 寄存器长度(固定为64) 
**
** 输   出: INT8U *recbuf 	  : 接收缓冲区
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: 只有SD卡才有SD Status 寄存器
********************************************************************************************************************/
INT8U SpiCmd_ReadSD_Status(sd_struct *sds, INT8U sdslen, INT8U *recbuf)
{
    INT8U param[4] = {0,0,0,0},resp[2],ret;
    
    ret = SdSpi_SendCmd(sds, CMD55, param, CMD55_R, resp);		/* 后续命令为一个应用命令 */
    if (ret != SD_NO_ERR)
    	return ret;											    /* command that the followed commnad is a specific application */
    												 
    if (resp[0] != 0)
        return SD_ERR_CMD_RESP;								    /* 响应错误 response is error */
    
    ret = SdSpi_SendCmd(sds, ACMD13, param, ACMD13_R, resp);	/* 读 SD_Status 命令 */
    if (ret != SD_NO_ERR)
    	return ret;											    /* command that read SD_Status register */
   												
    if ((resp[0] != 0) || (resp[1] != 0))
        return SD_ERR_CMD_RESP;								    /* 响应错误 response is error */
        
	return (SdSpi_ReadBlockData(sds, sdslen, recbuf));			/* 读出寄存器内容 read the content of the register */
}


/********
  ACMD51
*********/
/*******************************************************************************************************************
** 函数名称: SpiCmd_Send_SCR()				
**
** 功能描述: 读SD卡的 SCR 寄存器(MMC卡没有该命令)
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**           INT8U sdslen  	  : 寄存器长度(固定为64) 
**
** 输   出: INT8U *recbuf 	  : 接收缓冲区
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: MMC卡没有该寄存器
********************************************************************************************************************/
INT8U SpiCmd_Send_SCR(sd_struct *sds, INT8U scrlen, INT8U *recbuf)
{
    INT8U param[4] = {0,0,0,0},resp,ret;
    
    ret = SdSpi_SendCmd(sds, CMD55, param, CMD55_R, &resp);		/* 后续命令为一个应用命令 */
    if (ret != SD_NO_ERR)								        /* command that the followed commnad is a specific application */
    	return ret;													
    												 
    if (resp != 0)
        return SD_ERR_CMD_RESP;							        /* 响应错误 response is error */
    
    ret = SdSpi_SendCmd(sds, ACMD51, param, ACMD51_R, &resp);   /* 发送读 SD Status 命令*/
    if (ret != SD_NO_ERR)								        /* command that read SD Status register */
   		return ret;													
				    															
    if (resp != 0)
        return SD_ERR_CMD_RESP;						 	        /* 响应错误 response is error */
        
	return (SdSpi_ReadBlockData(sds, scrlen, recbuf));	 		/* 读出寄存器内容 read the content of the register */
}


/********
  ACMD22
*********/
/*******************************************************************************************************************
** 函数名称: SpiCmd_Send_Num_WR_Blcoks()				
**
** 功能描述: 得到正确写入的块数
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**
** 输   出: INT32U *blocknum : 返回的块数, 缓冲区长度固定为1
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: MMC卡没有该命令
********************************************************************************************************************/
#if SD_WriteMultiBlock_EN
INT8U SpiCmd_Send_Num_WR_Blcoks(sd_struct *sds, INT32U *blocknum)
{
    INT8U tmp[4] = {0,0,0,0},resp,ret;
  
    ret = SdSpi_SendCmd(sds, CMD55, tmp, CMD55_R, &resp);	 /* 后续命令为一个应用命令 */
    if (ret != SD_NO_ERR) 								     /* command that the followed commnad is a specific application */
    	return ret;
    	 
    if (resp != 0)
    	return SD_ERR_CMD_RESP;    	
 											
   	ret = SdSpi_SendCmd(sds, ACMD22, tmp, ACMD22_R, &resp); /* 读取正确写入的块数命令 */
   	if (ret != SD_NO_ERR)								    /* command that read the numbers of block written correctly */
   		return ret;											    
   		 														
	if (resp != 0)
    	return SD_ERR_CMD_RESP;							    /* 响应错误 response is error */
    		
    ret = SdSpi_ReadBlockData(sds, 4, tmp);				    /* 读块数 read the numbvers of block */
    if (ret != SD_NO_ERR)
    	return ret;
    	
    *blocknum = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];	
    													    /* 转换为32位 change to 32 bits */

	return SD_NO_ERR;    								    /* 返回执行成功 return perform sucessfully */		
}
#endif



		/*********************************************************
		
		    			下面为一些数据传输函数
		
		**********************************************************/

/*******************************************************************************************************************
** 函数名称: SdSpi_ReadRegister()				
**
** 功能描述: SPI模式下, 读SD/MMC卡寄存器内容
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**           INT32U len	      : 数据字节长度
**
** 输   出: INT8U *recbuf    : 接收缓冲区
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: 该函数只适应用于读寄存器时使用, 不适合于读数据块
********************************************************************************************************************/
INT8U SdSpi_ReadRegister(sd_struct *sds, INT32U len, INT8U *recbuf)
{	
	INT32U i = 0;
	INT8U resp;

    SdSpiHal_CSAssert(sds);
    do{    											/* 等待数据起始令牌 wait for data start token */
        resp = SdSpiHal_RecByte(sds);
    	i++;
    }while((resp == 0xFF) && (i < SD_READREG_TIMEOUT));    
    
    if (i >= SD_READREG_TIMEOUT)
    {
    	SdSpiHal_CSDeassert(sds);
    	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] = SdSpiHal_RecByte(sds);			/* 接收数据 receive data */
   		
    i = SdSpiHal_RecByte(sds);								
    i = (i << 8) + SdSpiHal_RecByte(sds);   		/* 读取16位CRC get 16-bit CRC */	

#if SD_CRC_EN 
   	if (i != SD_GetCRC16(recbuf, len))
   	{												/* CRC校验错误 CRC check is error */
   		SdSpiHal_SendByte(sds, 0xFF);
   		SdSpiHal_CSDeassert(sds);		
  		return SD_ERR_DATA_CRC16;					/* 返回RCR16错误  return error of CRC16 */				
  	}    
#endif   
  
    SdSpiHal_SendByte(sds, 0xFF);					/* 返回之前发送8个clock  clock out 8 clk before return */
    SdSpiHal_CSDeassert(sds);	
    	
	return SD_NO_ERR;
}	


#define  SD_UCOSII_SMALLWAIT  256

/*******************************************************************************************************************
** 函数名称: SdSpi_ReadBlockData()				
**
** 功能描述: SPI模式下, 从卡中读取数据块
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**           INT32U len	      : 数据字节长度
**
** 输   出: INT8U *recbuf    : 接收缓冲区
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: 该函数只适于读数据块, 并不适合于读卡寄存器内容
********************************************************************************************************************/
INT8U SdSpi_ReadBlockData(sd_struct *sds, INT32U len, INT8U *recbuf)
{
    INT8U tmp;
    INT32U i = 0,timeout;
    
#if SD_UCOSII_EN    
    timeout = SD_UCOSII_SMALLWAIT;						/* 很少的等待时间 small wait time */
#else
	timeout = sds->timeout_read;						/* 等待接收数据开始令牌最长时间 wait time that receive data start token */
#endif  
    
    SdSpiHal_CSAssert(sds);    
    do
    { 											    	/* 等待接收数据开始令牌0xFE  wait for receiving data start token 0xFE */
        tmp = SdSpiHal_RecByte(sds);
        i++;
    }while((tmp == 0xFF) && (i < timeout));
	
#if SD_UCOSII_EN    
    if (i >= timeout)
   	{													/* 继续等待(挂起任务) continue to wait(suspend task) */
   		timeout = sds->timeout_read;
   		i = 0;
	    do
    	{
        	OSTimeDly(1);								/* 挂起该任务1 tick(suspend task 1 tick) */
        	tmp = SdSpiHal_RecByte(sds);
       	 	i++;
   		}while((tmp == 0xFF) && (i < timeout));
	}
#endif

	if (i >= timeout)
	{
		SdSpiHal_CSDeassert(sds);
       	return SD_ERR_TIMEOUT_READ;						/* 返回读超时错误码  return error timeout error code of reading */
	}
	
	if (tmp != SD_TOK_READ_STARTBLOCK)					/* 块读开始令牌错误 read start block token is error */
	{
		SdSpiHal_SendByte(sds, 0xFF);
		SdSpiHal_CSDeassert(sds);
		return SD_ERR_DATA_START_TOK;
	}
	
	for (i = 0; i < len; i++)
   		recbuf[i] = SdSpiHal_RecByte(sds);				/* 接收数据 receive data */
   		
    i = SdSpiHal_RecByte(sds);							
    i = (i << 8) + SdSpiHal_RecByte(sds);    			/* 读取16位CRC get 16-bit CRC */	

#if SD_CRC_EN 
   	if (i != SD_GetCRC16(recbuf, len))
   	{	
   		SdSpiHal_SendByte(sds, 0xFF); 					/* CRC校验错误 CRC check is error */
   		SdSpiHal_CSDeassert(sds);		
  		return SD_ERR_DATA_CRC16;						/* 返回RCR16错误  return error of CRC16 */				
  	}    
#endif   

	SdSpiHal_SendByte(sds, 0xFF); 
	SdSpiHal_CSDeassert(sds);

  	return SD_NO_ERR;									/* 返回函数执行成功 return function perform sucessfully */
}


/*******************************************************************************************************************
** 函数名称: SdSpi_WriteBlockData()				
**
** 功能描述: SPI模式下, 向卡写数据块
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**           INT8U bmulti     : 是否为多块操作1:是0:否
**           INT32U len	      : 数据字节长度
**           INT8U *sendbuf   : 发送缓冲区
**
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: 
********************************************************************************************************************/
INT8U SdSpi_WriteBlockData(sd_struct *sds, INT8U bmulti, INT32U len, INT8U *sendbuf)
{
	INT16U i;
	INT8U tmp;

	SdSpiHal_CSAssert(sds);
		
    SdSpiHal_SendByte(sds, 0xFF);							/* 开始发送数据之前发送8个clock clock out 8 clk before start */
    
    if (bmulti == 1)
        SdSpiHal_SendByte(sds, SD_TOK_WRITE_STARTBLOCK_M);	/* 写多块开始令牌 start token of write multi blocks */
	else
		SdSpiHal_SendByte(sds, SD_TOK_WRITE_STARTBLOCK);	/* 写单块开始令牌 start token of write single block */

	for (i = 0; i < len; i++)
        SdSpiHal_SendByte(sds, sendbuf[i]);					/* 发送数据 send data */

#if SD_CRC_EN	
	i = SD_GetCRC16(sendbuf,len);							/* 计算CRC16 calculate CRC16 */
#endif

	SdSpiHal_SendByte(sds, (i >> 8) & 0xFF);
	SdSpiHal_SendByte(sds, i & 0xFF); 						/* 发送CRC16校验码 send CRC16 check code */
			    
	tmp = SdSpiHal_RecByte(sds);
  	if ((tmp & SD_RESP_DATA_MSK) != SD_RESP_DATA_ACCETPTED)	
  	{		
   		SdSpiHal_SendByte(sds, 0xFF);						/* 返回之前发送8个clock  clock out 8 clk before return */
   		SdSpiHal_CSDeassert(sds);
   		return SD_ERR_DATA_RESP;							/* 数据响应错误 data response error */
    }
        
    SdSpiHal_CSDeassert(sds);
     		
    if (SdSpi_WaitBusy(sds, SD_WAIT_WRITE) != SD_NO_ERR)			
    	return SD_ERR_TIMEOUT_WRITE;						/* 写入超时 write time out */
    else
    	return SD_NO_ERR; 									/* 写入正确 write right */
}


/*******************************************************************************************************************
** 函数名称: SdSpi_StopMultiToken()				
**
** 功能描述: SPI模式下, 发送多块写停止令牌
**
** 输   入: sd_struct *sds   : SD/MMC卡信息结构体
**
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: 
********************************************************************************************************************/
void SdSpi_StopMultiToken(sd_struct *sds)
{
	SdSpiHal_CSAssert(sds);
	
	SdSpiHal_SendByte(sds, 0xFF);							/* 先发送8

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -