SDIO驅動的命令從何玩起?

SDIO 

       SDIO 卡是在 SD 內存卡接口的基礎上發展起來的接口, SDIO 接口兼容以前的 SD 內存卡,並且可以連接 SDIO 接口的設備,目前根據 SDIO 協議的 SPEC  SDIO 接口支持的設備總類有藍牙,網卡,電視卡等。

       SDIO 協議是由 SD 卡的協議演化升級而來的,很多地方保留了 SD 卡的讀寫協議,同時 SDIO 協議又在 SD 卡協議之上添加了 CMD52  CMD53 命令。由於這個, SDIO  SD 卡規範間的一個重要區別是增加了低速標準,低速卡的目標應用是以最小的硬件開始來支持低速 I/O 能力。低速卡支持類似調制解調器 , 條形碼掃描儀和 GPS 接收器等應用。高速卡支持網卡,電視卡還有“組合”卡等,組合卡指的是存儲器 +SDIO 

       SDIO  SD 卡的 SPEC 間的又一個重要區別是增加了低速標準。 SDIO 卡只需要 SPI  1  SD 傳輸模式。低速卡的目標應用是以最小的硬件開支來支持低速 I/O 能力,低速卡支持類似 MODEM ,條形掃描儀和 GPS 接收器等應用。對組合卡來說,全速和 4BIT 操作對卡內存儲器和 SDIO 部分都是強制要求的。

       在非組合卡的 SDIO 設備裏,其最高速度要只有達到 25M ,而組合卡的最高速度同 SD 卡的最高速度一樣,要高於25M 

 

SDIO 總線

       SDIO 總線和 USB 總線類似, SDIO 總線也有兩端,其中一端是主機( HOST )端,另一端是設備端( DEVICE ),採用 HOST- DEVICE 這樣的設計是爲了簡化 DEVICE 的設計,所有的通信都是由 HOST 端發出命令開始的。在 DEVICE 端只要能解溪 HOST 的命令,就可以同 HOST 進行通信了。

       SDIO  HOST 可以連接多個 DEVICE ,如下圖所示 :

 

 

       這個是同 SD 的總線一樣的 , 其中有如下的幾種信號

1.        CLK 信號 :HOST  DEVICE 的時鐘信號 .

2.        CMD 信號:雙向的信號,用於傳送命令和反應。

3.        DAT0-DAT3 信號 : 四條用於傳送的數據線。

4.        VDD 信號 : 電源信號。

5.        VSS1  VSS2: 電源地信號。

 SDIO 總線定義中 ,DAT1 信號線複用爲中斷線。在 SDIO  1BIT 模式下 DAT0 用來傳輸數據, DAT1 用作中斷線。在 SDIO  4BIT 模式下 DAT0-DAT3 用來傳輸數據,其中 DAT1 複用作中斷線。

 

SDIO 命令:

       SDIO 總線上都是 HOST 端發起請求,然後 DEVICE 端迴應請求。其中請求和迴應中會數據信息。

1.        Command: 用於開始傳輸的命令,是由 HOST 端發往 DEVICE 端的。其中命令是通過 CMD 信號線傳送的。

2.        Response: 迴應是 DEVICE 返回的 HOST 的命令,作爲 Command 的迴應。也是通過

CMD 線傳送的。

3.        Data: 數據是雙向的傳送的。可以設置爲 1 線模式,也可以設置爲 4 線模式。數據是通過 DAT0-DAT3 信號線傳輸的。

   SDIO 的每次操作都是由 HOST  CMD 線上發起一個 CMD ,對於有的 CMD  DEVICE 需要返回 Response ,有的則不需要。

       對於讀命令,首先 HOST 會向 DEVICE 發送命令,緊接着 DEVICE 會返回一個握手信號,此時,當 HOST 收到迴應的握手信號後,會將數據放在 4 位的數據線上,在傳送數據的同時會跟隨着 CRC 校驗碼。當整個讀傳送完畢後, HOST 會再次發送一個命令,通知 DEVICE 操作完畢, DEVICE 同時會返回一個響應。

       對於寫命令,首先 HOST 會向 DEVICE 發送命令,緊接着 DEVICE 會返回一個握手信號,此時,當 HOST 收到迴應的握手信號後,會將數據放在 4 位的數據線上,在傳送數據的同時會跟隨着 CRC 校驗碼。當整個寫傳送完畢後, HOST 會再次發送一個命令,通知 DEVICE 操作完畢, DEVICE 同時會返回一個響應。

 

