• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 基于ARM含SD控制器的SD卡的SDIO模式驅動解析

    基于ARM含SD控制器的SD卡的SDIO模式驅動解析

    作者: 時間:2016-12-08 來源:網絡 收藏

      SD卡由日本松下、東芝及美國SanDisk公司于1999年8月共同開發研制。

    本文引用地址:http://www.czjhyjcfj.com/article/201612/341311.htm

      SD卡的結構能保證數字文件傳送的安全性,也很容易重新格式化,因此越來越多的被應用的嵌入式系統中。

      SD卡的使用非常方便,常見的有兩種工作模式:SPI和。SPI是串行的工作模式,速度相對較低,但是使用方便,只要MCU含有SPI接口均可使用。模式,可以最多4線傳輸,因此速度比較快,由于SD卡的普及,越來越多的MCU內部集成了控制器,簡化了我們的工作。本文以三星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

      }

      rSDICSTA=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;

      }



    關鍵詞: ARM SDIO

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 绥宁县| 无为县| 天柱县| 龙胜| 扶余县| 安庆市| 南澳县| 巴里| 蓝山县| 东山县| 井冈山市| 揭西县| 瓦房店市| 宣化县| 互助| 新泰市| 张家口市| 石林| 伊宁县| 嘉祥县| 崇礼县| 乌海市| 凭祥市| 新民市| 白山市| 芜湖县| 崇仁县| 二连浩特市| 秀山| 定陶县| 河津市| 会泽县| 嘉荫县| 都兰县| 新野县| 濮阳县| 斗六市| 龙口市| 泸溪县| 阜宁县| 朝阳区|