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

📄 sd_drv.c

📁 这是sd卡驱动的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
        (c) COPYRIGHT 2002- by Shenzhen Allywll Information Co.,Ltd
                          All rights reserved.
File:      spi_drv.c
Desc:    Common interface for SPI SD card.
Modification history(no, author, date, desc)
1. luke   2006-03-31  create file 
2 .william 2006-10-15   modify 
3   william 2006-10-29
     暂时没有完善CRC功能,初始化时调用CMD59可以,但读写
   CSD(CMD9)时没有正确应答,并且读 写块时的硬件CRC与软件
   预先计算的值不一致。
*****************************************************************************/
#include "syscfg.h"
#if( AOS_INCLUDE_DRIVER_SPI == TRUE )

#ifdef    __cplusplus
extern "C" {
#endif

#include "aos.h"
#include "os/ker/ssp_cputick.h"
#include "spi_drv.h"
#include "sdcard.h"
#include "drv/bsp_pub.h"
#include "drv/sdcard_pub.h"
#include "drv/flash_pub.h"

#define SINGLE_WRITE     // 是单块写,还是多块写
//#define CRC_ON         //是否CRC 校验

//extern U16 aos_CalCRC ( U8 *ptr, U32 count );  //16 bit CRC

//计算SD容量要用
SD_CSD_T g_stCSD;
SD_CID_T g_stCID;
BOOL_T sdcard_pos=FALSE;
U32    g_SDVolume=0;    //sh 命令用 
U32   g_readBlock_usec; //sh 命令用 
// SD擦写缓冲区,多块写要用到
BOOL_T g_bFirstFlag =FALSE;
BOOL_T g_bLastFlag =FALSE;
U8  g_szBuf0[BLOCK_SIZE];
U8  g_szBuf1[BLOCK_SIZE];
//CMD test
static U8 szTestBuf[5120];
static U8 szTestBuf1[512];

// After this command, CRC values are ignore unless explicitly enabled using CMD59
U8 CMD0_GO_IDLE_STATE[] = {0x00,0x00,0x00,0x00,0x00,0x95};
// Wait for SD Card to initialize
U8 CMD1_SEND_OP_COND[] = {0x01,0x00,0x00,0x00,0x00,0xFF};

// Send CMD55, required to precede all "application specific" commands
U8 CMD55_APP_CMD[] = {55,0x00,0x00,0x00,0x00,0xFF};
U8 ACMD41_SD_SEND_OP_COND[] = {41,0x00,0x00,0x00,0x00,0xFF};

#ifdef CRC_ON   
U8 CMD1_SEND_OP_COND[] = {0x01,0x00,0x00,0x00,0x00,0xF9};
U8 CMD9_READ_CSD[] = { 9,0x00,0x00,0x00,0x00,0xAF};
U8 CMD10_READ_CID[] = {10,0x00,0x00,0x00,0x00,0xFF};
U8 CMD55_APP_CMD[] = {55,0x00,0x00,0x00,0x00,0x65};
U8 ACMD41_SD_SEND_OP_COND[] = {41,0x00,0x00,0x00,0x00,0xE5};
#endif

U8 CMD9_READ_CSD[] = { 9,0x00,0x00,0x00,0x00,0xFF};
U8 CMD10_READ_CID[] = {10,0x00,0x00,0x00,0x00,0xFF};

U8  CMD17_READ_SINGLE_BLOCK[] = {17,0x00,0x00,0x00,0x00,0xFF};
U8  CMD18_READ_MULTI_BLOCK[] = {18,0x00,0x00,0x00,0x00,0xFF};

U8  CMD24_WRITE_SINGLE_BLOCK[] = {24,0x00,0x00,0x00,0x00,0xFF};
U8  CMD25_WRITE_MULTI_BLOCK[] = {25,0x00,0x00,0x00,0x00,0xFF};

U8  CMD13_SEND_STATUS_BLOCK[] ={13,0x00,0x00,0x00,0x00,0xFF};
U8  CMD32_ERASE_START_BLOCK[] = {32,0x00,0x00,0x00,0x00,0xFF};
U8  CMD33_ERASE_END_BLOCK[]  = {33,0x00,0x00,0x00,0x00,0xFF};
U8  CMD38_ERASE_BLOCK[]      = {38,0x00,0x00,0x00,0x00,0xFF};	

U8  CMD59_CRC_0N[]      = {59,0x00,0x00,0x00,0x01,0x83};
U8  CMD59_CRC_0FF[]      = {59,0x00,0x00,0x00,0x00,0xFF};

#define SD_CHECK_BUSY(loop)  {   U32 cnt; \
                                 U8 resp;   \
                                 for(cnt=0; cnt< loop; cnt++)  \
                                 {            \
                        	         resp = spi_read();   \
                        	         if( resp != 0 )      \
                         	         {             \
                         	            break;    \
                           	         }         \
                                 }     \
                             }

 
 /******************************************************************************
函数: sd_crc7
描述:
      8位CRC ,多项式为x^7+x^3+1  
输入:
      U8 *chr  指向要校验的数据
      U32 cnt  数据字节数
输出:
返回: 8位CRC 值( 7 位或一个置1 位)
******************************************************************************/
U8 sd_crc7(U8 * chr, U32 cnt) 
{ 
    U8 crc_7,Data; 
    U32 i,a;     
    crc_7=0; 
    for ( a=0; a<cnt; a++) 
    { 
        Data=chr[a]; 
        for (i=0;i<8;i++) 
        { 
              crc_7 <<= 1;
              if ((Data & 0x80)^(crc_7 & 0x80)) 
               crc_7 ^=0x09; 
               Data <<= 1; 
        } 
    } 
    crc_7=(crc_7<<1)|1;  
    return(crc_7); 
}

