您的位置 首页 开关

根据ARM含SD控制器的SD卡的SDIO形式驱动解析

SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。SD卡的结构能保证数字文件传送的安全性,也很容易重新格式化,因此越来越多的被应用的嵌入式系统中。SD卡的使用非常

  SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研发。

  SD卡的结构能确保数字文件传送的安全性,也很简单从头格式化,因而越来越多的被运用的嵌入式体系中。

  SD卡的运用十分便利,常见的有两种作业方法:SPI和SDIO。SPI是串行的作业方法,速度相对较低,可是运用便利,只需MCU含有SPI接口均可运用。SDIO方法,能够最多4线传输,因而速度比较快,因为SD卡的遍及,越来越多的MCU内部集成了SDIO操控器,简化了咱们的作业。本文以三星s3c2410为例介绍。

  1. SD卡的接口电路

    

 

  2. SD卡的协议

  SD卡的操控指令十分强壮,支撑SPI,SDIO方法,兼容MMC等。并且不同的

  指令有不同的呼应(3种),这在咱们运用指令是要注意的。我在附件里边放了一个SD卡的中文协议,包含数据包介绍,指令索引介绍,反应介绍等。

  3. S3C2410 SD卡操控器的介绍

  SD卡操控器帮咱们完结了协议上的许多作业,咱们只需要依照协议装备寄存器

  以及依照协议流程对SD卡操作就能够完结SD卡的功用了。

  SDICON:完结SD卡根底装备,包含巨细端,中止答应,方法挑选,时钟使能等。

  SDIPRE:对SDCLK的装备。

  SDICARG:指令的参数寄存在这儿

  SDICCON:操控指令方法的寄存器,装备SPI仍是SDI指令,指令的反应长度,是否等候反应,是否运转指令,指令的索引等

  SDICSTA:指令状况寄存器,指令是否超时,传送,完毕,CRC是否正确等

  SDIRSPO:反映SD的状况

  SDITIMER:设置超时时刻

  SDIBSIZE:block的巨细

  SDIDCON:数据操控寄存器,装备是几线传输,数据发送方向,数据传送方法等。

  SDIDSTA: 数据状况寄存器,数据是否发送完,CRC效验,超时等

  SDIFSTA: FIFO状况积存器,DMA传输时否判别FIFO

  SDIMSK:中止屏蔽

  4. SD卡SDIO方法的驱动剖析

  4.1 SD卡的初始化

  过程是:1)装备时钟,慢速一般为400K,设置作业方法

  2)发送CMD0,进入闲暇态,该指令没有反应

  3)发送CMD55+ACMD41,判别SD卡的上电是否正确,短反应

  4)发送CMD2,验证SD卡是否接入,长反应

  5)发送CMD3,读取SD卡的RCA(地址),短反应

  6)发送CMD7,使能SD卡

  7)装备高速时钟,预备数据传输,一般20M~25M

  8)发送CMD55+ACMD6装备为4bit数据传输方法

  代码如下:

  int SD_card_init(void)

  {

  int i;

  char key;

  rSDIPRE=PCLK/(2*INICLK)-1; //时钟 400KHz

  rSDICON=(1<<4)|(1<<1)|1; // Type B, FIFO reset, clk enable

  rSDIBSIZE=0x200; // 512byte(128word)

  rSDIDTIMER=0xffff; // Set timeout count

  for(i=0;i<0x1000;i++); // Wait 74SDCLK for MMC card

  CMD0(); //进入idle

  //– Check SD card OCR

  if(Chk_SD_OCR()) //发送AM41,判别电压正确否

  ;

  else

  {

  ;

  return 0;

  }

  RECMD2:

  rSDICARG=0x0;

  // CMD2(stuff bit),判别衔接

  rSDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x42;

  //lng_resp, wait_resp, start, CMD2

  //– Check end of CMD2

  if(!Chk_CMDend(2, 1)) //查询反应是否正确

  goto RECMD2;

  RECMD3:

  //–Send RCA,得到SD卡的地址

  rSDICARG=MMC<<16;

  // CMD3(MMC:Set RCA, SD:Ask RCA–>SBZ)

  rSDICCON=(0x1<<9)|(0x1<<8)|0x43;

  // sht_resp, wait_resp, start, CMD3

  //– Check end of CMD3

  if(!Chk_CMDend(3, 1))

  goto RECMD3;

  //–Publish RCA

  RCA=( rSDIRSP0 & 0xffff0000 )>>16;

  //–State(stand-by) check

  if( rSDIRSP0 & 0x1e00!=0x600 )

  // CURRENT_STATE check 验证反应

  goto RECMD3;

  rSDIPRE=PCLK/(2*NORCLK)-1;

  // 设置高速时钟Normal clock="25MHz"

  Card_sel_desel(1); // Select SD

  Set_4bit_bus(); //设置为4bit方法

  }

  void Set_4bit_bus(void)

  {

  Wide=1;

  SetBus();

  }

  void SetBus(void)

  {

  SET_BUS:

  CMD55();

  // Make ACMD

  //– CMD6 implement

  rSDICARG=Wide<<1;

  //Wide 0: 1bit, 1: 4bit

  rSDICCON=(0x1<<9)|(0x1<<8)|0x46;

  //sht_resp, wait_resp, start, CMD55

  if(!Chk_CMDend(6, 1)) // ACMD6

  goto SET_BUS;

  }

  4.2SD卡的读与写

  读写便是正反向的问题,这儿只剖析读

  过程:1)读单block CMD17 多block CMD18

  (写单block CMD24 多block CMD25)

  2)发送CMD12,停止数据传输

  程序如下:选用DMA方法

  void Rd_Block(void)

  {

  int status;

  rd_cnt=0;

  rSDICON |= rSDICON|(1<<1); // FIFO reset

  rSDICARG=0x0; // CMD17/18(addr参数)

  RERDCMD:

  pISR_DMA0=(unsigned)DMA_end; //DMA的相关装备

  rINTMSK = ~(BIT_DMA0);

  rDISRC0=(int)(SDIDAT); // SDIDAT

  rDISRCC0=(1<<1)+(1<<0); // APB, fix

  rDIDST0=(U32)(Rx_buffer); // Rx_buffer

  rDIDSTC0=(0<<1)+(0<<0); // AHB, inc

  rDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;

  //handshake, sync PCLK, TC int, single tx, single service, SDI, H/W request,

  //auto-reload off, word, 128blk*num

  rDMASKTRIG0=(0<<2)+(1<<1)+0;

  //no-stop, DMA2 channel on, no-sw trigger

  rSDIDCON=(1<<19)|(1<<17)|(Wide<<16)|(1<<15)|(2<<12)|(block<<0);

  // Rx after rsp, blk, 4bit bus, dma enable, Rx start, blk num

  if(block<2) // SINGLE_READ

  {

  rSDICCON=(0x1<<9)|(0x1<<8)|0x51;

  // sht_resp, wait_resp, dat, start, CMD17

  if(!Chk_CMDend(17, 1))

  //– Check end of CMD17

  goto RERDCMD;

  }

  else // MULTI_READ

  {

  rSDICCON=(0x1<<9)|(0x1<<8)|0x52;

  // sht_resp, wait_resp, dat, start, CMD18

  if(!Chk_CMDend(18, 1))

  //– Check end of CMD18

  goto RERDCMD;

  }

  while(!TR_end);

  rINTMSK |= (BIT_DMA0);

  TR_end=0;

  rDMASKTRIG0=(1<<2); //DMA0 stop

  break;

  default:

  break;

  }

  //– Check end of DATA

  if(!Chk_DATend())

  ;

  rSDIDSTA=0x10; // Clear data Tx/Rx end

  if(block>1)

  {

  RERCMD12:

  //–Stop cmd(CMD12)

  rSDICARG=0x0; //CMD12(stuff bit)

  rSDICCON=(0x1<<9)|(0x1<<8)|0x4c;

  //sht_resp, wait_resp, start, CMD12

  //– Check end of CMD12

  if(!Chk_CMDend(12, 1))

  goto RERCMD12;

  }

  }

  4.3上面用到的呼应判别函数

  首要完结对反应状况的剖析。

  函数如下:

  int Chk_CMDend(int cmd, int be_resp) //指令反应判别函数

  {

  int finish0;

  if(!be_resp) // No response

  {

  finish0=rSDICSTA;

  while((finish0&0x800)!=0x800) // 验证指令是不是发送

  finish0=rSDICSTA;

  rSDICSTA=finish0; // Clear cmd end state

  return 1;

  }

  else // With response

  {

  finish0=rSDICSTA;

  while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x400) ))

  // 验证反应呼应完结

  finish0=rSDICSTA;

  if(cmd==1 | cmd==9 | cmd==41) // CRC no check

  {

  if( (finish0&0xf00) != 0xa00 ) // CRC是否过错

  {

  rSDICSTA=finish0; // Clear error state

  if(((finish0&0x400)==0x400)) // 验证超时

  return 0; }

  rSDICSTA=finish0;

  // Clear cmd & rsp end state

  }

  else // CRC check

  {

  if( (finish0&0x1f00) != 0xa00 ) // Check error

  {

  ;

  rSDICSTA=finish0; // Clear error state

  if(((finish0&0x400)==0x400))

  return 0; // Timeout error

  }

  rSD%&&&&&%STA=finish0;

  }

  return 1;

  }

  }

  int Chk_DATend(void)

  {

  int finish;

  finish=rSDIDSTA;

  while( !( ((finish&0x10)==0x10) | ((finish&0x20)==0x20) ))

  // Chek timeout or data end

  finish=rSDIDSTA;

  if( (finish&0xfc) != 0x10 )

  {

  rSDIDSTA=0xec; // Clear error state

  return 0;

  }

  return 1;

  }

  int Chk_BUSYend(void) //数据反应判别函数

  {

  int finish;

  finish=rSDIDSTA;

  while( !( ((finish&0x08)==0x08) | ((finish&0x20)==0x20) ))

  finish=rSDIDSTA; //等候数据发送完结或超时

  if( (finish&0xfc) != 0x08 )

  {

  rSD

  IDSTA=0xf4; //clear error state

  return 0;

  }

  return 1;

  }

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/kaiguan/241553.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部