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

📄 sddriver.c

📁 基于lpc2378的SD/MMC卡读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:

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 + -