/******************************************************************************
函数: hw_delay
描述:
           硬件延时 要使用volatile
输入:
           U32  value     ,延时的值  
输出:
返回: void 
******************************************************************************/
VOID hw_delay(U32 value)
{
      volatile U32 i;
      for (i=0;i<value;i++);
}

     //R1 is a byte long
     //bit 0 in idle state
     //bit 1 erase reset
     //bit 2 illegal command
     //bit 3 com CRC error
     //bit 4 Erase_Seq_Error
     //bit 5 Address Error
     //bit 6 Parameter Error
     //bit 7 always 0
/******************************************************************************
函数: sd_wait_for_r1
描述:
      每次发送命令后有一个R1 应答
输入:  void   
输出:
返回: 应答
******************************************************************************/
U8 sd_wait_for_r1(void)
{
    U32 i;
    U8 response;
    U8  status;
	// Wait for the response
    for( i=0;i <250; i++ )
    {
        response = spi_read();
        if( response != 0xFF )
        {
              break;
        }
    }
     //add  eight clock ,complete 
    status=0xFF;            
    spi_write(&status,1);   
    return response;
}

/******************************************************************************
函数: sd_write_cmd_r2
描述:
      R2 is 2 bytes long response  sent by the card as a response to the SEND_STATUS command
输入:
      U8 *cmd   指向命令的指针 ( 一般为数组)
输出:
返回: U16 的应答
******************************************************************************/
U16 sd_write_cmd_r2(U8* cmd)
{	
    U8  status;
    U8  r_hi=0xFF,r_lo=0xFF;
    U16 response=0xFFFF;
    U32 i;
   	// SD Card Command Format 48Bit
   	// (from Section 5.2.1 of SanDisk SD Card Product Manual v1.9).
   	// Frame 7 = 0
   	// Frame 6 = 1
   	// Command (6 bits)
   	// Address (32 bits)	
   	// Frame 0 = 1
   
   	// Set the framing bits correctly (never change)
  	cmd[0] |= (1<<6);	
  	cmd[0] &= ~(1<<7);
  	cmd[5] |= (1<<0);
  
    #ifdef CRC_ON   
    cmd[5] =sd_crc7(cmd,5);
    #endif
	// Send the 6 byte command
    for(i=0;i<6;i++)
          spi_write(&cmd[i],1);

	// Wait for the response
    for( i=0;i <500; i++ )
    {
        r_hi = spi_read();
        r_lo = spi_read();       
        response = (r_hi<<8) +r_lo;
        if( response != 0xFFFF )
        {
            break;
        }
    }
	
	// Following any command, the SD Card needs 8 clocks to finish up its work.
	// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
	status=0xFF;
	spi_write(&status,1); 

	return(response);
}

/******************************************************************************
函数: sd_write_command
描述:
      向SD卡写一个命令字
输入:
      U8 *cmd   指向命令的指针 ( 一般为数组)
输出:
返回: U8的应答
******************************************************************************/
U8 sd_write_command(U8* cmd)
{
	U8 response=0xFF;
    U8 status;
	U32 i;
    
	// SD Card Command Format 48Bit
	// (from Section 5.2.1 of SanDisk SD Card Product Manual v1.9).
	// Frame 7 = 0
	// Frame 6 = 1
	// Command (6 bits)
	// Address (32 bits)
	// Frame 0 = 1

	// Set the framing bits correctly (never change)
	cmd[0] |= (1<<6);
	cmd[0] &= ~(1<<7);	
	cmd[5] |= (1<<0);   
	
    #ifdef CRC_ON      
    cmd[5]    = sd_crc7(cmd,5);
    #endif
       
	// Send the 6 byte command
    for(i=0;i<6;i++)
        spi_write(&cmd[i],1);   
  
    // Wait for the response
     i=0;
	do
	{
       response = spi_read();
       i++;
       if (i==500)   
       	break;
	}
	while(response == 0xFF );
	// Following any command, the SD Card needs 8 clocks to finish up its work.
	// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
	status=0xFF;
	spi_write(&status,1); 

	return(response);
}

