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

📄 sd_drv.c

📁 这是sd卡驱动的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    U32 vol,blocknr,block_len;
    U32 c_size,mult;
  
    c_size = (g_stCSD.c_size_hi<<2)+g_stCSD.c_size_lo;
    mult =  2 <<(g_stCSD.c_size_mul+1);
    blocknr = (c_size+1)*mult;
    block_len = 2<<(g_stCSD.read_bl_len-1);

    vol = blocknr*block_len/1024/1024; 
    aos_printf(MPE_SYS," SD-CARD Ok. Volume is %d M Bytes.",vol);
    /*
    aos_printf(MPE_DRV," read_bl_len is 0x%x .",g_stCSD.read_bl_len);
    aos_printf(MPE_DRV," write_bl_len is 0x%x .",g_stCSD.write_bl_len);
    aos_printf(MPE_DRV," c_size is 0x%x .",(g_stCSD.c_size_hi<<2)+g_stCSD.c_size_lo);
    aos_printf(MPE_DRV," c_size_mul 0x%x .",g_stCSD.c_size_mul);
    aos_printf(MPE_DRV," taac 0x%x .",g_stCSD.taac);
    aos_printf(MPE_DRV," nsac 0x%x .",g_stCSD.nsac);
    aos_printf(MPE_DRV, " SD-card Misalign Read=%d Write=%d",
              g_stCSD.write_bl_misalign,g_stCSD.read_bl_misalign);
              */
    g_SDVolume=vol;  //便于sh显示用
    return vol;
}

/******************************************************************************
函数: sd_read_cid_config
描述:
      读SD卡的CID
输入:
输出:
返回: 
      成功返回AOS_SUCC,失败返回AOS_FAIL
******************************************************************************/	
U32 sd_read_cid_config()
{
	U8 *pBuf;
	U8 status;
    U32 i,result;
    
	spi_enable_cs();
	
    result = AOS_SUCC;
   
    status = sd_write_command(CMD10_READ_CID);    //response R1 	     	
    if(status != 0)
    {
           AOS_ASSERT(0);
           result = AOS_FAIL;
           goto done;
    } 
 
    //start block 0xFE + 16 bytes user datas + 16 bit CRC  
    i=0;
   	do
   	{
   		status = spi_read();
   		i++;
   		if( i > 3000 )  
   		{
              AOS_ASSERT(0);
              result = AOS_FAIL;
              goto done;
   		}
   	} while(status != 0xFE);   

   	// Read off all the bytes in the block
    pBuf =(U8*)&g_stCID;   	
   	for(i = 0; i < 16; ++i)
   	{
   		*pBuf = spi_read();		
   		pBuf++;
   	}
   
    status = spi_read();   
    //aos_printf(0," CID CRC byte is 0x%x",status);    
    status = spi_read();    
    //aos_printf(0," CID CRC byte is 0x%x",status);
  done:  
    //发一个0xFF表示结束操作
	status=0xFF;
	spi_write(&status,1); 

	spi_disable_cs();
    
    return result;
    
}

/******************************************************************************
函数: sd_read_csd_config
描述:
      读SD卡的CSD
输入:
输出:
返回: 
      成功返回AOS_SUCC,失败返回AOS_FAIL
******************************************************************************/	
U32 sd_read_csd_config()
{
	U8 *pBuf;
	U8 status;
	//U8  crc_hi=0xFF,crc_lo=0xFF;
	//U16 crc_value=0xFFFF;
	U32 i,result;
    U32 AgainCnt=0;
    
    clear_watch_dog();
	spi_enable_cs();
	//需要计算卡的容量,有时需要多读几次卡才能得到CSD
again:
    result = AOS_SUCC;
    pBuf =(U8*)&g_stCSD;   
    for (i=0;i<5000;i++)
   	{
   	  	status = sd_write_command(CMD9_READ_CSD);    //response R1
   	  	if(status == 0)
   	  		break;
    }
    if(status != 0)
    {
       AOS_ASSERT(0);
       result = AOS_FAIL;
       goto done;
    } 
   
    //start block 0xFE + 16 bytes user datas + 16 bit CRC  
    i=0;
	do
	{
		status = spi_read();
		i++;
		if( i > 800 )
		{
            AOS_ASSERT(0);
            result = AOS_FAIL;
            AgainCnt++;
            goto done;
		}
	} while(status != 0xFE);    
   
	// Read off all the bytes in the block
	for(i = 0; i < 16; i++)
	{
        *pBuf = spi_read();  
		pBuf++;
	}
	status = spi_read();   
       status = spi_read();   
       /*  //对比硬件计算的CRC 与软件计算的CRC
        crc_hi = spi_read();   
        crc_lo = spi_read();    
        crc_value=((crc_hi<<8)|crc_lo);
        aos_printf(MPE_DRV," CSD CRC byte(hardwre) is 0x%x",crc_value);
        crc_value=aos_CalCRC ( pBuf, 16);
       aos_printf(MPE_DRV,"  CSD CRC(software)byte is 0x%x",crc_value);
       */
done:    
     if( (result == AOS_FAIL)&& (AgainCnt< 2) )
     {        
         goto again;
     }
     //发一个0xFF表示结束操作
	status=0xFF;
	spi_write(&status,1); 

	spi_disable_cs();
    
    return result;
    
}

