單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機
W55MH32是WIZnet重磅推出的高性能以太網單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數據處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內置MAC以及PHY,擁有獨立的32KB以太網收發(fā)緩存,可供8個獨立硬件socket使用。如此配置,真正實現了All-in-One解決方案,為開發(fā)者提供極大便利。
在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN68和QFN100。
W55MH32Q采用QFN68封裝版本,尺寸為8x8mm,它擁有36個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、3個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN以及1個USB2.0。在保持與同系列其他版本一致的核心性能基礎上,僅減少了部分GPIO以及SDIO接口,其他參數保持一致,性價比優(yōu)勢顯著,尤其適合網關模組等對空間布局要求較高的場景。緊湊的尺寸和精簡化外設配置,使其能夠在有限空間內實現高效的網絡連接與數據交互,成為物聯(lián)網網關、邊緣計算節(jié)點等緊湊型設備的理想選擇。 同系列還有QFN100封裝的W55MH32L版本,該版本擁有更豐富的外設資源,適用于需要多接口擴展的復雜工控場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網站或者私信獲取。
此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及MQTT SSL等,為網絡通信安全再添保障。
為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32Q這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數據線,就能輕松實現調試、下載以及串口打印日志等功能。開發(fā)板將所有外設全部引出,拓展功能也大幅提升,便于開發(fā)者全面評估芯片性能。
若您想獲取芯片和開發(fā)板的更多詳細信息,包括產品特性、技術參數以及價格等,歡迎訪問官方網頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。

第二十一章 SDIO接口(SDIO)
1 SDIO 主要功能
SD/SDIOMMC 卡主機模塊(SDIO)在 AHB 外設總線和多媒體卡(MMC)、SD 存儲卡、SDIO 卡和 CE-ATA設備間提供了操作接口。多媒體卡系統(tǒng)規(guī)格書由 MMC技術委員會發(fā)布,可以在多媒體卡協(xié)會的網站上(www.mmca.org)獲得。CE-ATA 系統(tǒng)規(guī)格書可以在 CE-ATA 工作組的網站上(www.ce-ata.org)獲得。SDIO 的主要功能如下:
?與多媒體卡系統(tǒng)規(guī)格書版本 4.2 全兼容。支持三種不同的數據總線模式:1 位(默認)、4 位和8 位。
?與較早的多媒體卡系統(tǒng)規(guī)格版本全兼容(向前兼容)。
?與 SD 存儲卡規(guī)格版本 2.0 全兼容。
?與 SDI/O 卡規(guī)格版本 2.0 全兼容:支持良種不同的數據總線模式:1 位(默認)和 4 位。
?完全支持 CE-ATA 功能(與 CE-ATA 數字協(xié)議版本 1.1 全兼容)。
?8 位總線模式下數據傳輸速率可達 48MHz。
注: 1.SDIO 沒有 SPI 兼容的通信模式
2.在多媒體卡系統(tǒng)規(guī)格書版本 2.11 中,定義 SD 存儲卡協(xié)議是多媒體卡協(xié)議的超集。只支持 I/O模式的 SD 卡或復合卡中的 I/O 部分不能支持 SD 存儲備中很多需要的命令,這里有些命令在SDI/O 設備中不起作用,如擦除命令,因此 SDIO 不支持這些命令。另外,SD 存儲卡和 SDI/O 卡中有些命令是不同的SDIO 也不支持這些命令。細節(jié)可以參考 SDI/O 卡規(guī)格書版本 1.0。使用現有的 MMC 命令機制,在 MMC 接口上可以實現 CE-ATA 的支持。SDIO 接口的電氣和信號定義詳見MMC 參考資料。多媒體卡/SD 總線將所有卡與控制器相連。當前版本的 SDIO 在同一時間里只能支持一個 SD/SDIO/MMC4.2 卡,但可以支持多個 MMC 版本4.1 或以前版本的卡。
2 SDIO 總線拓撲
總線上的通信是通過傳送命令和數據實現。在多媒體卡/SD/SDI/O 總線上的基本操作是命令/響應結構,這樣的總線操作在命令或總線機制下實現信息交換;另外,某些操作還具有數據令牌。在 SD/SDIO 存儲器卡上傳送的數據是以數據塊的形式傳輸;在 MMC 上傳送的數據是以數據塊或數據流的形式傳輸;在 CE-ATA 設備上傳送的數據也是以數據塊的形式傳輸。

SDIO“無響應”和“無數據”操作

SDIO(多)數據塊讀操作

SDIO(多)數據塊寫操作
SDIO 連續(xù)讀操作

SDIO 連續(xù)寫操作
3 SDIO 功能描述
SDIO 包含 2 個部分:
?--SDIO 適配器模塊:實現所有 MMC/SD/SDI/O 卡的相關功能,如時鐘的產生、命令和數據的傳送。
?--AHB 總線接口:操作 SDIO 適配器模塊中的寄存器,并產生中斷和 DMA 請求信號。

SDIO 框圖
復位后默認情況下 SDIO_D0 用于數據傳輸。初始化后主機可以改變數據總線的寬度。如果一個多媒體卡接到了總線上,則 SDIO_D0、SDIO_D[3:0]或 SDIO_D[7:0]可以用于數據傳輸。MMC 版本 V3.31 和之前版本的協(xié)議只支持 1 位數據線,所以只能用 SDIO_D0。如果一個 SD 或 SDI/O 卡接到了總線上,可以通過主機配置數據傳輸使用 SDIO_D0 或 SDIO_D[3:0]。所有的數據線都工作在推挽模式。
SDIO_CMD 有兩種操作模式:
?用于初始化時的開路模式(僅用于 MMC 版本 V3.31 或之前版本)
?用于命令傳輸的推挽模式(SD/SDI/O 卡和 MMCV4.2 在初始化時也使用推挽驅動)
SDIO_CK 是卡的時鐘:每個時鐘周期在命令和數據線上傳輸 1 位命令或數據。對于多媒體卡 V3.31協(xié)議,時鐘頻率可以在 0MHz 至 20MHz 間變化;對于多媒體卡 V4.0/4.2 協(xié)議,時鐘頻率可以在0MHz 至 48MHz 間變化;對于 SD 或 SDI/O 卡,時鐘頻率可以在 0MHz 至 25MHz 間變化。SDIO 使用兩個時鐘信號:
?SDIO 適配器時鐘(SDIOCLK=HCLK)
?AHB 總線時鐘(HCLK/2)
下表適用于多媒體卡/SD/SDI/O 卡總線:
表 SDIO 引腳定義
| 引腳 | 方向 | 說明 |
| SDIO_CK | 輸出 | 多媒體卡 / SD/SDIO 卡時鐘。這是從主機至卡的時鐘線。 |
| SDIO_CMD | 雙向 | 多媒體卡 / SD/SDIO 卡命令。這是雙向的命令 / 響應信號線。 |
| SDIO_D[7:0] | 雙向 | 多媒體卡 / SD/SDIO 卡數據。這些是雙向的數據總線。 |
3.1 SDIO 適配器
下圖是簡化的 SDIO 適配器框圖:

SDIO 適配器
SDIO 適配器是多媒體/加密數字存儲卡總線的主設備(主機),用于連接一組多媒體卡或加密數字存儲卡,它包含以下 5 個部分:
?適配器寄存器模塊
?控制單元
?命令通道
?數據通道
?數據 FIFO
注: 適配器寄存器和 FIFO 使用 AHB 總線一側的時鐘(HCLK/2),控制單元、命令通道和數據通道使SDIO 適配器一側的時鐘(SDIOCLK)。
適配器寄存器模塊
適配器寄存器模塊包含所有系統(tǒng)寄存器。該模塊還產生清除多媒體卡中靜態(tài)標記的信號,當在SDIO 清除寄存器中的相應位寫'1'時會產生清除信號。
控制單元
控制單元包含電源管理功能和為存儲器卡提供的時鐘分頻。共有三種電源階段:
?電源關閉
?電源啟動
?電源開