/******************************************************************************
函数:  spi_sdcard_init
描述:
       SD卡的SPI 模式初始化
输入:
输出:
返回: 
       成功返回AOS_SUCC,失败返回其它值(1,2,3,4)
******************************************************************************/
U32 spi_sdcard_init()
{
 	U8 status;
    U32 i;	  
       
	spi_enable_cs();
    
	// Wait for the SD Card to go into IDLE state
	i = 0;
	do
	{
	    status = sd_write_command(CMD0_GO_IDLE_STATE);  	
		if(i++ > 1000)
		{
		    AOS_ASSERT(0);		   
			return 1;
		}
	} while( status != R1_IN_IDLE_STATE );
        // aos_printf(MPE_DRV,"cmd0 response is %d,time is %d",status,i);           
     
       i = 0;
	do
	{
		status = sd_write_command(CMD1_SEND_OP_COND);
		if(i++ > 8000 )   //适应不同卡
		{
		    AOS_ASSERT(0);
			return 2;
		}
	} while( status != 0 );
    // aos_printf(MPE_DRV,"cmd1 response is %d,time is %d,cmd[5] is 0x%x",status,i,CMD1_SEND_OP_COND[5]);  
 
     hw_delay(500);     
     
     status = sd_write_command(CMD55_APP_CMD);     
     //aos_printf(MPE_SYS,"cmd55 response is %d,cmd[5] is 0x%x",status,  CMD55_APP_CMD[5] );   
     // ACMD41的工作频率按标准应该100Khz<f<400KHz 使用前需调用CMD55_APP_CMD
 
     hw_delay(500);
    // aos_printf(MPE_SYS,"ACMD41 cmd[5] is 0x%x",ACMD41_SD_SEND_OP_COND[5]);
     i = 0;
 	do
 	{
 		status = sd_write_command(ACMD41_SD_SEND_OP_COND);	
 		if(i++ > 500 )
 		{
 		    AOS_ASSERT(0);		    
 			return 4;
 		}
 	} while( status != 0 );
 	// Might return 0x04 for Invalid Command if MMC card is connected
    //aos_printf(MPE_DRV,"ACMD41 response is %d,time is %d",status,i);   
    
    #ifdef CRC_ON      
    status = sd_write_command(CMD59_CRC_0N);	
    if (status!=0)
    {
        AOS_ASSERT(0);
    }
    #endif          
 
    spi_disable_cs();
	
	return AOS_SUCC;
}

/******************************************************************************
函数:  sd_card_init
描述:
       SD卡的初始化,检查是否存在,读CSD ,CID,
输入:
输出:
返回: 
       成功返回AOS_SUCC,失败返回AOS_FAIL或重启动
******************************************************************************/	
U32 sd_card_init()
{
    	U8 ucBuf[32];
        U32 result;

        spi_init();

        if( !is_sd_card_in() )
        {
            aos_printf(MPE_SYS," SD-Card is no exist!");
            return AOS_FAIL;
        }  
        // Wait for power to really come up
        spi_enable_cs();
        // We need to give SD Card about a hundred clock cycles to boot up
        aos_memset(ucBuf,0xFF,16);
        // write dummy data to pump clock signal line
        spi_write(ucBuf,16); 
        spi_disable_cs();

        aos_printf(MPE_SYS, "SD-Card: %s %s",
                   (is_sd_card_in()?"OnBoard":"NoExist"),
                   (is_sd_card_protect()?"Protected":"unProtected"));        

        aos_task_delay(50);
                 	
        result= spi_sdcard_init();
      
        if( result == AOS_SUCC )
        {
            sd_read_cid_config();    
            sd_read_csd_config();
            sd_get_card_volume(); 
            sdcard_pos = TRUE;
        }

        spi_fast_clock();
        
	    return result;
}


/*
device size    12bit R[73:62]
size multiper 2bit  R[49:47]
erase sector size 7bit R[45:39]
memory capacity = BLOCKNR * BLOCK_LEN
Where:
BLOCKNR = (C_SIZE+1) * MULT
MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8)
BLOCK_LEN = 2^READ_BL_LEN (READ_BL_LEN < 12)
Therefore, the maximum capacity which can be coded is 4096*512*2048 = 4 GBytes. 
Example: A four MByte card with BLOCK_LEN = 512 can be coded with 
C_SIZE_MULT = 0 and C_SIZE = 2047.
*/
/******************************************************************************
函数: sd_get_card_volume
描述:
      计算SD卡的容量
输入:
输出:
返回: SD卡的容量
******************************************************************************/	
U32 sd_get_card_volume()
{

⌨️ 快捷键说明

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