SDIO 的寄存器:

      SDIO 卡的設備驅動 80% 的任務就是操作 SDIO 卡上的有關寄存器。 SDIO 卡最多允許有 7 個功能( function  ,這個同其功能號是對應的( 0  7  , 每個功能都對應一個 128K 字節大小的寄存器,這個見下面的圖。功能號之所以取值範圍是 1~7 ,而沒有包含 0 ,是因爲功能 0 並不代表真正的功能,而代表 CIA 寄存器,即 Common I/O Area ,這個紀錄着 SDIO 卡的一些基本信息和特性,並且可以改寫這些寄存器。其中地址 0x1000~0x17fff  SDIO 卡的 CIS 區域,就是基本信息區域, Common Information Structure 。初始化的時候讀取並配對 SDIO 設備。

       這些寄存器的詳細分區已經其對應的功能,在開發過程中都是需要仔細研讀的,這些都在協議的 SPEC 中都有詳細說明,這裏就不在羅索了。  

 

CMD52 命令:

SDIO 設備爲了和 SD 內存卡兼容, SD 卡所有 Command  Response 完全兼容,同時加入了一些新的 Command Response 。例如,初始化 SD 內存卡使用 ACMD41 ,而 SDIO 卡設備則用 CMD5 通知 DEVICE 進行初始化。

但二者最重要的區別是, SDIO 卡比 SD 內存卡多了 CMD52  CMD53 命令,這兩個命令可以方便的訪問某個功能的某個地址寄存器。

CMD52 命令是 IO_RW_DIRECT 命令的簡稱,其命令格式如下

 

首先第一位爲 0, 表明是起始位,第二位爲傳輸方向,這裏爲 1 ,代表方向爲 HOST  DEVICE 設備傳送,其後 6 位爲命令號,這裏是 110100b ,用十進制表示爲 52  CMD52 的名字也由此而來。緊接着是讀寫標誌位。

      然後是操作的功能號。也就是 function   number 。如果爲 0 則指示爲 CCCR 寄存器組。

       緊接着是寄存器地址,用 17 指示,由於功能寄存器有 128K 地址, 17 位正好能尋址。

       再下來 8  Write data or Staff Bits 的意思是說,如果當前爲寫操作,則爲數據,否則 8 位爲填充位。無意義。

       最後 7 位爲 CRC 校驗碼。最後一位爲結束位 0 

       對於 CMD52  Response  48 位,命令格式如下:

 

       總結下, CMD52 是由 HOST 發往 DEVICE 的,它必須有 DEVICE 返回來的 Response  CMD52 不需要佔用DAT 線,讀寫的數據是通過 CMD52 或者 Response 來傳送。每次 CMD52 只能讀或者寫一個 byte 

 

CMD53 命令:

CMD52 每次只能讀寫一個字節,因爲有了 CMD53 對讀寫進行了擴展, CMD53 允許每次讀寫多個字節或者多個塊(BLOCK)  CMD53 的命令格式如下:

 

       第一位是 1, 爲開始位,然後是一位方向位,總是 1 ,代表方向爲 HOST  DEVICE 設備傳送,其後 6 位爲命令號,這裏是 110101b ,用十進制表示爲 53  CMD53 的名字也由此而來。

       然後是 1 位的讀寫標誌。接着是 3 位功能號,這個同 CMD52 都是相同的。 Block   Mode 如果 1 代表是塊傳輸模式,否則爲字節傳輸模式。

       OP Code 爲操作位,如果是 0 ,代表數據往固定的位置讀寫,如果 1 代表是地質增量讀寫。例如,對地址 0 固定讀寫16 個字節,相當於 16 次讀寫的地址 0 ,而對地址 0 增量讀寫 16 個字節,相當於讀寫 0~15 地址的數據。

       然後是 17 位的地址寄存器,可以尋址到 128K 字節的地址,然後是 9 位的讀寫的計數,對於字節讀取,讀寫大小就是這個計數,而對於塊讀寫,讀寫的大小是計數乘以塊的大小。

       隨後的 7 位爲 CRC 校驗碼。最後一位爲 1 

       當讀寫操作是塊操作的時候,塊的大小是可以通過設置 FBR 中的相關寄存器來設置。

        CMD52 命令不同的是, CMD53 沒有返回的命令的,這裏判斷是否 DEVICE 設備讀寫完畢是需要驅動裏面自己判斷的,一般有 2 個方法, 1. 設置相應的讀寫完畢中斷。如果 DEVICE 設備讀寫完畢,則對 HOST 設備發送中斷。 2.HOST 設備主動查詢 DEVICE 設備是否讀寫完畢,可以通過 CMD 命令是否有返回來判斷是否 DEVICE 是否讀寫完畢。

——————————————————————————————————————

瞭解了SDIO總線命令的基礎知識,下面看一個具體的基於s3c2440平臺的mmc/sd卡驅動實例,會用到sd卡的命令字,對sdio的命令字道理也是差不多的:

發現了兩篇講SD/MMC卡驅動的文章,覺得不錯,轉了過來,謝謝原作者
文一:FROM:http://blog.chinaunix.net/u2/69999/showart_734099.html

 關於linux 2.6 mmc/sd驅動    

 linux 2.6 中的mmc/sd驅動分爲以下幾方面的內容        

1. sysfs 層的總線類型處理: 註冊一組 mmc 類型處理函數, 標誌爲 "mmc"    

   具體在mmc_sysfs.c文件中實現
 

2. mmc/sd 快設備管理:註冊一個塊設備和一組 mmc 總線類型的 driver 子函數, 實現塊設備的隊列管理等      

drivers/mmc/mmc_block.c

3. mmc/sd host管理: 實現 host 的管理 

. drivers/mmc/mmc.c:主要的 MMC command 與 protocol 實作。

4. 針對特定的mcu實現一個host驅動實例:主要是註冊一個 host實體,中斷處理函數,io設置函數,請求處理函數等    

       以上1.2.3基本是不需要修改的,需要處理的就是 4.要做的工作.當有卡插入時,由4中實現的插卡中斷激活卡初始化程序和總線探測函數. 由mmc總線探測函數會調用塊設備的探測函數,在卡設備探測函數中會初始化塊設備的請求隊列和註冊一個gendisk實體(以後文件系統會通過 gendisk實體訪問 mmc 塊設備),同時在sysfs中建立真正的 mmc/sd 設備.塊設備通過具體的 host 註冊的io設置函數和請求函數與具體的host通訊.

後面的文章將具體對幾個部分進行分析
-----------------------------------------------------------------------------
文二:
FROM:http://blog.chinaunix.net/u1/42456/showart_516030.html

最近要讓s3c2440在linux2.6.18上 支持4G的SD卡.

原文地址:http://linux4u.wikidot.com/mmc-controller-driver

==============================================================

linux-2.6.2x的mmc驅動與linux-2.6.1x的mmc驅動的區別
在linux-2.6.2x中,mmc驅動用到的block_device_operations結構已重新定義,請看:
linux-2.6.1x:

struct block_device_operations {
    int (*open) (struct inode *, struct file *);
    int (*release) (struct inode *, struct file *);
    int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
    int (*media_changed) (struct gendisk *);
    int (*revalidate_disk) (struct gendisk *);
    struct module *owner;
};

linux-2.6.2x

struct block_device_operations {
    int (*open) (struct inode *, struct file *);
    int (*release) (struct inode *, struct file *);
    int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
    long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
    long (*compat_ioctl) (struct file *, unsigned, unsigned long);
    int (*direct_access) (struct block_device *, sector_t, unsigned long *);
    int (*media_changed) (struct gendisk *);
    int (*revalidate_disk) (struct gendisk *);
    int (*getgeo)(struct block_device *, struct hd_geometry *);
    struct module *owner;
};

注意到新版本的block驅動接口結構增加了gntgeo成員,使調用者可以直接調用此函數獲得設備的幾何結構。

工作流程:
mmc驅動主要文件包括
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/
內核啓動時,首先執行core/core.c的mmc_init,註冊mmc、sd總線,以及一個host class設備。接着執行card/block.c中,申請一個塊設備。

數據結構:
mmc總線操作相關函數,由於mmc卡支持多種總數據線,如SPI、SDIO、8LineMMC,而不同的總線的操作控制方式不盡相同,所以通過此結構與相應的總線回調函數相關聯。

//總線操作結構
struct mmc_bus_ops {
    void (*remove)(struct mmc_host *);
    void (*detect)(struct mmc_host *);
    int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
    void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
    void (*suspend)(struct mmc_host *);
    void (*resume)(struct mmc_host *);
};
//  mmc卡的總線操作 core/mmc.c
static const struct mmc_bus_ops mmc_ops = {
    .remove = mmc_remove,
    .detect = mmc_detect,
    .sysfs_add = mmc_sysfs_add,
    .sysfs_remove = mmc_sysfs_remove,
    .suspend = mmc_suspend,
    .resume = mmc_resume,
};
// sd卡的總線操作 core/sd.c
static const struct mmc_bus_ops mmc_sd_ops = {
    .remove = mmc_sd_remove,
    .detect = mmc_sd_detect,
    .sysfs_add = mmc_sd_sysfs_add,
    .sysfs_remove = mmc_sd_sysfs_remove,
    .suspend = mmc_sd_suspend,
    .resume = mmc_sd_resume,
};
// sdio的總線操作 core/sdio.c
static const struct mmc_bus_ops mmc_sdio_ops = {
    .remove = mmc_sdio_remove,
    .detect = mmc_sdio_detect,
};

關於總線操作的函數:
.detect,驅動程序經常需要調用此函數去檢測mmc卡的狀態,具體實現是發送CMD13命令,並讀迴響應,如果響應錯誤,則依次調用.remove、detach_bus來移除卡及釋放總線。

總體架構:
kernel啓動時,先後執行mmc_init()及mmc_blk_init(),以對mmc設備及mmc塊模塊進行初始化。
然後在掛載mmc設備驅動時,執行驅動程序中的xx_mmc_probe(),檢測host設備中掛載的sd設備。此時probe函數會創建一個host設備,然後開啓一個延時任務mmc_rescan()。
驅動掛載成功後,mmc_rescan()函數被執行,然後對卡進行初始化(步驟後面詳細講述)。
假如掃描到總線上掛有有效的設備,就調用相對應的函數把設備裝到系統中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()這三個函數分別是裝載sdio設備,sd卡和mmc卡的。
在 sd卡中,驅動循環發送ACMD41、CMD55給卡,讀取OCR寄存器,成功後,依次發送CMD2(讀CID)、CMD3(得到RCA)、CMD9(讀 CSD)、CMD7(選擇卡)。後面還有幾個命令分別是ACMD41&CMD51,使用CMD6切換一些功能,如切換到高速模式。
經過上述步驟,已經確定當前插入的卡是一張有效、可識別的存儲卡。然後調用mmc_add_card()把存儲卡加到系統中。正式與系統驅動連接在一起。
卡設備加到系統中後,通知mmc塊設備驅動。塊設備驅動此時調用probe函數,即mmc_blk_probe()函數,mmc_blk_probe()首先分配一個新的mmc_blk_data結構變量,然後調用mmc_init_queue,初始化blk隊列。然後建立一個線程 mmc_queue_thread()。
  

mmc_rescan:mmc_rescan()函數是在驅動裝載的時候,由驅動xx_mmc_probe()調用 mmc_alloc_host()時啓動的一個延時任務。 xx_mmc_probe()->mmc_alloc_host()->INIT_DELAYED_WORK(&host->detect, mmc_rescan);

core部分
1、取得總線
2、檢查總線操作結構指針bus_ops,如果爲空,則重新利用各總線對端口進行掃描,檢測順序依次爲:SDIO、Normal SD、MMC。當檢測到相應的卡類型後,就使用mmc_attach_bus()把相對應的總線操作與host連接起來。

void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
{
    ...
    host->bus_ops = ops;
    ...
}

3、初始化卡接以下流程初始化:
a、發送CMD0使卡進入IDLE狀態
b、發送CMD8,檢查卡是否SD2.0。SD1.1是不支持CMD8的,因此在SD2.0 Spec中提出了先發送CMD8,如響應爲無效命令,則卡爲SD1.1,否則就是SD2.0(請參考SD2.0 Spec)。
c、發送CMD5讀取OCR寄存器。
d、發送ACMD55、CMD41,使卡進入工作狀態。MMC卡並不支持ACMD55、CMD41,如果這步通過了,則證明這張卡是SD卡。
e、如果d步驟錯誤,則發送CMD1判斷卡是否爲MMC。SD卡不支持CMD1,而MMC卡支持,這就是SD和MMC類型的判斷依據。
f、如果ACMD41和CMD1都不能通過,那這張卡恐怕就是無效卡了,初始化失敗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章