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

📄 sd_drv.c

📁 这是sd卡驱动的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    }
    //8个时钟表示结束
    status=0xFF;
	spi_write(&status,1); 
	
	spi_disable_cs();

	return result;
}

#ifdef SINGLE_WRITE
/******************************************************************************
函数: sd_mem_write
描述:
      从SDRAM的相应源地址写数据到SD目的地址
输入:
      U32 buf_addr  将要读出数据的SDRAM源地址
      U32 addr      SD目的地址
      U32 size      数据大小 
输出:
返回:
      如果成功,返回AOS_SUCC , 否则AOS_FAIL
******************************************************************************/
U32 sd_mem_write(U32 addr,U32 buf_addr,U32 size)
{
        U32 sd_addr,len=0;
        U32 blockaddr0,blockaddr1,off=0;
        U8  *pDst=NULL,*pSrc=NULL;
        // SD擦写缓冲区
        U8  szBuf[BLOCK_SIZE+4];

        if( !sdcard_pos )
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        }

        aos_printf( MPE_DRV, "sd mem write addr=0x%x mem=0x%x len=%d",
                              addr, buf_addr,size);
                              
        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,写之前先读出块,再写        
                if( blockaddr0 != sd_addr )
                {
                    if( AOS_FAIL == sd_read_block(blockaddr0,szBuf))
                    {
                        AOS_ASSERT(0);
                        return AOS_FAIL;
                    }    
                }        
                pSrc = (U8*)buf_addr;
                pDst = szBuf+ (sd_addr%BLOCK_SIZE);
                len  = BLOCK_SIZE-(sd_addr%BLOCK_SIZE);
                if( len > size )
                    len = size;
            }
            else if( off == blockaddr1 )
            {
                if( (blockaddr1 != sd_addr+size) &&
                    (blockaddr1 != blockaddr0) )
                {
                    if( AOS_FAIL == sd_read_block(blockaddr1,szBuf))
                    {
                           AOS_ASSERT(0);
                           return AOS_FAIL;
                    }                
                }
            
                // the last block
                pDst = szBuf;            
                len = (sd_addr+size)%BLOCK_SIZE;
            }

            aos_memcpy(pDst,pSrc,len);
            pSrc += len;
            
            if( AOS_SUCC != sd_write_block(off,szBuf) )
            {
                    AOS_ASSERT(0);
                    return AOS_FAIL;
            }
            hw_delay(100);
            pDst = szBuf;
            len  = BLOCK_SIZE;
        }
        
        return AOS_SUCC;
}
#else