/******************************************************************************
函数:sd_erase_block
描述:
      擦除SD卡的一部分,在SD模式下,先擦除再写速度有提高
输入:
      U32 addr0   起始地址
      U32 addr1   结束地址
输出:
返回: 
      成功返回AOS_SUCC,失败返回AOS_FAIL
******************************************************************************/	
U32 sd_erase_block(U32 addr0, U32 addr1)
{
	U8  status;
	U8  cmd;
    U16 status_r2;
    U32 i,result;

	result = AOS_SUCC;

    aos_printf(MPE_DRV,"sd erase  block from addr0=0x%x to addr1=0x%x",
                        addr0, addr1);
	CMD32_ERASE_START_BLOCK[1] = ((addr0 & 0xFF000000) >> 24);
	CMD32_ERASE_START_BLOCK[2] = ((addr0 & 0x00FF0000) >> 16);
	CMD32_ERASE_START_BLOCK[3] = ((addr0 & 0x0000FF00) >> 8);
	CMD32_ERASE_START_BLOCK[4] = ((addr0 & 0x000000FF));

	CMD33_ERASE_END_BLOCK[1] = ((addr1 & 0xFF000000) >> 24);
	CMD33_ERASE_END_BLOCK[2] = ((addr1 & 0x00FF0000) >> 16);
	CMD33_ERASE_END_BLOCK[3] = ((addr1 & 0x0000FF00) >> 8);
	CMD33_ERASE_END_BLOCK[4] = ((addr1 & 0x000000FF));
	
	spi_enable_cs();

	status = sd_write_command(CMD32_ERASE_START_BLOCK);
	if(status != 0)
	{
		// ABORT: invalid response for read single block command
		//aos_printf(MPE_DRV," sd erase start cmd status=0x%x",status);
		AOS_ASSERT(0);
        result = AOS_FAIL;
        goto done;
	}
    
	status = sd_write_command(CMD33_ERASE_END_BLOCK);
	if(status != 0)
	{
		// ABORT: invalid response for read single block command
		//aos_printf(MPE_SYS," sd erase end cmd status=0x%x",status);
		AOS_ASSERT(0);
        result = AOS_FAIL;
        goto done;
	}

	status = sd_write_command(CMD38_ERASE_BLOCK);
	if(status != 0)
	{
		// ABORT: invalid response for read single block command
		//aos_printf(MPE_DRV," sd erase cmd status=0x%x",status);
		AOS_ASSERT(0);
        result = AOS_FAIL;
        goto done;
	}

    status = sd_wait_for_r1();    
    SD_CHECK_BUSY(500); 
 	
    // send status R2 response
    for( i=0; i< 500; i++ )
    {
     	status_r2 = sd_write_cmd_r2(CMD13_SEND_STATUS_BLOCK);
     	if(status_r2 == 0)
     	{
     		result = AOS_SUCC;
            break;
     	}
 	// ABORT: invalid response for read single block command
 	//aos_printf(MPE_DRV," sd erase status=0x%x",status_r2);
 	result = AOS_FAIL;
	}

done:     
	cmd=0xFF;
	spi_write(&cmd,1); 

	spi_disable_cs();

	return result;
}

/******************************************************************************
函数: sd_mem_read
描述:
      从SD的相应源地址读数据到SDRAM目的地址
输入:
      U32 addr     将要读出数据的SD源地址
      U32 buf_addr SDRAM目的地址
      U32 size     数据大小(字节数) 
输出:
返回:
      如果成功,返回AOS_SUCC , 否则AOS_FAIL
******************************************************************************/
U32 sd_mem_read(U32 addr,U32 buf_addr,U32 size)
{
        U32 sd_addr,len=0;
        U32 blockaddr0,blockaddr1,off;
        U8  *pDst=NULL,*pSrc=NULL;
        U8  szBuf[BLOCK_SIZE+4];
        
        //卡不存在就返回
        if( !sdcard_pos )
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        }
        
        sd_addr = addr - SDCARD_BASE_ADDR;
        // 512字节对齐
        blockaddr0= sd_addr-(sd_addr%BLOCK_SIZE);
        blockaddr1= (sd_addr+size)-((sd_addr+size)%BLOCK_SIZE);    
            
        for( off=blockaddr0; off<= blockaddr1; off=off+BLOCK_SIZE )
        {
            
            if( off == blockaddr0 )
            {
                // the first block
                pDst = (U8*)buf_addr;
                pSrc = szBuf+ (sd_addr%BLOCK_SIZE);
                len  = BLOCK_SIZE-(sd_addr%BLOCK_SIZE);
                if( len > size )
                    len = size;
            }
            else if( off == blockaddr1 )
            {
                // the last block
                len = (sd_addr+size)%BLOCK_SIZE;
            }
             //should add delay 
            if( AOS_SUCC != sd_read_block(off,szBuf) )
            {
                AOS_ASSERT(0);
                return AOS_FAIL;
            }
            
            aos_memcpy( pDst,pSrc, len);
            pDst += len;
            pSrc = szBuf;
            len  = BLOCK_SIZE;
        }
        
        return AOS_SUCC;
}

