新聞中心

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

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

        作者: 時間:2016-11-11 來源:網絡 收藏
        SD卡由日本松下、東芝及美國SanDisk公司于1999年8月共同開發研制。

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

        本文引用地址:http://www.104case.com/article/201611/316808.htm

        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.1SD卡的初始化

        步驟是: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

        //--CheckSDcard 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:SetRCA,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;

        }



        關鍵詞: ARMSD控制器SDIO模

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 天峻县| 卓资县| 孝感市| 昌吉市| 包头市| 浦北县| 大洼县| 福泉市| 石家庄市| 海门市| 鄄城县| 静宁县| 抚松县| 河南省| 堆龙德庆县| 常州市| 抚顺市| 股票| 西贡区| 宿州市| 邯郸县| 宁津县| 杭锦旗| 秦安县| 湟源县| 烟台市| 疏附县| 黄龙县| 漳浦县| 香格里拉县| 德钦县| 庄河市| 津市市| 紫阳县| 禹城市| 旺苍县| 吴江市| 徐州市| 武鸣县| 怀集县| 定结县|