控制單元
上圖為控制單元的框圖,有電源管理和時鐘管理子單元。在電源關閉和電源啟動階段,電源管理子單元會關閉卡總線上的輸出信號。時鐘管理子單元產生和控制 SDIO_CK 信號。SDIO_CK 輸出可以使用時鐘分頻或時鐘旁路模式。下述情況下沒有時鐘輸出:
?復位后
?在電源關閉和電源啟動階段
?當啟動了省電模式并且卡總線處于空閑狀態(tài)(命令通道和數據通道子單元進入空閑階段后的 8個時鐘周期)
命令通道
命令通道單元向卡發(fā)送命令并從卡接收響應。

SDIO適配器命令通道
命令通道狀態(tài)機(CPSM)
當寫入命令寄存器并設置了使能位,開始發(fā)送命令。命令發(fā)送完成時,命令通道狀態(tài)機(CPSM)設置狀態(tài)標志并在不需要響應時進入空閑狀態(tài)(見下圖)。當收到響應后,接收到的CRC 碼將會與內部產生的 CRC 碼比較,然后設置相應的狀態(tài)標志。

命令通道狀態(tài)機(CPSM)
當進入等待(Wait)狀態(tài)時,命令定時器開始運行;當 CPSM 進入接收(Receive)狀態(tài)之前,產生了超時,則設置超時標志并進入空閑(Idle)狀態(tài)。
注: 命令超時固定為 64 個 SDIO_CK 時鐘周期。
如果在命令寄存器設置了中斷位,則關閉定時器,CPSM 等待某一個卡發(fā)出的中斷請求。如果命令寄存器中設置掛起位,CPSM 進入掛起(Pend)狀態(tài)并等待數據通道子單元發(fā)出的 CmdPend 信號,在檢測到 CmdPend 信號時,CPSM 進入發(fā)送(Send)狀態(tài),這將觸發(fā)數據計數器發(fā)送停止命令的功能。
注: CPSM 保持在空閑狀態(tài)至少 8 個 SDIO_CK 周期,以滿足 NCC 和 NRC 時序限制。NCC 是兩個主機命令間的最小間隔;NRC 是主機命令與卡響應之間的最小間隔。

SDIO命令傳輸
命令格式
命令:命令是用于開始一項操作。主機向一個指定的卡或所有的卡發(fā)出帶地址的命令或廣播命令(廣播命令只適合于 MMCV3.31 或之前的版本)。命令在 CMD 線上串行傳送。所有命令的長度固定為 48 位,下表給出了多媒體卡、SD 存儲卡和 SDIO 卡上一般的命令格式。CE-ATA 命令是 MMCV4.2 命令的擴充,所以具有相同的格式。命令通道操作于半雙工模式,這樣命令和響應可以分別發(fā)送和接收。如果 CPSM 不處在發(fā)送狀態(tài),SDIO_CMD 輸出處于高阻狀態(tài),如圖 所示。SDIO_CMD 上的數據與 SDIO_CK 的上升沿同步。
| 位 | 寬度 | 數值 | 說明 |
| 47 | 1 | 0 | 開始位 |
| 46 | 1 | 1 | 傳輸位 |
| [45:40] | 6 | - | 命令索引 |
| [39:8] | 32 | - | 參數 |
| [7:1] | 7 | - | CRC7 |
| 0 | 1 | 1 | 結束位 |
響應:響應是由一個被指定地址的卡發(fā)送到主機,對于 MMCV3.31 或以前版本所有的卡同時發(fā)送響應;響應是對先前接收到命令的一個應答。響應在 CMD 線上串行傳送。
SDIO 支持 2 種響應類型,2 種類型都有 CRC 錯誤檢測:
?48 位短響應
?136 位長響應
注: 如果響應不包含 CRC(如 CMD1 的響應),設備驅動應該忽略 CRC 失敗狀態(tài)
短響應格式
| 位 | 寬度 | 數值 | 說明 |
| 47 | 1 | 0 | 開始位 |
| 46 | 1 | 1 | 傳輸位 |
| [45:40] | 6 | - | 命令索引 |
| [39:8] | 32 | - | 參數 |
| [7:1] | 7 | - | CRC7 (或 1111111) |
| 0 | 1 | 1 | 結束位 |
長響應格式
| 位 | 寬度 | 數值 | 說明 |
| 135 | 1 | 0 | 開始位 |
| 134 | 1 | 0 | 傳輸位 |
| [133:128] | 6 | 111111 | 保留 |
| [127:1] | 127 | - | CID 或 CSD (包含內部 CRC7) |
| 0 | 1 | 1 | 結束位 |
命令寄存器包含命令索引(發(fā)至卡的 6 位)和命令類型;命令本身決定了是否需要響應和響應的類型、48 位還是 136 位(見 20.9.4 節(jié))。命令通道中的狀態(tài)標志示于下表:
命令通道狀態(tài)標志
| 標志 | 說明 |
| CMDRCEND | 響應的 CRC 正確 |
| CCRCFAIL | 響應的 CRC 錯誤 |
| CMDSENT | 命令 (不需要響應的命令) 已經送出 |
| CTIMEOUT | 響應超時 |
| CMDACT | 正在發(fā)送命令 |
CRC發(fā)生器計算 CRC碼之前所有位的 CRC校驗和,包括開始位、發(fā)送位、命令索引和命令參數(或卡狀態(tài))。對于長響應格式,CRC 校驗和計算的是 CID 或 CSD 的前 120 位;注意,長響應格式中的開始位、傳輸位和 6 個保留位不參與 CRC 計算。
CRC 校驗和是一個 7 位的數值:
CRC[6:0]=余數[(M(x)*x7)/G(x)]
G(x)=x7+x3+1
M(x)=(開始位)*x39+…+(CRC 前的最后一位)*x0,或
M(x)=(開始位)*x119+…+(CRC 前的最后一位)*x0,或
數據通道
數據通道子單元在主機與卡之間傳輸數據。下圖是數據通道的框圖。

數據通道
在時鐘控制寄存器中可以配置卡的數據總線寬度。如果選擇了 4 位總線模式,則每個時鐘周期四條數據信號線(SDIO_D[3:0])上將傳輸 4 位數據;如果選擇了 8 位總線模式,則每個時鐘周期八條數據信號線(SDIO_D[7:0])上將傳輸 8 位數據;如果沒有選擇寬總線模式,則每個時鐘周期只在SDIO_D0 上傳輸 1 位數據。根據傳輸的方向(發(fā)送或接收),使能時數據通道狀態(tài)機(DPSM)將進入 Wait_S 或 Wait_R 狀態(tài):
?發(fā)送:DPSM 進入 Wait_S 狀態(tài)。如果發(fā)送 FIFO 中有數據,則 DPSM 進入發(fā)送狀態(tài),同時數據通道子單元開始向卡發(fā)送數據。
?接收:DPSM 進入 Wait_R 狀態(tài)并等待開始位;當收到開始位時,DPSM 進入接收狀態(tài),同時數據通子單元開始從卡接收數據。
數據通道狀態(tài)機(DPSM)
DPSM 工作在 SDIO_CK 頻率,卡總線信號與 SDIO_CK 的上升沿同步。DPSM 有 6 個狀態(tài),如下圖所示:

數據通道狀態(tài)機(DPSM)
?空閑(Idle):數據通道不工作,SDIO_D[7:0]輸出處于高阻狀態(tài)。當寫入數據控制寄存器并設置使能位時,DPSM 為數據計數器加載新的數值,并依據數據方向位進入 Wait_S 或 Wait_R狀態(tài)。
?Wait_R:如果數據計數器等于 0,當接收 FIFO 為空時 DPSM 進入到空閑(Idle)狀態(tài)。如果數據計數器不等于 0,DPSM 等待 SDIO_D上的開始位。如果 DPSM 在超時之前接收到一個開始位,它會進入接收(Receive)狀態(tài)并加載數據塊計數器。如果 DPSM 在檢測到一個開始位前出現超時,或發(fā)生開始位錯誤,DPSM 將進入空閑狀態(tài)并設置超時狀態(tài)標志。
?接收(Receive):接收到的串行數據被組合為字節(jié)并寫入數據 FIFO。根據數據控制寄存器中傳輸模式位的設置,數據傳輸模式可以是塊傳輸或流傳輸:
······在塊模式下,當數據塊計數器達到 0 時,DPSM 等待接收 CRC 碼,如果接收到的代碼與內部產生的 CRC 碼匹配,則 DPSM 進入 Wait_R 狀態(tài),否則設置 CRC 失敗狀態(tài)標志同時 DPSM進入到空閑狀態(tài)。
······在流模式下,當數據計數器不為 0 時,DPSM 接收數據;當計數器為 0 時,將移位寄存器中的剩余數據寫入數據 FIFO,同時 DPSM 進入 Wait_R 狀態(tài)。如果產生了 FIFO 上溢錯誤,DPSM 設置 FIFO 的錯誤標志并進入空閑狀態(tài)。
?Wait_S:如果數據計數器為 0,DPSM 進入空閑狀態(tài);否則 DPSM 等待數據 FIFO 空標志消失后,進入發(fā)送狀態(tài)。
注: DPSM 會在 Wait_S 狀態(tài)保持至少 2 個時鐘周期,以滿足 NWR 的時序要求,NWR 是接收到卡的響應至主機開始數據傳輸的間隔。
?發(fā)送(Send):DPSM 開始發(fā)送數據到卡設備。根據數據控制寄存器中傳輸模式位的設置,數據傳輸模式可以是塊傳輸或流傳輸:
······在塊模式下,當數據塊計數器達到 0 時,DPSM 發(fā)送內部產生的 CRC 碼,然后是結束位,并進入繁忙狀態(tài)。
······在流模式下,當使能位為高同時數據計數器不為 0 時,DPSM 向卡設備發(fā)送數據,然后進入空閑狀態(tài)。如果產生了 FIFO 下溢錯誤,DPSM 設置 FIFO 的錯誤標志并進入空閑狀態(tài)。
?繁忙(Busy):DPSM 等待 CRC 狀態(tài)標志:
······如果沒有接收到正確的 CRC 狀態(tài),則 DPSM 進入空閑狀態(tài)并設置 CRC 失敗狀態(tài)標志。
······如果接收到正確的 CRC 狀態(tài),則當 SDIO_D0 不為低時(卡不繁忙)DPSM 進入 Wait_S 狀態(tài)。
當 DPSM 處于繁忙狀態(tài)時發(fā)生了超時,DPSM 則設置數據超時標志并進入空閑狀態(tài)。
當 DPSM 處于 Wait_R 或繁忙狀態(tài)時,數據定時器被使能,并能夠產生數據超時錯誤:
······發(fā)送數據時,如果 DPSM 處于繁忙狀態(tài)超過程序設置的超時間隔,則產生超時。
······接收數據時,如果未收完所有數據,并且 DPSM 處于 Wait_R 狀態(tài)超過程序設置的超時間隔,則產生超時。
?數據:數據可以從主機傳送到卡,也可以反向傳輸。數據在數據線上傳輸。數據存儲在一個32 字的 FIFO 中,每個字為 32 位寬。
數據令牌格式
| 說明 | 開始位 | 數據 | CRC16 | 結束位 |
| 塊數據 | 0 | - | 有 | 1 |
| 流數據 | 0 | - | 無 | 1 |
數據 FIFO
數據 FIFO(先進先出)子單元是一個具有發(fā)送和接收單元的數據緩沖區(qū)。FIFO 包含一個每字 32 位寬、共 32 個字的數據緩沖區(qū),和發(fā)送與接收電路。因為數據 FIFO 工作在AHB 時鐘區(qū)域(HCLK/2),所有與 SDIO 時鐘區(qū)域(SDIOCLK)連接的信號都進行了重新同步。依據 TXACT 和 RXACT 標志,可以關閉 FIFO、使能發(fā)送或使能接收。TXACT 和 RXACT 由數據通道子單元設置而且是互斥的:
······當 TXACT 有效時,發(fā)送 FIFO 代表發(fā)送電路和數據緩沖區(qū)
······當 RXACT 有效時,接收 FIFO 代表接收電路和數據緩沖區(qū)
?發(fā)送 FIFO:當使能了 SDIO 的發(fā)送功能,數據可以通過 AHB 接口寫入發(fā)送 FIFO。
發(fā)送 FIFO 有 32 個連續(xù)的地址。發(fā)送 FIFO 中有一個數據輸出寄存器,包含讀指針指向的數據字。當數據通道子單元裝填了移位寄存器后,它移動讀指針至下個數據并傳輸出數據。如果未使能發(fā)送 FIFO,所有的狀態(tài)標志均處于無效狀態(tài)。當發(fā)送數據時,數據通道子單元設置TXACT 為有效。
發(fā)送 FIFO 狀態(tài)標志
| 標志 | 說明 |
| TXFIFOF | 當所有 32 個發(fā)送 FIFO 字都有有效的數據時,該標志為高。 |
| TXFIFOE | 當所有 32 個發(fā)送 FIFO 字都沒有有效的數據時,該標志為高。 |
| TXFIFOHE | 當 8 個或更多發(fā)送 FIFO 字為空時,該標志為高。該標志可以作為 DMA 請求。 |
| TXDAVL | 當發(fā)送 FIFO 包含有效數據時,該標志為高。該標志的意思剛好與 TXFIFOE 相反。 |
| TXUNDERR | 當發(fā)生下溢錯誤時,該標志為高。寫入 SDIO 清除寄存器時清除該標志。 |
?接收 FIFO:當數據通道子單元接收到一個數據字,它會把數據寫入 FIFO,寫操作結束后,寫指針自動加一;在另一端,有一個讀指針始終指向FIFO中的當前數據。如果關閉了接收FIFO,所有的狀態(tài)標志會被清除,讀寫指針也被復位。在接收到數據時數據通道子單元設置 RXACT。下表列出了接收 FIFO 的狀態(tài)標志。通過 32 個連續(xù)的地址可以訪問接收 FIFO。
接收 FIFO 狀態(tài)標志
| 標志 | 說明 |
| RXFIFOF | 當所有 32 個接收 FIFO 字都有有效的數據時,該標志為高。 |
| RXFIFOE | 當所有 32 個接收 FIFO 字都沒有有效的數據時,該標志為高。 |
| RXFIFOHF | 當 8 個或更多接收 FIFO 字有有效的數據時,該標志為高。該標志可以作為 DMA 請求。 |
| RXDAVL | 當接收 FIFO 包含有效數據時,該標志為高。該標志的意思剛好與 RXFIFOE 相反。 |
| RXOVERR | 當發(fā)生上溢錯誤時,該標志為高。寫入 SDIO 清除寄存器時清除該標志。 |
3.2 SDIOAHB 接口
AHB 接口產生中斷和 DMA 請求,并訪問 SDIO 接口寄存器和數據 FIFO。它包含一個數據通道、寄存器譯碼器和中斷/DMA 控制邏輯。
SDIO 中斷
當至少有一個選中的狀態(tài)標志為高時,中斷控制邏輯產生中斷請求。有一個屏蔽寄存器用于選擇可以產生中斷的條件,如果設置了相應的屏蔽標志,則對應的狀態(tài)標志可以產生中斷。
SDIO/DMA 接口:在 SDIO 和存儲器之間數據傳輸的過程
在下面的例子中,主機控制器使用 CMD24(WRITE_BLOCK)從主機傳送 512 字節(jié)到 MMC 卡,DMA 控制器用于從存儲器向 SDIO 的 FIFO 填充數據。
執(zhí)行卡識別過程。
提高 SDIO_CK 頻率。
發(fā)送 CMD7 命令選擇卡。
按下述步驟配置 DMA2:
使能 DMA2 控制器并清除所有的中斷標志位。
設置 DMA2 通道 4 的源地址寄存器為存儲器緩沖區(qū)的基地址,DMA2 通道 4 的目標地址寄存器為SDIO_FIFO 寄存器的地址。
設置 DMA2 通道 4 控制寄存器(存儲器遞增,非外設遞增,外設和源的數據寬度為字寬度)。
使能 DMA2 通道 4。
發(fā)送 CMD24(WRITE_BLOCK),操作如下:
設置 SDIO 數據長度寄存器(SDIO 數據時鐘寄存器應該在執(zhí)行卡識別過程之前設置好)。
設置 SDIO 參數寄存器為卡中需要傳送數據的地址。
設置 SDIO 命令寄存器:CmdIndex 置為 24(WRITE_BLOCK);WaitRest 置為 1(SDIO 卡主機等待響應);CPSMEN 置為 1(使能 SDIO 卡主機發(fā)送命令),保持其它域為他們的復位值。
等待 SDIO_STA[6]=CMDREND 中斷,然后設置 SDIO 數據寄存器:DTEN 置為 1(使能 SDIO卡主機發(fā)送數據);DTDIR 置為 0(控制器至卡方向);DTMODE 置為 0(塊數據傳送);DMAEN 置為 1(使能 DMA);DBLOCKSIZE 置為 9(512 字節(jié));其它域不用設置。
等待 SDIO_STA[10]=DBCKEND。
查詢 DMA 通道的使能狀態(tài)寄存器,確認沒有通道仍處于使能狀態(tài)。
4 卡功能描述
4.1 卡識別模式
在卡識別模式,主機復位所有的卡、檢測操作電壓范圍、識別卡并為總線上每個卡設置相對地址(RCA)。在卡識別模式下,所有數據通信只使用命令信號線(CMD)。
4.2 卡復位
GO_IDLE_STATE 命令(CMD0)是一個軟件復位命令,它把多媒體卡和 SD 存儲器置于空閑狀態(tài)。
IO_RW_DIRECT 命令(CMD52)復位 SDI/O 卡。上電后或執(zhí)行 CMD0 后,所有卡的輸出端都處于高阻狀態(tài),同時所有卡都被初始化至一個默認的相對卡地址(RCA=0x0001)和默認的驅動器寄存器設置(最低的速度,最大的電流驅動能力)。
4.3 操作電壓范圍確認
所有的卡都可以使用任何規(guī)定范圍內的電壓與 SDIO卡主機通信,可支持的最小和最大電壓 VDD數值由卡上的操作條件寄存器(OCR)定義。內部存儲器存儲了卡識別號(CID)和卡特定數據(CSD)的卡 ,僅能在數據傳輸 VDD 條件下傳送這些信息。
當 SDIO 卡主機模塊與卡的 VDD 范圍不一致時,卡將不能完成識別周期,也不能發(fā)送 CSD數據;因此,在 VDD 范圍不匹配時,SDIO 卡主機可以用下面幾個特殊命令去識別和拒絕卡:SEND_OP_COND(CMD1)、SD_APP_OP_COND(SD 存儲卡的 ACMD41)和 IO_SEND_OP_COND(SDI/O卡的 CMD5)。
SDIO 卡主機在執(zhí)行這幾個命令時會產生需要的 VDD 電壓。不能在指定的電壓范圍進行數據傳輸的卡,將從總線斷開并進入非激活狀態(tài)。使用這些不包含電壓范圍作為操作數的命令,SDIO 卡主機能夠查詢每個卡并在確定公共的電壓范圍前,把不在此范圍內的卡置于非激活狀態(tài)。當 SDIO 卡主機能夠選擇公共的電壓范圍或用戶需要知道卡是否能用時,SDIO 卡主機可以進行這樣的查詢。
4.4 卡識別過程
多媒體卡和 SD 卡的卡識別過程是有區(qū)別的;對于多媒體卡,卡識別過程以時鐘頻率 Fod 開始,所有 SDIO_CMD 輸出為開路驅動,允許在這個過程中的卡的并行連接,識別過程如下:
1. 總線被激活。
2. SDIO 卡主機廣播發(fā)送 SEND_OP_COND(CMD1)命令,并接收操作條件。
3. 得到的響應是所有卡的操作條件寄存器內容的“線與”。
4. 不兼容的卡會被置于非激活狀態(tài)。
5. SDIO 卡主機廣播發(fā)送 ALL_SEND_CID(CMD2)至所有激活的卡。
6. 所有激活的卡同時串行地發(fā)送他們的 CID 號,那些檢測到輸出的 CID 位與命令線上的數據不相符的卡必須停止發(fā)送,并等待下一個識別周期。最終只有一個卡能夠成功地傳送完整的CID 至 SDIO 卡主機并進入識別狀態(tài)。
7. SDIO 卡主機發(fā)送 SET_RELATIVE_ADDR(CMD3)命令至這個卡,這個新的地址被稱為相對卡地址(RCA),它比 CID 短,用于對卡尋址。至此,這個卡轉入待機狀態(tài),并不再響應新的識別過程,同時它的輸出驅動從開路轉變?yōu)橥仆炷J健?/p>
SDIO 卡主機重復上述步驟 5 至 7,直到收到超時條件。對于 SD 卡而言,卡識別過程以時鐘頻率 Fod 開始,所有 SDIO_CMD 輸出為推挽驅動而不是開路驅動,識別過程如下:
1. 總線被激活
2. SDIO 卡主機廣播發(fā)送 SEND_APP_OP_COND(ACMD41)命令
3. 得到的響應是所有卡的操作條件寄存器的內容
4. 不兼容的卡會被置于非激活狀態(tài)
5. SDIO 卡主機廣播發(fā)送 ALL_SEND_CID(CMD2)至所有激活的卡
6. 所有激活的卡發(fā)送回他們唯一卡識別號(CID)并進入識別狀態(tài)。
7. SDIO 卡主機發(fā)送 SET_RELATIVE_ADDR(CMD3)命令和一個地址到一個激活的卡,這個新的地址被稱為相對卡地址(RCA),它比 CID 短,用于對卡尋址。至此,這個卡轉入待機狀態(tài)。SDIO卡主機可以再次發(fā)送該命令更改 RCA,卡的 RCA 將是最后一次的賦值。
8. SDIO 卡主機對所有激活的卡重復上述步驟 5 至 7。
對于 SDI/O 卡而言,卡識別過程如下:
1. 總線被激活
2. SDIO 卡主機發(fā)送 IO_SEND_OP_COND(CMD5)命令
3. 得到的響應是卡的操作條件寄存器的內容
4. 不兼容的卡會被置于非激活狀態(tài)
5. SDIO 卡主機發(fā)送 SET_RELATIVE_ADDR(CMD3)命令和一個地址到一個激活的卡,這個新的地址被稱為相對卡地址(RCA),它比 CID 短,用于對卡尋址。至此,這個卡轉入待機狀態(tài)。SDIO卡主機可以再次發(fā)送該命令更改 RCA,卡的 RCA 將是最后一次的賦值。
4.5 寫數據塊
執(zhí)行寫數據塊命令(CMD24-27)時,主機把一個或多個數據塊從主機傳送到卡中,同時在每個數據塊的末尾傳送一個 CRC 碼。一個支持寫數據塊命令的卡應該始終能夠接收由 WRITE_BL_LEN 定義的數據塊。如果CRC校驗錯誤,卡通過SDIO_D信號線指示錯誤,傳送的數據被丟棄而不被寫入,所有后續(xù)(在多塊寫模式下)傳送的數據塊將被忽略。
如果主機傳送部分數據,而累計的數據長度未與數據塊對齊,當不允許塊錯位(未設置 CSD 的參數WRITE_BLK_MISALIGN),卡將在第一個錯位的塊之前檢測到塊錯位錯誤(設置狀態(tài)寄存器中的ADDRESS_ERROR 錯誤位)。當主機試圖寫一個寫保護區(qū)域時,寫操作也會被中止,此時卡會設置WP_VIOLATION 位。設置 CID 和 CSD 寄存器不需要事先設置塊長度,傳送的數據也是通過 CRC 保護的。如果 CSD 或CID 寄存器的部分是存儲在 ROM 中,則這個不能更改的部分必須與接收緩沖區(qū)的對應部分相一致,如果有不一致之處,卡將報告一個錯誤同時不修改任何寄存器的內容。有些卡需要長的甚至不可預計的時間完成寫一個數據塊,在接收一個數據塊并完成 CRC 檢驗后,卡開始寫操作,如果它的寫緩沖區(qū)已經滿并且不能再從新的 WRITE_BLOCK 命令接受新的數據時,它會把 SDIO_D 信號線拉低。
主機可以在任何時候使用 SEND_STATUS(CMD13)查詢卡的狀態(tài),卡將返回當前狀態(tài)。READY_FOR_DATA 狀態(tài)位指示卡是否可以接受新的數據或寫操作是否還在進行。主機可以使用CMD7(選擇另一個卡)不選中某個卡,而把這個卡置于斷開狀態(tài),這樣可以釋放 SDIO_D 信號線而不中斷未完成的寫操作;當重新選擇了一個卡,如果寫操作仍然在進行并且寫緩沖區(qū)仍不能使用,它會重新通過拉低 SDIO_D 信號線指示忙的狀態(tài)。
4.6 讀數據塊
在讀數據塊模式下,數據傳輸的基本單元是數據塊,它的大小在 CSD 中(READ_BL_LEN)定義。如果設置了 READ_BL_PARTIAL,同樣可以傳送較小的數據塊,較小數據塊是指開始和結束地址完全包含在一個物理塊中,READ_BL_LEN 定義了物理塊的大小。為保證數據傳輸的正確,每個數據塊后都有一個 CRC 校驗碼。CMD17(READ_SINGLE_BLOCK)啟動一次讀數據塊操作,在傳輸結束后卡返回到發(fā)送狀態(tài)。
CMD18(READ_MULTIPLE_BLOCK)啟動一次連續(xù)多個數據塊的讀操作。主機可以在多數據塊讀操作的任何時候中止操作,而不管操作的類型。發(fā)送停止傳輸命令即可中止操作。如果在多數據塊讀操作中(任一種類型)卡檢測到錯誤(例如:越界、地址錯位或內部錯誤),它將停止數據傳輸并仍處于數據狀態(tài);此時主機必須發(fā)送停止傳輸命令中止操作。在停止傳輸命令的響應中報告讀錯誤。如果主機發(fā)送停止傳輸命令時,卡已經傳輸完一個確定數目的多個數據塊操作中的最后一個數據塊,因為此時卡已經不在數據狀態(tài),主機會得到一個非法命令的響應。如果主機傳輸部分數據塊,而累計的數據長度不能與物理塊對齊同時不允許塊錯位,卡會在出現第一個未對齊的塊時檢測出一個塊對齊錯誤,并在狀態(tài)寄存器中設置 ADDRESS_ERROR 錯誤標志。
4.7 數據流操作,數據流寫入和數據流讀出(只適用于多媒體卡)
在數據流模式,數據按字節(jié)傳輸,同時每個數據塊后沒有 CRC。數據流寫(只適用于多媒體卡)WRITE_DAT_UNTIL_STOP(CMD20)開始從 SDIO 卡主機至卡的數據傳輸,從指定的地址開始連續(xù)傳輸直到 SDIO 卡主機發(fā)出一個停止命令。如果允許部分數據塊傳輸(設置了 CSD 參 數WRITE_BL_PARTIAL),則數據流可以在卡的地址空間中的任意地址開始和停止,否則數據流只能在數據塊的邊界開始和停止。因為傳輸的數據數目沒有事先設定,不能使用 CRC 校驗。
如果發(fā)送數據時達到了存儲器的最大地址,即使 SDIO 卡主機沒有發(fā)送停止命令,隨后傳輸的數據也會被丟棄。
數據流寫操作的最大時鐘頻率可以通過下式計算:

?Maximumspeed=最大寫頻率
?TRANSPEED=最大數據傳輸率
?writebllen=最大寫數據塊長度
?NSAC=以 CLK 周期計算的數據讀操作時間 2
?TAAC=數據讀操作時間 1
?R2WFACTOR=寫速度因子
如果主機試圖使用更高的頻率,卡可能不能處理數據并停止編程,同時在狀態(tài)寄存器中設置OVERRUN 錯誤位,丟棄所有隨后傳輸的數據并(在接收數據狀態(tài))等待停止命令。如果主機試圖寫入一個寫保護區(qū)域,寫操作將被中止,同時卡將設置 WP_VIOLATION 位。數據流讀(只適用于多媒體卡)READ_DAT_UNTIL_STOP(CMD11)控制數據流數據傳輸。這個命令要求卡從指定的地址讀出數據,直到 SDIO 卡主機發(fā)送 STOP_TRANSMISSION(CMD12)。
因為串行命令傳輸的延遲,停止命令的執(zhí)行會有延遲,數據傳送會在停止命令的結束位后停止。如果發(fā)送數據時達到了存儲器的最大地址,SDIO 卡主機沒有發(fā)送命令,隨后傳輸的數據將是無效數據。
數據流讀操作的最大時鐘頻率可以通過下式計算:

?Maximumspeed=最大寫頻率
?TRANSPEED=最大數據傳輸率
?readbllen=最大讀數據塊長度
?NSAC=以 CLK 周期計算的數據讀操作時間 2
?TAAC=數據讀操作時間 1
?R2WFACTOR=寫速度因子
如果主機試圖使用更高的頻率,卡將不能處理數據傳輸,此時卡在狀態(tài)寄存器中設置 UNDERRUN錯誤位,中止數據傳輸并在數據狀態(tài)等待停止命令。
4.8 擦除:成組擦除和扇區(qū)擦除
多媒體卡的擦除單位是擦除組,擦除組是以寫數據塊計算,寫數據塊是卡的基本寫入單位。擦除組的大小是卡的特定參數,在 CSD 中定義。
主機可以擦除一個連續(xù)范圍的擦除組,開始擦除操作有三個步驟。
首先,主機使用 ERASE_GROUP_START(CMD35)命令定義連續(xù)范圍的開始地址,然后使用ERASE_GROUP_END(CMD36)命令定義連續(xù)范圍的結束地址,最后發(fā)送擦除命令 ERASE(CMD38)開始擦除操作。擦除命令的地址域是以字節(jié)為單位的擦除組地址??〞釛壩磁c擦除組大小對齊的部分,把地址邊界對齊到擦除組的邊界。如果未按照上述步驟收到了擦除命令,卡在狀態(tài)寄存器中設置 ERASE_SEQ_ERROR 位,并重新等待第一個步驟。如果收到了除 SEND_STATUS 和擦除命令之外的其它命令,卡在狀態(tài)寄存器中設置 ERASE_RESET位,解除擦除序列并執(zhí)行新的命令。如果擦除范圍包含了寫保護數據塊,這些塊不被擦除,只有未保護的塊被擦除,同時卡在狀態(tài)寄存器中設置 WP_ERASE_SKIP 狀態(tài)位。在擦除過程中,卡拉低 SDIO_D 信號。實際的擦除時間可能很長,主機可以使用 CMD7 解除卡的選擇。
4.9 寬總線選擇和解除選擇
可以通過 SET_BUS_WIDTH(ACMD6)命令選擇或不選擇寬總線(4 位總線寬度)操作模式,上電后或GO_IDLE_STATE(CMD0)命令后默認的總線寬度為 1 位。SET_BUS_WIDTH(ACMD6)命令僅在傳輸狀態(tài)時有效,即只有在使用 SELECT/DESELECT_CARD(CMD7)命令選擇了卡后才能改變總線寬度。
4.10 保護管理
SDIO 卡主機模塊支持三種保護方式:
1. 內部卡保護(卡內管理)
2. 機械寫保護開關(僅由 SDIO 卡主機模塊管理)
3. 密碼管理的卡鎖操作
內部卡的寫保護
卡的數據可以被保護不被覆蓋或擦除。在 CSD 中永久地或臨時地設置寫保護位,生產廠商或內容提供商可以永久地對整個卡施行寫保護。對于支持在 CSD 中設置 WP_GRP_ENABLE 位從而提供一組扇區(qū)寫保護的卡,部分數據可以被保護,寫保護可以通過程序改變。寫保護的基本單位是 CSD參數 WP_GRP_SIZE 個扇區(qū)。
SET_WRITE_PROT 和 CLR_WRITE_PROT 命令控制指定組的保護,SEND_WRITE_PROT 命令與單數據塊讀命令類似,卡送出一個包含 32 個寫保護位(代表從指定地址開始的 32 個寫保護組)的數據塊,跟著一個 16 位的 CRC 碼。寫保護命令的地址域是一個以字節(jié)為單位的組地址??▽⒔財嗨薪M大小以下的地址。
機械寫保護開關
在卡的側面有一個機械的滑動開關,允許用戶設置或清除卡的寫保護。當滑動開關置于小窗口打開的位置時,卡處于寫保護狀態(tài),當滑動開關置于小窗口關閉的位置時,可以更改卡中內容。在卡的插槽上的對應部位也有一個開關指示 SDIO 卡主機模塊,卡是否處于寫保護狀態(tài)??ǖ膬炔侩娐凡恢缹懕Wo開關的位置。
密碼保護
密碼保護功能允許 SDIO 卡主機模塊使用密碼對卡實行上鎖或解鎖。密碼存儲在 128 位的 PWD 寄存器中,它的長度設置在 8 位的 PWD_LEN 寄存器中。這些寄存器是不可揮發(fā)的,即掉電后它們的內容不丟失。已上鎖的卡能夠響應和執(zhí)行相應的命令,即允許 SDIO 卡主機模塊執(zhí)行復位、初始化和查詢狀態(tài)等操作,但不允許操作卡中的數據。當設置了密碼后(即 PWD_LEN 的數值不為 0),上電后卡自動處于上鎖狀態(tài)。
正如 CSD 和 CID 寄存器寫命令,上鎖/解鎖命令僅在傳輸狀態(tài)下有效,在這個狀態(tài)下,命令中沒有地址參數,但卡已經被選中??ǖ纳湘i/解鎖命令具有單數據塊寫命令的結構和總線操作類型,傳輸的數據塊包含所有命令所需要的信息(密碼設置模式、PWD內容和上鎖/解鎖指示)。在發(fā)送卡的上鎖/解鎖命令之前,命令數據塊的長度由 SDIO 卡主機模塊定義,命令結構示于表 110。
位的設置如下:
?ERASE:設置該位將執(zhí)行強制擦除,所有其它位必須為 0,只發(fā)送命令字節(jié)。
?LOCK_UNLOCK:設置該位鎖住卡,LOCK_UNLOCK 與 SET_PWD 可以同時設置,但不能與CLR_PWD 同時設置。
?CLR_PWD:設置該位清除密碼數據。
?SET_PWD:設置該位將密碼數據保存至存儲器。
?PWD_LEN:以字節(jié)為單位定義密碼的長度。
?PWD:密碼(依不同的命令,新的密碼或正在使用的密碼)
以下幾節(jié)列出了設置/清除密碼、上鎖/解鎖和強制擦除的命令序列。
設置密碼
1. 選擇一個卡(SELECT/DESELECT_CARD,CMD7)。
2. 定義要在 8 位的卡上鎖/解鎖模式下發(fā)送的數據塊長度(SET_BLOCKLEN,CMD16),8 位的PWD_LEN,新密碼的字節(jié)數目。當更換了密碼后,發(fā)送命令的數據塊長度必須同時考慮新舊密碼的長度。
3. 以合適的數據塊長度在數據線上發(fā)送 LOCK/UNLOCK(CMD42)命令,并包含 16 位的 CRC 碼。數據塊包含了操作模式(SET_PWD=1)、長度(PWD_LEN)和密碼(PWD)。當更換了密碼后,長度數值(PWD_LEN)包含了新舊兩個密碼的長度,PWD 域包含了舊的密碼(正在使用的)和新的密碼。
4. 當舊的密碼匹配后,新的密碼和它的長度被分別存儲在 PWD 和 PWD_LEN 域。如果送出的舊密碼與期望的密碼(長度或內容)不吻合,則設置狀態(tài)寄存器中的 LOCK_UNLOCK_FAILED 錯誤位,同時密碼不變。密碼長度域(PWD_LEN)指示當前是否設置了密碼,如果該域為非零,則表示使用了密碼,卡在上電時自動上鎖。在不斷電的情況下,如果設置了密碼,可以通過設置 LOCK_UNLOCK 位或發(fā)送一個額外的上鎖命令,立即鎖住卡。
清除密碼
1. 選擇一個卡(SELECT/DESELECT_CARD,CMD7)。
2. 定義要在 8 位的卡上鎖/解鎖模式下發(fā)送的數據塊長度(SET_BLOCKLEN,CMD16),8 位的PWD_LEN,當前使用密碼的字節(jié)數目。
3. 當密碼匹配后,PWD 域被清除同時 PWD_LEN 被設為 0。如果送出的密碼與期望的密碼(長度或內容)不吻合,則設置狀態(tài)寄存器中的 LOCK_UNLOCK_FAILED 錯誤位,同時密碼不變。
卡上鎖
1. 選擇一個卡(SELECT/DESELECT_CARD,CMD7)
2. 定義要在 8 位的卡上鎖/解鎖模式(見表 110 的字節(jié) 0)下發(fā)送的數據塊長度(SET_BLOCKLEN,CMD16),8 位的 PWD_LEN,和當前密碼的字節(jié)數目。
3. 以合適的數據塊長度在數據線上發(fā)送 LOCK/UNLOCK(CMD42)命令,并包含 16 位的 CRC 碼。數據塊包含了操作模式(LOCK_UNLOCK=1)、長度(PWD_LEN)和密碼(PWD)。
4. 當密碼匹配后,卡被上鎖并則設置狀態(tài)寄存器中的 CARD_IS_LOCKED 狀態(tài)位。如果送出的密碼與期望的密碼(長度或內容)不吻合,則設置狀態(tài)寄存器中的 LOCK_UNLOCK_FAILED 錯誤位,同時上鎖操作失敗。設置密碼和為卡上鎖可以在同一個操作序列中進行,此時 SDIO 卡主機模塊按照前述的步驟設置密碼,但在發(fā)送新密碼命令的第 3 步需要設置 LOCK_UNLOCK 位。如果曾經設置過密碼(PWD_LEN 不為 0),卡會在上電復位時自動地上鎖。對已經上鎖的卡執(zhí)行上鎖操作或對沒有密碼的卡執(zhí)行上鎖操作會導致失敗,并設置狀態(tài)寄存器中的LOCK_UNLOCK_FAILED 錯誤位。
卡解鎖
1. 選擇一個卡(SELECT/DESELECT_CARD,CMD7)
2. 定義要在 8 位的卡上鎖/解鎖模式下發(fā)送的數據塊長度(SET_BLOCKLEN,CMD16),8 位的 PWD_LEN,和當前密碼的字節(jié)數目。
3. 以合適的數據塊長度在數據線上發(fā)送 LOCK/UNLOCK(CMD42)命令,并包含 16 位的 CRC 碼。數據塊包含了操作模式(LOCK_UNLOCK=0)、長度(PWD_LEN)和密碼(PWD)。
4. 當密碼匹配后,卡鎖被解除,同時狀態(tài)寄存器中的 CARD_IS_LOCKED 位被清除。如果送出的密碼與期望的密碼(長度或內容)不吻合,則設置狀態(tài)寄存器中的 LOCK_UNLOCK_FAILED 錯誤位,同時卡仍保持上鎖狀態(tài)。解鎖狀態(tài)只在當前的供電過程中有效,只要不清除 PWD 域,下次上電后卡會被自動上鎖。試圖對
已經解了鎖的卡執(zhí)行解鎖操作會導致操作失敗,并設置狀態(tài)寄存器中的 LOCK_UNLOCK_FAILED 錯誤位。
強制擦除
如果用戶忘記了密碼(PWD 的內容),可以在清除卡中的所有內容后使用卡。強制擦除操作擦除所
有卡中的數據和密碼。
1. 選擇一個卡(SELECT/DESELECT_CARD,CMD7)
2. 設置發(fā)送的數據塊長度(SET_BLOCKLEN,CMD16)為 1,僅發(fā)送 8 位的卡上鎖/解鎖字節(jié)。
3. 以合適的數據塊長度在數據線上發(fā)送 LOCK/UNLOCK(CMD42)命令,并包含 16 位的 CRC 碼。數據塊包含了操作模式(ERASE=1)所有其它位為 0。
當 ERASE 位是數據域中僅有的位時,卡中的所有內容將被擦除,包括 PWD 和 PWD_LEN 域,同時卡不再被上鎖。如果有任何其它位不為 0,則設置狀態(tài)寄存器中的LOCK_UNLOCK_FAILED 錯誤位,卡中的數據保持不變,同時卡仍保持上鎖狀態(tài)。試圖對已經解了鎖的卡執(zhí)行擦除操作會導致操作失敗,并設置狀態(tài)寄存器中的LOCK_UNLOCK_FAILED 錯誤位。
5 例程設計
5.1 SDIO_SDCardFatfs
該程序通過清晰的模塊化設計,實現了對 SD 卡 FATFS 文件系統(tǒng)的全面測試,適用于嵌入式系統(tǒng)存儲功能驗證和教學演示。
程序功能概述
1.硬件初始化
?系統(tǒng)時鐘、延時函數、串口(UART1)初始化。
?SD卡通過SDIO接口初始化,支持FATFS文件系統(tǒng)。
2.用戶交互
while (1)
{
cmd = GetCmd();
switch (cmd)
{
case '1': {
printf("1.--->>>FatfsTestrn");
FatfsTest();
TestList();
break;
}
case '2': {
printf("2.--->>>FatfsBigDataTestrn");
FatfsBigDataTest();
TestList();
break;
}
case '3': {
printf("3.--->>>ViewRootDirrn");
ViewRootDir();
TestList();
break;
}
case '4': {
printf("4.--->>>CreateDirrn");
CreateDir();
TestList();
break;
}
case '5': {
printf("5.--->>>DeleteDirFilern");
DeleteDirFile();
TestList();
break;
}
}
}
}
void TestList(void)
{
printf("/***************************SD Card Test*******************************/n");
printf("==========================List==========================n");
printf("1: Create a new file (FatFs read-write test file.txt) for read-write testingn");
printf("2: Read and write large amounts of data (FatFs read and write test file .txt), perform read and write testsn");
printf("3: Show the file test in the root directory of the SD Cardn");
printf("4: Create directory(/Dir1,/Dir1/Die1_1,/Dir2)n");
printf("5: Delete files and directories (/Dir1,/Dir1/Dir1_1,/Dir2, FatFs read and write test files.txt)n");
printf("****************************************************************************/n");
}
void SDInfoShow(void)
{
printf("/***************************SD Info Show*******************************/n");
printf("SDCardInfo.CardType : %dn", SDCardInfo.CardType);
printf("SDCardInfo.CardCapacity : %lld Byten", (SDCardInfo.CardCapacity));
printf("SDCardInfo.CardBlockSize : %d Byten", SDCardInfo.CardBlockSize);
}
uint8_t GetCmd(void)
{
uint8_t tmp = 0;
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
{
tmp = USART_ReceiveData(USART1);
}
return tmp;
}
?通過串口接收用戶命令(1-5),執(zhí)行對應操作:
?基礎文件操作測試(創(chuàng)建文件、讀寫數據)。
?大數據讀寫性能測試(2MB文件)。
?顯示SD卡根目錄內容。
?創(chuàng)建多級目錄(/Dir1, /Dir1/Dir1_1, /Dir2)。
?刪除目錄及測試文件。
3.關鍵函數
void FatfsTest(void)
{
res_sd = f_mount(&fs, "0:", 1);
/***************************Format test**************************/
printf("n format testn");
if (res_sd == FR_NO_FILESYSTEM)
{
printf("The SD card has no file system and is about to be formattedrn");
res_sd = f_mkfs("0:", 0, 0);
if (res_sd == FR_OK)
{
printf("The SD card successfully mounted the file systemrn");
res_sd = f_mount(NULL, "0:", 1);
res_sd = f_mount(&fs, "0:", 1);
}
else
{
printf("SD card formatting failedrn");
while (1);
}
}
else if (res_sd != FR_OK)
{
printf("SD card mount failed (%d), maybe SD card initialization failedrn", res_sd);
while (1);
}
else
{
printf("The file system is mounted and can be read and written for testingrn");
}
SDInfoShow();
/***************************File system testing --->>> Write test*********************/
printf("n file system test --->>> Write testn");
res_sd = f_open(&fnew, "0:FatFs read and write test files.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
if (res_sd == FR_OK)
{
printf("Open/create FatFs to read and write the test file.txt successfully, and write data to the filern");
res_sd = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum);
if (res_sd == FR_OK)
{
printf("The file was written successfully, the number of bytes written:% d The data written is: n%srn", fnum, WriteBuffer);
}
else
{
printf("File write failed (%d)n", res_sd);
}
f_close(&fnew);
}
else
{
printf("Failed to open/create, filern");
}
/*************************File system testing --->>> read test**************************/
printf("n file system test --->>> read testn");
res_sd = f_open(&fnew, "0:FatFs read and write test files.txt", FA_OPEN_ALWAYS | FA_READ);
if (res_sd == FR_OK)
{
printf("File successfully openedrn");
res_sd = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum);
if (res_sd == FR_OK)
{
printf("File read successful. Bytes read:% d The data read was: n%srn", fnum, ReadBuffer);
}
else
{
printf("File read failed (%d)n", res_sd);
}
}
else
{
printf("File opening failedn");
}
f_close(&fnew);
f_mount(NULL, "0:", 1);
}
FatfsTest():掛載文件系統(tǒng),格式化(若需要),測試文件讀寫。
void FatfsBigDataTest(void)
{
uint32_t i;
res_sd = f_mount(&fs, "0:", 1);
/***************************File system testing --->>> Big data write test*********************/
printf("nFile system test --->>> write testn");
res_sd = f_open(&fnew, "0:FatFs read and write test files.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
if (res_sd == FR_OK)
{
printf("Open/create FatFs to read and write the test file.txt successfully, and write data to the filern");
for (i = 0; i < 0xFFFFF; i++)
{
res_sd = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum);
if ((i % 0x8FFF) == 0)
{
printf("......n");
}
}
if (res_sd == FR_OK)
{
printf("File written successfullyn");
}
else
{
printf("File write failed (%d)n", res_sd);
}
f_close(&fnew);
}
else
{
printf("Failed to open/create, filern");
}
}
FatfsBigDataTest():寫入大量數據測試性能。
void CreateDir(void)
{
res_sd = f_mount(&fs, "0:", 1);
if (res_sd != FR_OK)
{
printf("Failed to mount file system (%d)rn", res_sd);
}
res_sd = f_mkdir("/Dir1");
if (res_sd == FR_OK)
{
printf("f_mkdir Dir1 OKrn");
}
else if (res_sd == FR_EXIST)
{
printf("Dir1 Target already exists(%d)rn", res_sd);
}
else
{
printf("f_mkdir Dir1 fail(%d)rn", res_sd);
return;
}
res_sd = f_mkdir("/Dir2");
if (res_sd == FR_OK)
{
printf("f_mkdir Dir2 OKrn");
}
else if (res_sd == FR_EXIST)
{
printf("Dir2 Target already exists(%d)rn", res_sd);
}
else
{
printf("f_mkdir Dir2 fail (%d)rn", res_sd);
return;
}
res_sd = f_mkdir("/Dir1/Dir1_1");
if (res_sd == FR_OK)
{
printf("f_mkdir Dir1_1 OKrn");
}
else if (res_sd == FR_EXIST)
{
printf("Dir1_1 Target already exists(%d)rn", res_sd);
}
else
{
printf("f_mkdir Dir1_1 fail (%d)rn", res_sd);
return;
}
f_mount(NULL, "0:", 1);
}
CreateDir() 和 DeleteDirFile():目錄創(chuàng)建與刪除。
void ViewRootDir(void)
{
DIR dirinf;
FILINFO fileinf;
uint32_t cnt = 0;
char name[256];
res_sd = f_mount(&fs, "0:", 1);
if (res_sd != FR_OK)
{
printf("Failed to mount file system (%d)rn", res_sd);
}
res_sd = f_opendir(&dirinf, "/");
if (res_sd != FR_OK)
{
printf("Failed to open root directory (%d)rn", res_sd);
return;
}
fileinf.lfname = name;
fileinf.lfsize = 256;
printf("attribute | file size | short filename | long file namern");
for (cnt = 0;; cnt++)
{
res_sd = f_readdir(&dirinf, &fileinf);
if (res_sd != FR_OK || fileinf.fname[0] == 0)
{
break;
}
if (fileinf.fname[0] == '.')
{
continue;
}
if (fileinf.fattrib & AM_DIR)
{
printf("(0x%02d)directory", fileinf.fattrib);
}
else
{
printf("(0x%02d)attribute", fileinf.fattrib);
}
printf("%10d ", fileinf.fsize);
printf(" %s |", fileinf.fname);
printf(" %srn", (char *)fileinf.lfname);
}
f_mount(NULL, "0:", 1);
}
ViewRootDir():顯示根目錄內容。
關鍵代碼分析:
1.文件系統(tǒng)初始化與掛載
res_sd = f_mount(&fs, "0:", 1);
?掛載SD卡(邏輯驅動號0:),失敗時嘗試格式化(f_mkfs)。
2.文件讀寫操作
?創(chuàng)建/打開文件:f_open使用FA_OPEN_ALWAYS模式,若文件不存在則創(chuàng)建。
?寫入數據:f_write將緩沖區(qū)數據寫入文件。
?讀取數據:f_read從文件讀取數據到緩沖區(qū)。
3.目錄操作
?創(chuàng)建目錄:f_mkdir創(chuàng)建目錄,處理已存在情況(FR_EXIST)。
?刪除目錄/文件:f_unlink刪除文件或空目錄(非空目錄需遞歸刪除)。
6 下載驗證
6.1 SDIO_SDCardFatfs