/******************************************************************************
函数: sd_mem_write
描述:
       从SDRAM的相应源地址写数据到SD目的地址
输入:
       U32 buf_addr  将要读出数据的SDRAM源地址
       U32 addr      SD目的地址
       U32 size      数据大小 (字节数)
输出:
返回:
       如果成功,返回AOS_SUCC , 否则AOS_FAIL
******************************************************************************/
U32 sd_mem_write(U32 addr,U32 buf_addr,U32 size)
{
        U8  *pDst=NULL,*pSrc=NULL;
        U8  *pMidDst,*pMidSrc;
        U32 sd_addr;
        U32 blockaddr0,blockaddr1;
        U32 len=0;
        U32 blockcnt0,blockcnt;
        
        if( !sdcard_pos )
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        }

        aos_printf( MPE_DRV, "sd mem write addr=0x%x mem=0x%x len=%d",
                              addr, buf_addr,size);

        g_bFirstFlag =FALSE;
        g_bLastFlag  =FALSE;
        
        sd_addr = addr - SDCARD_BASE_ADDR;
        // 512字节对齐
        blockaddr0= sd_addr-(sd_addr%BLOCK_SIZE);
        blockaddr1= (sd_addr+size)-((sd_addr+size)%BLOCK_SIZE);    

        //计算连续写的SD卡的块数目
        blockcnt  = (blockaddr1-blockaddr0)/BLOCK_SIZE +1;
        // 出去前后两段中间段的块数目 
        blockcnt0 = blockcnt;
        
        // 写之前先读出块,擦除后再写        
        if( blockaddr0 != sd_addr )
        {
            //第一块
            if( AOS_FAIL == sd_read_block(blockaddr0,g_szBuf0))
            {
                AOS_ASSERT(0);
                return AOS_FAIL;
            }    
            // 第一块未对齐
            g_bFirstFlag = TRUE;    
            blockcnt--;
            
            pSrc = (U8*)buf_addr;
            pDst = g_szBuf0+ (sd_addr%BLOCK_SIZE);
            len  = BLOCK_SIZE-(sd_addr%BLOCK_SIZE);
            if( len > size )
                len = size;
            aos_memcpy(pDst,pSrc,len);
            pMidDst = (U8*)(blockaddr0 + BLOCK_SIZE);
            pMidSrc = pSrc+len;
          //  aos_printf( MPE_DRV, "First block read len=%d,MidDst=%x,MidSrc=%x",
                //                 len, pMidDst,pMidSrc);
        } 
        else
        {
            pMidDst = (U8*)blockaddr0;
            pMidSrc = (U8*)buf_addr;
        }

        if( (blockaddr1 != sd_addr+size) &&
            (blockaddr1 != blockaddr0) )
        {
            if( AOS_FAIL == sd_read_block(blockaddr1,g_szBuf1))
            {
                AOS_ASSERT(0);
                return AOS_FAIL;
            }    
            // 最后一块未对齐
            g_bLastFlag = TRUE;
            blockcnt--;
            
            len = (sd_addr+size)%BLOCK_SIZE; 
            pSrc= (U8*) (buf_addr+size-len);                        
            aos_memcpy(g_szBuf1,pSrc,len);
           // aos_printf( MPE_DRV, "last block read len=%d ",
                         //         len );        
        }

        /*
        // 写之前先擦除,提高效率
        if( AOS_FAIL == sd_erase_block(blockaddr0, blockaddr1) )
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        } 
        */
                    
        if( blockcnt0 > 1 )
        {    
            if( blockcnt )
            {
                if( AOS_SUCC != sd_write_multi_block((U32)pMidDst,
                                                     pMidSrc,blockcnt*BLOCK_SIZE) )
                {
                    AOS_ASSERT(0);
                    return AOS_FAIL;
                }
            }

            if( g_bFirstFlag )
            {
        	    sd_write_block(blockaddr0,g_szBuf0);	
            }

            if( g_bLastFlag )
            {
        	    sd_write_block(blockaddr1,g_szBuf1 );	            
            }
            
        }
        else
        {
            if( AOS_SUCC != sd_write_block((U32)pMidDst,pMidSrc) )
            {
                AOS_ASSERT(0);
                return AOS_FAIL;
            }
        }
            
        return AOS_SUCC;
}

#endif


/******************************************************************************
函数: sd_write_block
描述:
      写数据到SD的相应地址
输入:
      U32 addr  数据将要写到的地址
      U8 *buf   将要写出数据所在指针     
输出:
返回:
      如果成功,返回AOS_SUCC , 否则AOS_FAIL
******************************************************************************/
U32 sd_write_block(U32 addr, U8 *buf)
{	
	U8  status=10;
    U16 status_r2;
    // U16  crc_value;
    U32 i,result;
    U32 AgainCnt_write=0;
    aos_printf(MPE_DRV,"sd write a block addr=0x%x buf=0x%x",
                        addr, buf);
 
    if( addr%BLOCK_SIZE != 0 )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }            
     
