MyFPGA Forum

 找回密码
 注册
搜索
查看: 10863|回复: 13
打印 上一主题 下一主题

关于DE2 板上SD卡的写操作

[复制链接]
跳转到指定楼层
1#
发表于 2010-5-4 08:39:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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
2#
 楼主| 发表于 2010-5-4 08:40:45 | 只看该作者
主函数如下:
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");

}
3#
 楼主| 发表于 2010-5-4 08:48:14 | 只看该作者
本帖最后由 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”状态了。。。。
4#
发表于 2010-5-16 21:56:29 | 只看该作者
我也在学习SD卡的读写和文件系统的移植,不过目前对友晶提供的代码不是很理解,尤其是CRC部分和response。可否求教于你呢?谢谢!
5#
 楼主| 发表于 2010-5-17 18:50:51 | 只看该作者
本帖最后由 jiayanfu 于 2010-5-17 18:54 编辑

回复 4# withoutwing


    好啊,一起交流吧,可以提供给你所有可以提供的。
  SD的读写命令基本已经掌握了,貌似现在卡在了写数据的时候的那个CRC的计算上有误。。。
有问题,可以发邮件(首选):yanfu_Jia@163.com
也可以加我QQ:710480120
6#
 楼主| 发表于 2010-5-18 09:22:07 | 只看该作者
7#
发表于 2010-5-18 16:02:55 | 只看该作者
回复 5# jiayanfu

我的QQ:76563135。加你的Q要回答问题
一起交流下,共同学习相互鼓劲。
8#
发表于 2010-7-6 20:50:02 | 只看该作者
回复 1# jiayanfu


    DE0_NIOS_SDCARD范例里面的一个文件(SD_Driver.c)和此段代码一样,而版主的这段代码是不是“SD写”的代码而非SD驱动代码啊?不理解!
   请问,这段代码是SD驱动代码吗?还是SD写代码?
9#
发表于 2010-7-6 22:39:05 | 只看该作者
这是写函数部分。
10#
发表于 2010-7-7 09:24:11 | 只看该作者
回复 9# withoutwing


    请问,SDCARD驱动该如何操作?有相关的代码可以给我参考下吗,不盛感激啊!!多谢。
期待中,THANK YOU!!!
11#
发表于 2010-7-18 10:29:55 | 只看该作者
回复 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存储???谢谢。
12#
发表于 2010-7-18 20:04:50 | 只看该作者
回复 11# WPZAC
SD卡是一次512个字节的操作,用个buffer存你要写的数,然后写进SD卡。
13#
发表于 2010-7-21 10:32:46 | 只看该作者
学习...纠结的SD
14#
发表于 2011-5-9 09:24:17 | 只看该作者
友晶提供的代码中根本没有用到CS脚,怎么能成功呢?我试了n次都是失败的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|MyFPGA

GMT+8, 2024-5-3 06:45 , Processed in 0.034869 second(s), 15 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表