/******************************************************************************
函数: sd_read_block
描述:
      从SD的相应地址读数据到指针处
输入:
      U32 addr  将要读出数据的SD地址
         
输出: U8 *buf   数据保存所在指针 
返回:
      如果成功,返回AOS_SUCC , 否则AOS_FAIL
******************************************************************************/
U32 sd_read_block(U32 addr, U8 *buf)
{
	U8  status=1;
	U8  *pCh;
	//U8  crc_hi=0xFF,crc_lo=0xFF;
	//U16 crc_value=0xFFFF;
	U32 i,result;	
    U32 AgainCnt=0;
    
    if( addr%BLOCK_SIZE != 0 )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    clear_watch_dog();         
     
again:    
    aos_printf(MPE_DRV,"sd read a block addr=0x%x buf=0x%x",addr, buf);    
	result = AOS_SUCC;
	//read block length is 512 bytes	
	CMD17_READ_SINGLE_BLOCK[1] = ((addr & 0xFF000000) >> 24);
	CMD17_READ_SINGLE_BLOCK[2] = ((addr & 0x00FF0000) >> 16);
	CMD17_READ_SINGLE_BLOCK[3] = ((addr & 0x0000FF00) >> 8);
	CMD17_READ_SINGLE_BLOCK[4] = ((addr & 0x000000FF));

	spi_enable_cs();

	// Send the read command
	for( i=0; i< 200; i++ )
	{
    	    status = sd_write_command(CMD17_READ_SINGLE_BLOCK);
	    	if( status == 0 )
	    	//aos_printf(MPE_DRV,"cmd17 response  is %d,and current i is %d",status,i);
	    	   break;    	   
	}

	if( i ==200 )
	{
		// ABORT: invalid response for read single block command
		AOS_ASSERT(0);	
		//aos_printf(MPE_DRV,"cmd17 error status is = %d",status); 
        result = AOS_FAIL;
        goto done;
	}
        //不同卡TAAC不同,有可能Nac达到ms,这里有一个goto ,again重写机制,不会出错
       /*
       if (((g_stCSD.taac)&0x07)==7)   
            hw_delay(8000);
       else */
        	hw_delay(100);
    	
	// BLOCK  0xFE 2-513 CRC16  (515Bytes)
	// Now wait for the "Start Block" token	(0xFE)
	// (see SanDisk SD Card Product Manual v1.9 section 5.2.4. Data Tokens)	
    i=0;
	do
	{
		status = spi_read();		
		i++;
		if( i ==1000)    
		{
             AOS_ASSERT(0);
             AgainCnt++;                
             result = AOS_FAIL;
             goto done;
		}
	} 
	while(status!=0xFE);
       // aos_printf(MPE_DRV,"read start block( 1111110) is %d ,times is %d",status,i);    

       // Read off all the bytes in the block
    pCh = buf;	
	for(i = 0; i < BLOCK_SIZE; i++)  
	{		
		*pCh = spi_read();		
		pCh++;
	}
 
	// Read CRC bytes
	status = spi_read();
	status = spi_read();   
	//比较硬件计算的CRC值和软件计算的CRC值
	/* 
	crc_hi = spi_read();   
        crc_lo = spi_read();    
        crc_value=((crc_hi<<8)|crc_lo);
        aos_printf(MPE_DRV," read block CRC byte(hardwre) is 0x%x",crc_value);
        crc_value=aos_CalCRC ( pCh, BLOCK_SIZE);
        aos_printf(MPE_DRV,"  read CRC(software)byte is 0x%x",crc_value);
	*/
        hw_delay(10);
	// Following a read transaction, the SD Card needs 8 clocks after the end 
	// bit of the last data block to finish up its work.
	// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
done:	
	
    if( (result == AOS_FAIL)&& (AgainCnt< 3) )
    {        
        goto again;

⌨️ 快捷键说明

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