again:
    clear_watch_dog();
	result = AOS_SUCC;
    
	CMD24_WRITE_SINGLE_BLOCK[1] = ((addr & 0xFF000000) >> 24);
	CMD24_WRITE_SINGLE_BLOCK[2] = ((addr & 0x00FF0000) >> 16);
	CMD24_WRITE_SINGLE_BLOCK[3] = ((addr & 0x0000FF00) >> 8);
	CMD24_WRITE_SINGLE_BLOCK[4] = ((addr & 0x000000FF));
	spi_enable_cs();

	// Send the write command
	for( i=0; i< 50; i++ )
	{
          	status = sd_write_command(CMD24_WRITE_SINGLE_BLOCK);
            if( status == 0 )
                 break;
	}	
	if( i == 50 )
	{
		// ABORT: invalid response for read single block command  
		AOS_ASSERT(0);
        result = AOS_FAIL;
        AgainCnt_write++;
        goto done;
	}
    
    //Nwr >8 clock
    hw_delay(100);
    
    // BLOCK  0xFE 2-513 CRC16  (515Bytes)
    // Now for the "Start Block" token	(0xFE)
    status = 0xFE;
    spi_write(&status,1);	   
    spi_write(buf,BLOCK_SIZE);	
 
    status=0xFF;
    spi_write(&status,1);
    spi_write(&status,1);    
   
     //wait data response
    i=0;
    do 
    {
           status = spi_read();  
           i++;
           if (i==800)
           {
                 AOS_ASSERT(0);
                 AgainCnt_write++;
                 result = AOS_FAIL;
                 goto done;
           }
    }
    while(!(((status&0x0F)==0x05)||(status==0)));
     //  aos_printf(MPE_DRV," write block data response  is 0x%x,time is %d",status,i); 
         
     //after  write block data response the first  busy 
    i=0;
    do 
    {
        status = spi_read();  
        i++;
         //16M i=6200   1G i=260  有快速卡和慢速卡,第一次写需要长一点
        if (i==15000)     
        {
                AOS_ASSERT(0);
                AgainCnt_write++;
                result = AOS_FAIL;
                goto done;
        }
    }
    while(status==0);
    // aos_printf(MPE_DRV,"after  write block data response the first  busy times is  %d",i);
   //测试时,写一次sd块不能当时读出,需要拔出再插入 ,才能读出,
   //cs 拉高,再cs使能,并判断是否busy
    spi_disable_cs();
    spi_enable_cs();
     
  //after  write block data response the last busy  
  i=0;
    do 
    {
        status = spi_read();  
        i++;
         if (i==2000)
        {
            AOS_ASSERT(0);
            goto done;
        }
    }
    while(status==0);
    //aos_printf(MPE_DRV,"after  write block data response the last busy times is  %d",i);
  
    // 等待R2应答  ,看写数据是否正确
	i=0;
	do
	{
	    status_r2 = sd_write_cmd_r2(CMD13_SEND_STATUS_BLOCK);
	    if (i==1000)
	    {
              AOS_ASSERT(0);
	          result = AOS_FAIL;
	          goto done;
	    }
	}
	while(status_r2 != 0);
	result = AOS_SUCC;
	//aos_printf(MPE_DRV,"after  write block read status times is  %d",i);
	
done:
     // Following a read transaction, the SD Card needs 8 clocks after the end 
	// bit of the last data block to finish up its work.	
  	status=0xFF;
  	spi_write(&status,1); 
  	spi_disable_cs();
  	
    if( (result == AOS_FAIL)&& ( AgainCnt_write< 3) )
    {        
        goto again;
    }        
       
	return result;
}

/******************************************************************************
函数: sd_write_multi_block
描述:
      写多块数据到SD的相应地址
输入:
       U32 addr  数据将要写到的地址
       U8 *buf   将要写出数据所在指针
       U32 len   数据长度,单位为字节数            
输出:
返回:
      如果成功,返回AOS_SUCC , 否则AOS_FAIL
******************************************************************************/
U32 sd_write_multi_block(U32 addr, U8 *buf, U32 len)
{
	U8  status;
    U16 status_r2;
	U32 i,j,result;
    aos_printf(MPE_DRV,"sd write multi block addr=0x%x buf=0x%x,len=%d",
                     addr, buf , len );
 
    if( addr%BLOCK_SIZE != 0 )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
 
    if( len%BLOCK_SIZE != 0 )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    clear_watch_dog();
       
	result = AOS_SUCC;
	CMD25_WRITE_MULTI_BLOCK[1] = ((addr & 0xFF000000) >> 24);
	CMD25_WRITE_MULTI_BLOCK[2] = ((addr & 0x00FF0000) >> 16);
	CMD25_WRITE_MULTI_BLOCK[3] = ((addr & 0x0000FF00) >> 8);
	CMD25_WRITE_MULTI_BLOCK[4] = ((addr & 0x000000FF));
	spi_enable_cs();

	// Send the write command
	for( i=0; i< 500; i++ )
	{
          	status = sd_write_command(CMD25_WRITE_MULTI_BLOCK);
            if( status == 0 )
                     break;

⌨️ 快捷键说明

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