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

📄 sddriver.c

📁 NIOS II 的几个源代码
💻 C
字号:
#include <stdio.h>
#include <sys/unistd.h>
#include <io.h>
#include <string.h>

#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"

#include "sdconfig.h"
#include "sdhal.h"
#include "SDCmd.h"
#include "sddriver.h"

// SD卡信息结构体变量
sd_struct sds;			

// 超时时间单位表(单位:0.000000001ns)
const INT32U time_unit[8] = {1000000000,100000000,10000000,
							 1000000,100000,10000,1000,100};

// 超时时间表
const INT8U time_value[16] = {0,10,12,13,15,20,25,30,
                              35,40,45,50,55,60,70,80};
 
// 超时时间因数表
const INT8U r2w_fator[6] = {1,2,4,8,16,32};                           
    
//初始化SD卡
INT8U SD_Initialize(void)
{
	INT8U recbuf[4],ret;
    
  SD_HardWareInit();
    
  if (SD_ChkCard() != 1)	
  	return SD_ERR_NO_CARD;   
         
  SPI_CS_Assert();	
	SD_SPIDelay(25);
  SPI_CS_Deassert();
  SD_SPIDelay(2);
    
  ret = SD_ResetSD();
  if (ret != SD_NO_ERR)
    return ret;									
 	
 	ret = SD_ActiveInit();
 	if (ret != SD_NO_ERR)
 		return ret;
        
  ret = SD_ReadOCR(4, recbuf); 
  if (ret != SD_NO_ERR)
    return ret;
    
  if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
    return SD_ERR_VOL_NOTSUSP;
    
  SPI_ClkToMax();	
        
#if SD_CRC_EN        
  ret = SD_EnableCRC(1);
	if (ret != SD_NO_ERR)  
		return ret;
#endif

  ret = SD_SetBlockLen(SD_BLOCKSIZE);
  if (ret != SD_NO_ERR)  
    return ret;
        
	return (SD_GetCardInfo());
}

//从SD卡中读一个块	
INT8U SD_ReadBlock(INT32U blockaddr, INT8U *recbuf)
{
	INT8U ret; 
	
	if (blockaddr > sds.block_num)	
		return SD_ERR_OVER_CARDRANGE;
	
 	ret = SD_ReadSingleBlock(blockaddr);
 	if (ret != SD_NO_ERR)
 		return ret;
 	
  return (SD_ReadBlockData(SD_BLOCKSIZE, recbuf));
}

//从SD卡中读多个块	
#if SD_ReadMultiBlock_EN
INT8U SD_ReadMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *recbuf)
{
  INT32U i;
  INT8U ret;
    
  if ((blockaddr + blocknum) > sds.block_num)	
		return SD_ERR_OVER_CARDRANGE;	
    
	ret = SD_ReadMultipleBlock(blockaddr);
	if (ret != SD_NO_ERR)
		return ret;
    
  for (i = 0; i < blocknum; i++)
  {	
  	ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf);
   	if (ret == SD_NO_ERR)
   		recbuf = recbuf + SD_BLOCKSIZE;
   	else
   		return ret;
  }
 	 
 	return (SD_StopTransmission());	
}

#endif

//向SD卡中写入一个块
INT8U SD_WriteBlock(INT32U blockaddr, INT8U *sendbuf)
{
	INT8U ret,tmp[2];
	
	if (blockaddr > sds.block_num)	
		return SD_ERR_OVER_CARDRANGE;
	
	if (SD_ChkCardWP() == 1)
		return SD_ERR_WRITE_PROTECT;
	
	ret = SD_WriteSingleBlock(blockaddr);
	if (ret != SD_NO_ERR)	
		return ret;
	
	ret = SD_WriteBlockData(0, SD_BLOCKSIZE, sendbuf);
 	if (ret == SD_NO_ERR)
 	{	
 		ret = SD_ReadCard_Status(2,tmp);
 		if (ret != SD_NO_ERR)
 			return ret;	

 		if((tmp[0] != 0) || (tmp[1] != 0))
			ret = SD_ERR_WRITE_BLK; 
 	}
  
 	return ret;
}

