MyFPGA Forum
标题:
关于DE2 板上SD卡的写操作
[打印本页]
作者:
jiayanfu
时间:
2010-5-4 08:39
标题:
关于DE2 板上SD卡的写操作
本帖最后由 jiayanfu 于 2010-5-4 08:59 编辑
DE2开发板上,对SD卡进行写操作。SD卡的文件系统是FAT16。
我对SD卡的初始化操作,以及SD卡的读操作,用的都是友晶提供的代码,程序运行都没有问题。写文件操作是自己根据SD卡的写时序 写的代码,但是总是写不成功。
见代码:
#ifndef __SD_Card_H__
#define __SD_Card_H__
//-------------------------------------------------------------------------
// SD Card Set I/O Direction
#define SD_CMD_IN IOWR(SD_CMD_BASE, 1, 0)
#define SD_CMD_OUT IOWR(SD_CMD_BASE, 1, 1)
#define SD_DAT_IN IOWR(SD_DAT_BASE, 1, 0)
#define SD_DAT_OUT IOWR(SD_DAT_BASE, 1, 1)
// SD Card Output High/Low
#define SD_CMD_LOW IOWR(SD_CMD_BASE, 0, 0)
#define SD_CMD_HIGH IOWR(SD_CMD_BASE, 0, 1)
#define SD_DAT_LOW IOWR(SD_DAT_BASE, 0, 0)
#define SD_DAT_HIGH IOWR(SD_DAT_BASE, 0, 1)
#define SD_CLK_LOW IOWR(SD_CLK_BASE, 0, 0)
#define SD_CLK_HIGH IOWR(SD_CLK_BASE, 0, 1)
// SD Card Input Read
#define SD_TEST_CMD IORD(SD_CMD_BASE, 0)
#define SD_TEST_DAT IORD(SD_DAT_BASE, 0)
//-------------------------------------------------------------------------
#define BYTE unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
//-------------------------------------------------------------------------
void Ncr(void);
void Ncc(void);
BYTE response_R(BYTE);
BYTE send_cmd(BYTE *);
BYTE SD_read_lba(BYTE *,UINT32,UINT32);
BYTE SD_card_init(void);
//-------------------------------------------------------------------------
BYTE read_status;
BYTE write_status;
BYTE response_buffer[20];
BYTE RCA[2];
BYTE cmd_buffer[5];
const BYTE cmd0[5] = {0x40,0x00,0x00,0x00,0x00};
const BYTE cmd55[5] = {0x77,0x00,0x00,0x00,0x00};
const BYTE cmd2[5] = {0x42,0x00,0x00,0x00,0x00};
const BYTE cmd3[5] = {0x43,0x00,0x00,0x00,0x00};
const BYTE cmd7[5] = {0x47,0x00,0x00,0x00,0x00};
const BYTE cmd9[5] = {0x49,0x00,0x00,0x00,0x00};
const BYTE cmd16[5] = {0x50,0x00,0x00,0x02,0x00};
const BYTE cmd17[5] = {0x51,0x00,0x00,0x00,0x00};
const BYTE cmd24[5] = {0x58,0x00,0x00,0x00,0x00};
const BYTE acmd6[5] = {0x46,0x00,0x00,0x00,0x01};////////set width //added by jiayanfu
const BYTE acmd41[5] = {0x69,0x0f,0xf0,0x00,0x00};
const BYTE acmd51[5] = {0x73,0x00,0x00,0x00,0x00};
//-------------------------------------------------------------------------
void Ncr(void)
{
SD_CMD_IN;
SD_CLK_LOW;
SD_CLK_HIGH;
SD_CLK_LOW;
SD_CLK_HIGH;
}
//-------------------------------------------------------------------------
void Ncc(void)
{
int i;
for(i=0;i<8;i++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
}
}
//-------------------------------------------------------------------------
BYTE SD_card_init(void)
{
BYTE x,y;
SD_CMD_OUT; //////////命令host to card added by jiayanfu
// SD_DAT_IN;
SD_CLK_HIGH;
SD_CMD_HIGH;
SD_DAT_LOW;
read_status=0;
for(x=0;x<40;x++)
Ncr();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd0[x];
y = send_cmd(cmd_buffer);
do
{
for(x=0;x<40;x++);
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd55[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1) //response too long or crc error
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=acmd41[x];
y = send_cmd(cmd_buffer);
Ncr();
} while(response_R(3)==1);
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd2[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(2)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd3[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(6)>1)
return 1;
RCA[0]=response_buffer[1];
RCA[1]=response_buffer[2];
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd9[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(2)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd7[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd16[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
read_status =1; //sd card ready
return 0;
}
//-------------------------------------------------------------------------
BYTE SD_read_block(alt_u16 block_number, alt_u8 *buff)
{
SD_CMD_OUT;
SD_DAT_IN;/////修改数据方向为IN card to host
BYTE c=0;
UINT32 i,j,lba;
lba = block_number *512;
{
Ncc();
cmd_buffer[0] = cmd17[0];
cmd_buffer[1] = (lba>>24)&0xff;
cmd_buffer[2] = (lba>>16)&0xff;
cmd_buffer[3] = (lba>>8)&0xff;
cmd_buffer[4] = lba&0xff;
send_cmd(cmd_buffer);
Ncr();
}
while(1)
{
SD_CLK_LOW;
SD_CLK_HIGH;
if((SD_TEST_DAT & 0x01) == 0)
break;
}
for(i=0;i<513;i++)
{
BYTE j;
for(j=0;j<8;j++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
c <<= 1;
if((SD_TEST_DAT & 0x01))
c |= 0x01;
}
*buff=c;
buff++;
}
for(i=0; i<16; i++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
}
read_status = 1; //SD data next in
return 0;
}
//-------------------------------------------------------------------------
BYTE response_R(BYTE s)
{
BYTE a=0,b=0,c=0,r=0,crc=0;
BYTE i,j=6,k;
while(1)
{
SD_CLK_LOW;
SD_CLK_HIGH;
if(!(SD_TEST_CMD))
break;
if(crc++ >100)
return 2;
}
crc =0;
if(s == 2)
j = 17;
for(k=0; k<j; k++)
{
c = 0;
if(k > 0) //for crc culcar
b = response_buffer[k-1];
for(i=0; i<8; i++)
{
SD_CLK_LOW;
if(a > 0)
c <<= 1;
else
i++;
a++;
SD_CLK_HIGH;
if(SD_TEST_CMD)
c |= 0x01;
if(k > 0)
{
crc <<= 1;
if((crc ^ b) & 0x80)
crc ^= 0x09;
b <<= 1;
crc &= 0x7f;
}
}
if(s==3)
{
if( k==1 &&(!(c&0x80)))
r=1;
}
response_buffer[k] = c;
}
if(s==1 || s==6)
{
if(c != ((crc<<1)+1))
r=2;
}
return r;
}
//return crc-------------------------------------------------------------------------
BYTE send_cmd(BYTE *in)
{
int i,j;
BYTE b,crc=0;
SD_CMD_OUT; ///////////cmd from host to card
for(i=0; i < 5; i++)
{
b = in
;
/////////// when up_edge of host clock send the cmd
///////////added by jiayanfu
for(j=0; j<8; j++)
{
SD_CLK_LOW;
if(b&0x80)
SD_CMD_HIGH;
else
SD_CMD_LOW;
crc <<= 1;
SD_CLK_HIGH;
if((crc ^ b) & 0x80) /////CRC校验,x7+x3+1,即生成多项式代码为0x8009
crc ^= 0x09;
b<<=1;
}
crc &= 0x7f;
}
crc =((crc<<1)|0x01);
b = crc;
for(j=0; j<8; j++)
{
SD_CLK_LOW;
if(crc&0x80)
SD_CMD_HIGH;
else
SD_CMD_LOW;
SD_CLK_HIGH;
crc<<=1;
}
return b;
}
//-------------------------SD_write_lba----------------------------------------
BYTE SD_write_block(alt_u16 block_number, alt_u8 *buff)
{
BYTE b,crc=0;
///////////修改数据方式为out方式,即写方式。
SD_DAT_OUT;
UINT32 i,k,lba;
lba = block_number * 512;
Ncc();
cmd_buffer[0] = cmd24[0];
cmd_buffer[1] = (lba>>24)&0xff;
cmd_buffer[2] = (lba>>16)&0xff;
cmd_buffer[3] = (lba>>8)&0xff;
cmd_buffer[4] = lba&0xff;
send_cmd(cmd_buffer);
Ncr();
for(i=0; i < 512; i++)
{
b = buff [ i ];
for(k=0; k<8; k++)
{
SD_CLK_LOW;
if(b&0x80)
SD_DAT_HIGH;
else
SD_DAT_LOW;
crc <<= 1;
//SD_CLK_LOW;
SD_CLK_HIGH;
if((crc ^ b) & 0x80)
crc ^= 0x09;
b<<=1;
}
crc &= 0x7f;
}
crc =((crc<<1)|0x01); ////////////end bit "1" added by jiayanfu
for(k=0; k<8; k++)
{
SD_CLK_LOW;
if(crc&0x80)
SD_DAT_HIGH;
else
SD_DAT_LOW;
SD_CLK_HIGH;
crc<<=1;
}
SD_DAT_IN; ///////////修改数据方向为in 即card to host,读取CRC status
for(i=0; i<16; i++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
}
write_status = 1;
return 0;
}
//-------------------------------------------------------------------------
#endif
作者:
jiayanfu
时间:
2010-5-4 08:40
主函数如下:
int main(void)
{
UINT16 block_num = 2460;
UINT32 i = 0;
BYTE Buf_write[512]={0,1,2,3,4,5,6,7};
BYTE Buf_read[513]={0};
while(SD_card_init())
usleep(500000);
while(1)
{
SD_write_block(block_num,Buf_write);
SD_read_block(block_num,Buf_read);
block_num++;
}
printf("successful");
}
作者:
jiayanfu
时间:
2010-5-4 08:48
本帖最后由 jiayanfu 于 2010-5-4 09:23 编辑
在SD_write_block()时,(红色字体显示)把512字节数据写完毕,然后把CRC校验码也发送到DAT0上,然后应该根据SD卡的写时序的话,发送两个时钟周期之后,CRC校验正确的话CRC status 应该为“010”,不正确的话 CRC status 应该为“101”,如果正确,数据开始program,数据在program的时候出错的话,DAT0应该一直为高,自己通过signal tap 调试发现,在发送完两个时钟周期之后,DAT0一直为高。CRC校验错误?还是正确?还是已经开始数据program,编程错误了呢??????????不解中。。。。。。。。。。。
那个SD卡我已经拨到了“unlock”状态了。。。。
作者:
withoutwing
时间:
2010-5-16 21:56
我也在学习SD卡的读写和文件系统的移植,不过目前对友晶提供的代码不是很理解,尤其是CRC部分和response。可否求教于你呢?谢谢!
作者:
jiayanfu
时间:
2010-5-17 18:50
本帖最后由 jiayanfu 于 2010-5-17 18:54 编辑
回复
4#
withoutwing
好啊,一起交流吧,可以提供给你所有可以提供的。
SD的读写命令基本已经掌握了,貌似现在卡在了写数据的时候的那个CRC的计算上有误。。。
有问题,可以发邮件(首选):
yanfu_Jia@163.com
也可以加我QQ:710480120
作者:
jiayanfu
时间:
2010-5-18 09:22
问题搞定,见
http://www.myfpga.org/discuz/viewthread.php?tid=19312
作者:
withoutwing
时间:
2010-5-18 16:02
回复
5#
jiayanfu
我的QQ:76563135。加你的Q要回答问题
一起交流下,共同学习相互鼓劲。
作者:
WPZAC
时间:
2010-7-6 20:50
回复
1#
jiayanfu
DE0_NIOS_SDCARD范例里面的一个文件(SD_Driver.c)和此段代码一样,而版主的这段代码是不是“SD写”的代码而非SD驱动代码啊?不理解!
请问,这段代码是SD驱动代码吗?还是SD写代码?
作者:
withoutwing
时间:
2010-7-6 22:39
这是写函数部分。
作者:
WPZAC
时间:
2010-7-7 09:24
回复
9#
withoutwing
请问,SDCARD驱动该如何操作?有相关的代码可以给我参考下吗,不盛感激啊!!多谢。
期待中,THANK YOU!!!
作者:
WPZAC
时间:
2010-7-18 10:29
回复
7#
withoutwing
有个地方一直不太明白:如何把我的数据给SD,好存到卡里面????
#define SD_CMD_IN IOWR_ALTERA_AVALON_PIO_DIRECTION(SD_CMD_BASE, ALTERA_AVALON_PIO_DIRECTION_INPUT)
#define SD_CMD_OUT IOWR_ALTERA_AVALON_PIO_DIRECTION(SD_CMD_BASE, ALTERA_AVALON_PIO_DIRECTION_OUTPUT)
#define SD_DAT_IN IOWR_ALTERA_AVALON_PIO_DIRECTION(SD_DAT_BASE, ALTERA_AVALON_PIO_DIRECTION_INPUT)
#define SD_DAT_OUT IOWR_ALTERA_AVALON_PIO_DIRECTION(SD_DAT_BASE, ALTERA_AVALON_PIO_DIRECTION_OUTPUT)
是不是这些赋值语句呢?????从总线取得数据送往SD存储???谢谢。
作者:
withoutwing
时间:
2010-7-18 20:04
回复
11#
WPZAC
SD卡是一次512个字节的操作,用个buffer存你要写的数,然后写进SD卡。
作者:
IamDavid
时间:
2010-7-21 10:32
学习...纠结的SD
作者:
tornadomeet
时间:
2011-5-9 09:24
友晶提供的代码中根本没有用到CS脚,怎么能成功呢?我试了n次都是失败的
欢迎光临 MyFPGA Forum (http://www.myfpga.org/discuz/)
Powered by Discuz! X3