📄 sd_drv.c
字号:
}
//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 + -