命令1:基礎文件測試(FatfsTest):

命令2:大數據讀寫測試(FatfsBigDataTest):

命令3:查看根目錄(ViewRootDir):

命令4:創(chuàng)建目錄(CreateDir):

命令5:刪除目錄與文件(DeleteDirFile):

WIZnet 是一家無晶圓廠半導體公司,成立于 1998 年。產品包括互聯(lián)網處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術,基于獨特的專利全硬連線 TCP/IP。iMCU? 面向各種應用中的嵌入式互聯(lián)網設備。
WIZnet 在全球擁有 70 多家分銷商,在香港、韓國、美國設有辦事處,提供技術支持和產品營銷。
香港辦事處管理的區(qū)域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。
審核編輯 黃宇
-
單片機
+關注
關注
6072文章
45268瀏覽量
661134 -
SDIO
+關注
關注
2文章
78瀏覽量
20403
發(fā)布評論請先 登錄
明德?lián)P視頻分享點撥FPGA課程--第二十一章 ?矩陣鍵盤工程
第二十一講 組合邏輯電路中的競爭冒險
模擬電路網絡課件 第二十一節(jié):場效應管與BJT放大電路的比較
第二十一屆中國西部國際投資貿易洽談會開幕 全方位展示工業(yè)4.0以來最新科技成果
西安高新第二十一小學能耗監(jiān)測及電力監(jiān)控系統(tǒng)的研究與應用
獲雙項榮譽:中科智云受邀出席第二十一屆中國科學家論壇
【節(jié)能學院】西安高新第二十一小學能耗監(jiān)測及電力監(jiān)控系統(tǒng)的研究與應用
圖撲軟件亮相第二十一屆中國·海峽創(chuàng)新項目成果交易會
閃耀灣區(qū),諾安智能獲評第二十一屆“深圳知名品牌(灣區(qū)知名品牌)”稱號
2024第二十一屆(上海)國際物聯(lián)網展覽會4月24日-26日開幕
云知聲亮相第二十一屆中國-東盟博覽會

第二十一章 SDIO接口(SDIO)
評論