//向SD卡中写入多个块	
#if SD_WriteMultiBlock_EN
INT8U SD_WriteMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *sendbuf)
{
	INT32U i;
	INT8U ret;
	
	if ((blockaddr + blocknum) > sds.block_num)	
		return SD_ERR_OVER_CARDRANGE;	
		
	if (SD_ChkCardWP() == 1)
		return SD_ERR_WRITE_PROTECT;
	
	ret = SD_WriteMultipleBlock(blockaddr);	
	if (ret != SD_NO_ERR)
		return ret;

    for (i = 0; i < blocknum; i++)
    {															
 		ret = SD_WriteBlockData(1, SD_BLOCKSIZE, sendbuf);
 		if (ret == SD_NO_ERR)	
 			sendbuf = sendbuf + SD_BLOCKSIZE;
 		else
 		{		
			SD_StopTransmission();	
			SD_WaitBusy(SD_WAIT_WRITE);
			return ret;
		}
	}
   
  SD_StopMultiToken();
      
  ret = SD_WaitBusy(SD_WAIT_WRITE);
  if (ret != SD_NO_ERR)
  	return SD_ERR_TIMEOUT_WRITE;
    
  ret = SD_GetNumWRBlcoks(&i);
  if (ret != SD_NO_ERR)
  	return ret;
   	  	
  if(i != blocknum) 
   	return SD_ERR_WRITE_BLKNUMS;
   	   	     
	return SD_NO_ERR;
}
#endif

//擦除SD卡中的块							Function: Erase the block of sd card
#if SD_EraseBlock_EN
INT8U SD_EraseBlock(INT32U startaddr, INT32U blocknum)
{
	INT32 tmp;
	INT8U ret;
	
	if ((startaddr + blocknum) > sds.block_num)	
		return SD_ERR_OVER_CARDRANGE;	
		
	if (SD_ChkCardWP() == 1)
		return SD_ERR_WRITE_PROTECT;
		
	tmp = blocknum - sds.erase_unit;	
	while(tmp >= 0)
	{	
		ret = SD_EraseStartBlock(startaddr);
		if (ret != SD_NO_ERR)
			return ret;
		
		ret = SD_EraseEndBlock(startaddr + sds.erase_unit - 1);
		if (ret != SD_NO_ERR)
			return ret;
			
		ret = SD_EraseSelectedBlock();
		if (ret != SD_NO_ERR)
			return ret;

		startaddr += sds.erase_unit;	
		blocknum  -= sds.erase_unit;
		tmp = blocknum - sds.erase_unit;
	};		
	
	if (blocknum > 0)	
	{	
		ret = SD_EraseStartBlock(startaddr);
		if (ret != SD_NO_ERR)
			return ret;
		
		ret = SD_EraseEndBlock(startaddr + blocknum - 1);
		if (ret != SD_NO_ERR)
			return ret;
			
		ret = SD_EraseSelectedBlock();
		if (ret != SD_NO_ERR)
			return ret;
	}

	return SD_NO_ERR;	
}
#endif


//获得SD卡的信息	
INT8U SD_GetCardInfo()
{
	INT32U tmp;
	INT8U csdbuf[16],ret;
		
	ret = SD_ReadCSD(16,csdbuf);
	if (ret != SD_NO_ERR)	
		return ret;	
		
	SD_CalTimeout(csdbuf);
		
	/* 计算块的最大长度  */	
	sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK); 
	
	/* 计算卡中块的个数 */
	sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
	      			 (csdbuf[C_SIZE_POS2] << 2) +
	 	 			((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1;
		 	  															
	tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +   
	      ((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2;
    	
    /* 获得卡中块的数量 */	
	sds.block_num = sds.block_num * (1 << tmp);
																			
	/* 计算扇区大小 */
	sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +  			
	                 ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1;
	    			
	return SD_NO_ERR;
}

//计算读/写/擦超时时间
void SD_CalTimeout(INT8U *csdbuf)
{
	INT32U tmp;
	INT8U time_u,time_v,fator;
	
	sds.timeout_read = READ_TIMEOUT_100MS;
	sds.timeout_write = WRITE_TIMEOUT_250MS;
	sds.timeout_erase = WRITE_TIMEOUT_250MS;
		
	time_u = (csdbuf[TAAC_POS] & TAAC_MSK);
	time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3;
	fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2;	
	
	if(time_v == 0)	return;
	if(fator >= 6) return;
	
	tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u];	
	tmp = tmp + csdbuf[NSAC_POS] * 100;	
	
	sds.timeout_read = tmp;
	sds.timeout_write = tmp * r2w_fator[fator];
	
	sds.timeout_read  = sds.timeout_read * 100 / 8;	
	sds.timeout_write = sds.timeout_write * 100 / 8;
	
	if (sds.timeout_read > READ_TIMEOUT_100MS)
		sds.timeout_read = READ_TIMEOUT_100MS;
	
	if (sds.timeout_write > WRITE_TIMEOUT_250MS)
		sds.timeout_write = WRITE_TIMEOUT_250MS;

	sds.timeout_erase = sds.timeout_write;
}

//计算读/写/擦超时时间
INT8U SD_ActiveInit(void)
{
	INT8U param[4] = {0,0,0,0},resp[5],ret;
	INT32U i = 0;

 	do 
  {
    ret = SD_SendCmd(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));
														
  if (i >= SD_IDLE_WAIT_MAX)
    return SD_ERR_TIMEOUT_WAITIDLE;	

	return SD_NO_ERR;
}

⌨️ 快捷键说明

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