單芯片解決方案,開(kāi)啟全新體驗(yàn)——W55MH32 高性能以太網(wǎng)單片機(jī)
W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機(jī),它為用戶(hù)帶來(lái)前所未有的集成化體驗(yàn)。這顆芯片將強(qiáng)大的組件集于一身,具體來(lái)說(shuō),一顆W55MH32內(nèi)置高性能Arm? Cortex-M3核心,其主頻最高可達(dá)216MHz;配備1024KB FLASH與96KB SRAM,滿(mǎn)足存儲(chǔ)與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內(nèi)置MAC以及PHY,擁有獨(dú)立的32KB以太網(wǎng)收發(fā)緩存,可供8個(gè)獨(dú)立硬件socket使用。如此配置,真正實(shí)現(xiàn)了All-in-One解決方案,為開(kāi)發(fā)者提供極大便利。
在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN100和QFN68。
W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專(zhuān)為各種復(fù)雜工控場(chǎng)景設(shè)計(jì)。它擁有66個(gè)GPIO、3個(gè)ADC、12通道DMA、17個(gè)定時(shí)器、2個(gè)I2C、5個(gè)串口、2個(gè)SPI接口(其中1個(gè)帶I2S接口復(fù)用)、1個(gè)CAN、1個(gè)USB2.0以及1個(gè)SDIO接口。如此豐富的外設(shè)資源,能夠輕松應(yīng)對(duì)工業(yè)控制中多樣化的連接需求,無(wú)論是與各類(lèi)傳感器、執(zhí)行器的通信,還是對(duì)復(fù)雜工業(yè)協(xié)議的支持,都能游刃有余,成為復(fù)雜工控領(lǐng)域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網(wǎng)關(guān)模組等場(chǎng)景,軟件使用方法一致。更多信息和資料請(qǐng)進(jìn)入網(wǎng)站或者私信獲取。
此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應(yīng)用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網(wǎng)絡(luò)通信安全再添保障。
為助力開(kāi)發(fā)者快速上手與深入開(kāi)發(fā),基于W55MH32L這顆芯片,WIZnet精心打造了配套開(kāi)發(fā)板。開(kāi)發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線(xiàn),就能輕松實(shí)現(xiàn)調(diào)試、下載以及串口打印日志等功能。開(kāi)發(fā)板將所有外設(shè)全部引出,拓展功能也大幅提升,便于開(kāi)發(fā)者全面評(píng)估芯片性能。
若您想獲取芯片和開(kāi)發(fā)板的更多詳細(xì)信息,包括產(chǎn)品特性、技術(shù)參數(shù)以及價(jià)格等,歡迎訪(fǎng)問(wèn)官方網(wǎng)頁(yè),我們期待與您共同探索W55MH32的無(wú)限可能。
第二十五章 SDIO——SD卡讀寫(xiě)測(cè)試
本章參考資料:《W55MH32參考手冊(cè)》、SD簡(jiǎn)易規(guī)格文件 《Physical Layer Simplified SpecificationV2.0》(版本號(hào):2.00)。
閱讀本章內(nèi)容之前,建議先閱讀SD簡(jiǎn)易規(guī)格文件。
1 SDIO簡(jiǎn)介
SD卡(Secure Digital Memory Card)在我們生活中已經(jīng)非常普遍了,控制器對(duì)SD卡進(jìn)行讀寫(xiě)通信操作一般有兩種通信接口可選, 一種是SPI接口,另外一種就是SDIO接口。SDIO全稱(chēng)是安全數(shù)字輸入/輸出接口,多媒體卡(MMC)、SD卡、SD I/O卡都有SDIO接口。 W55MH32系列控制器有一個(gè)SDIO主機(jī)接口,它可以與MMC卡、SD卡、SD I/O卡以及CE-ATA設(shè)備進(jìn)行數(shù)據(jù)傳輸。MMC卡可以說(shuō)是SD卡的前身, 現(xiàn)階段已經(jīng)用得很少。SD I/O卡本身不是用于存儲(chǔ)的卡,它是指利用SDIO傳輸協(xié)議的一種外設(shè)。比如Wi-Fi Card, 它主要是提供Wi-Fi功能,有些Wi-Fi模塊是使用串口或者SPI接口進(jìn)行通信的,但Wi-Fi SDIO Card是使用SDIO接口進(jìn)行通信的。 并且一般設(shè)計(jì)SD I/O卡是可以插入到SD的插槽。CE-ATA是專(zhuān)為輕薄筆記本硬盤(pán)設(shè)計(jì)的硬盤(pán)高速通訊接口。
多媒體卡協(xié)會(huì)網(wǎng)站www.mmca.org中提供了有MMCA技術(shù)委員會(huì)發(fā)布的多媒體卡系統(tǒng)規(guī)范。
SD卡協(xié)會(huì)網(wǎng)站www.sdcard.org中提供了SD存儲(chǔ)卡和SDIO卡系統(tǒng)規(guī)范。
CE-ATA工作組網(wǎng)站www.ce-ata.org中提供了CE_ATA系統(tǒng)規(guī)范。
隨之科技發(fā)展,SD卡容量需求越來(lái)越大,SD卡發(fā)展到現(xiàn)在也是有幾個(gè)版本的, 關(guān)于SDIO接口的設(shè)備整體概括見(jiàn)下圖,SDIO接口的設(shè)備 :
關(guān)于SD卡和SD I/O部分內(nèi)容可以在SD協(xié)會(huì)網(wǎng)站獲取到詳細(xì)的介紹,比如各種SD卡尺寸規(guī)則、讀寫(xiě)速度標(biāo)示方法、應(yīng)用擴(kuò)展等等信息。
本章內(nèi)容針對(duì)SD卡使用講解,對(duì)于其他類(lèi)型卡的應(yīng)用可以參考相關(guān)系統(tǒng)規(guī)范實(shí)現(xiàn),所以對(duì)于控制器中針對(duì)其他類(lèi)型卡的內(nèi)容可能在本章中簡(jiǎn)單提及或者被忽略, 本章內(nèi)容不區(qū)分SDIO和SD卡這兩個(gè)概念。即使目前SD協(xié)議提供的SD卡規(guī)范版本最新是4.01版本,但W55MH32系列控制器只支持SD卡規(guī)范版本2.0, 即只支持標(biāo)準(zhǔn)容量SD和高容量SDHC標(biāo)準(zhǔn)卡,不支持超大容量SDXC標(biāo)準(zhǔn)卡,所以可以支持的最高卡容量是32GB。
2 SD卡物理結(jié)構(gòu)
一張SD卡包括有存儲(chǔ)單元、存儲(chǔ)單元接口、電源檢測(cè)、卡及接口控制器和接口驅(qū)動(dòng)器5個(gè)部分,見(jiàn)下圖,SD卡物理結(jié)構(gòu)。 存儲(chǔ)單元是存儲(chǔ)數(shù)據(jù)部件,存儲(chǔ)單元通過(guò)存儲(chǔ)單元接口與卡控制單元進(jìn)行數(shù)據(jù)傳輸;電源檢測(cè)單元保證SD卡工作在合適的電壓下, 如出現(xiàn)掉電或上狀態(tài)時(shí),它會(huì)使控制單元和存儲(chǔ)單元接口復(fù)位;卡及接口控制單元控制SD卡的運(yùn)行狀態(tài),它包括有8個(gè)寄存器;接口驅(qū)動(dòng)器控制SD卡引腳的輸入輸出。
SD卡總共有8個(gè)寄存器,用于設(shè)定或表示SD卡信息,參考表 SD卡寄存器 。這些寄存器只能通過(guò)對(duì)應(yīng)的命令訪(fǎng)問(wèn), 對(duì)SD卡進(jìn)行控制操作并不是像操作控制器GPIO相關(guān)寄存器那樣一次讀寫(xiě)一個(gè)寄存器的,它是通過(guò)命令來(lái)控制, SDIO定義了64個(gè)命令,每個(gè)命令都有特殊意義,可以實(shí)現(xiàn)某一特定功能,SD卡接收到命令后, 根據(jù)命令要求對(duì)SD卡內(nèi)部寄存器進(jìn)行修改,程序控制中只需要發(fā)送組合命令就可以實(shí)現(xiàn)SD卡的控制以及讀寫(xiě)操作。
名稱(chēng) | bit 寬度 | 描述 |
CID | 128 | 卡識(shí)別號(hào) (Card identification number):用來(lái)識(shí)別的卡的個(gè)體號(hào)碼 (唯一的) |
RCA | 16 | 相對(duì)地址 (Relative card address):卡的本地系統(tǒng)地址,初始化時(shí),動(dòng)態(tài)地由卡建議,主機(jī)核準(zhǔn)。 |
DSR | 16 | 驅(qū)動(dòng)級(jí)寄存器 (Driver Stage Register):配置卡的輸出驅(qū)動(dòng) |
CSD | 128 | 卡的特定數(shù)據(jù) (Card Specific Data):卡的操作條件信息 |
SCR | 64 | SD 配置寄存器 (SD Configuration Register):SD 卡特殊特性信息 |
OCR | 32 | 操作條件寄存器 (Operation conditions register) |
SSR | 512 | SD 狀態(tài) (SD Status):SD 卡專(zhuān)有特征的信息 |
CSR | 32 | 卡狀態(tài) (Card Status):卡狀態(tài)信息 |
每個(gè)寄存器位的含義可以參考SD簡(jiǎn)易規(guī)格文件《Physical Layer Simplified Specification V2.0》第5章內(nèi)容。
3 SDIO總線(xiàn)
3.1 總線(xiàn)拓?fù)?/strong>
SD卡一般都支持SDIO和SPI這兩種接口,本章內(nèi)容只介紹SDIO接口操作方式,如果需要使用SPI操作方式可以參考SPI相關(guān)章節(jié)。 另外,W55MH32系列控制器的SDIO是不支持SPI通信模式的,如果需要用到SPI通信只能使用SPI外設(shè)。
SD卡總線(xiàn)拓?fù)鋮⒖紙D SD卡總線(xiàn)拓?fù)?。雖然可以共用總線(xiàn), 但不推薦多卡槽共用總線(xiàn)信號(hào),要求一個(gè)單獨(dú)SD總線(xiàn)應(yīng)該連接一個(gè)單獨(dú)的SD卡。
SD卡使用9-pin接口通信,其中3根電源線(xiàn)、1根時(shí)鐘線(xiàn)、1根命令線(xiàn)和4根數(shù)據(jù)線(xiàn),具體說(shuō)明如下:
CLK:時(shí)鐘線(xiàn),由SDIO主機(jī)產(chǎn)生,即由W55MH32控制器輸出;
CMD:命令控制線(xiàn),SDIO主機(jī)通過(guò)該線(xiàn)發(fā)送命令控制SD卡,如果命令要求SD卡提供應(yīng)答(響應(yīng)),SD卡也是通過(guò)該線(xiàn)傳輸應(yīng)答信息;
D0-3:數(shù)據(jù)線(xiàn),傳輸讀寫(xiě)數(shù)據(jù);SD卡可將D0拉低表示忙狀態(tài);
VDD、VSS1、VSS2:電源和地信號(hào)。
在之前的I2C以及SPI章節(jié)都有詳細(xì)講解了對(duì)應(yīng)的通信時(shí)序,實(shí)際上,SDIO的通信時(shí)序簡(jiǎn)單許多,SDIO不管是從主機(jī)控制器向SD卡傳輸, 還是SD卡向主機(jī)控制器傳輸都只以CLK時(shí)鐘線(xiàn)的上升沿為有效。SD卡操作過(guò)程會(huì)使用兩種不同頻率的時(shí)鐘同步數(shù)據(jù),一個(gè)是識(shí)別卡階段時(shí)鐘頻率FOD, 最高為400kHz,另外一個(gè)是數(shù)據(jù)傳輸模式下時(shí)鐘頻率FPP,默認(rèn)最高為25MHz,如果通過(guò)相關(guān)寄存器配置使SDIO工作在高速模式,此時(shí)數(shù)據(jù)傳輸模式最高頻率為50MHz。
對(duì)于W55MH32控制器只有一個(gè)SDIO主機(jī),所以只能連接一個(gè)SDIO設(shè)備, 開(kāi)發(fā)板上集成了一個(gè)Micro SD卡槽和SDIO接口的WiFi模塊,要求只能使用其中一個(gè)設(shè)備。 SDIO接口的WiFi模塊一般集成有使能線(xiàn),如果需要用到SD卡需要先控制該使能線(xiàn)禁用WiFi模塊。
3.2 總線(xiàn)協(xié)議
SD總線(xiàn)通信是基于命令和數(shù)據(jù)傳輸?shù)?。通訊由一個(gè)起始位(“0”),由一個(gè)停止位(“1”)終止。SD通信一般是主機(jī)發(fā)送一個(gè)命令(Command), 從設(shè)備在接收到命令后作出響應(yīng)(Response),如有需要會(huì)有數(shù)據(jù)(Data)傳輸參與。
SD總線(xiàn)的基本交互是命令與響應(yīng)交互,見(jiàn)下圖,命令與響應(yīng)交互:
SD數(shù)據(jù)是以塊(Black)形式傳輸?shù)?,SDHC卡數(shù)據(jù)塊長(zhǎng)度一般為512字節(jié),數(shù)據(jù)可以從主機(jī)到卡, 也可以是從卡到主機(jī)。數(shù)據(jù)塊需要CRC位來(lái)保證數(shù)據(jù)傳輸成功。CRC位由SD卡系統(tǒng)硬件生成。 W55MH32控制器可以控制使用單線(xiàn)或4線(xiàn)傳輸,本開(kāi)發(fā)板設(shè)計(jì)使用4線(xiàn)傳輸。圖 多塊寫(xiě)入操作 為主機(jī)向SD卡寫(xiě)入數(shù)據(jù)塊操作示意。
SD數(shù)據(jù)傳輸支持單塊和多塊讀寫(xiě),它們分別對(duì)應(yīng)不同的操作命令,多塊寫(xiě)入還需要使用命令來(lái)停止整個(gè)寫(xiě)入操作。 數(shù)據(jù)寫(xiě)入前需要檢測(cè)SD卡忙狀態(tài),因?yàn)镾D卡在接收到數(shù)據(jù)后編程到存儲(chǔ)區(qū)過(guò)程需要一定操作時(shí)間。SD卡忙狀態(tài)通過(guò)把D0線(xiàn)拉低表示。
數(shù)據(jù)塊讀操作與之類(lèi)似,只是無(wú)需忙狀態(tài)檢測(cè)。
使用4數(shù)據(jù)線(xiàn)傳輸時(shí),每次傳輸4bit數(shù)據(jù),每根數(shù)據(jù)線(xiàn)都必須有起始位、終止位以及CRC位,CRC位每根數(shù)據(jù)線(xiàn)都要分別檢查,并把檢查結(jié)果匯總?cè)缓笤跀?shù)據(jù)傳輸完后通過(guò)D0線(xiàn)反饋給主機(jī)。
SD卡數(shù)據(jù)包有兩種格式,一種是常規(guī)數(shù)據(jù)(8bit寬),它先發(fā)低字節(jié)再發(fā)高字節(jié),而每個(gè)字節(jié)則是先發(fā)高位再發(fā)低位,4線(xiàn)傳輸示意如圖 8位寬數(shù)據(jù)包傳輸 。
4線(xiàn)同步發(fā)送,每根線(xiàn)發(fā)送一個(gè)字節(jié)的其中兩個(gè)位,數(shù)據(jù)位在四線(xiàn)順序排列發(fā)送,DAT3數(shù)據(jù)線(xiàn)發(fā)較高位,DAT0數(shù)據(jù)線(xiàn)發(fā)較低位。
另外一種數(shù)據(jù)包發(fā)送格式是寬位數(shù)據(jù)包格式,對(duì)SD卡而言寬位數(shù)據(jù)包發(fā)送方式是針對(duì)SD卡SSR(SD狀態(tài))寄存器內(nèi)容發(fā)送的, SSR寄存器總共有512bit,在主機(jī)發(fā)出ACMD13命令后SD卡將SSR寄存器內(nèi)容通過(guò)DAT線(xiàn)發(fā)送給主機(jī)。寬位數(shù)據(jù)包格式示意見(jiàn)圖,寬位數(shù)據(jù)包傳輸:
3.3 命令
SD命令由主機(jī)發(fā)出,以廣播命令和尋址命令為例,廣播命令是針對(duì)與SD主機(jī)總線(xiàn)連接的所有從設(shè)備發(fā)送的,尋址命令是指定某個(gè)地址設(shè)備進(jìn)行命令傳輸。
3.3.1 命令格式
SD命令格式固定為48bit,都是通過(guò)CMD線(xiàn)連續(xù)傳輸?shù)模〝?shù)據(jù)線(xiàn)不參與),見(jiàn)下圖,SD命令格式:
SD命令的組成如下:
起始位和終止位:命令的主體包含在起始位與終止位之間,它們都只包含一個(gè)數(shù)據(jù)位,起始位為0,終止位為1。
傳輸標(biāo)志:用于區(qū)分傳輸方向,該位為1時(shí)表示命令,方向?yàn)橹鳈C(jī)傳輸?shù)絊D卡,該位為0時(shí)表示響應(yīng),方向?yàn)镾D卡傳輸?shù)街鳈C(jī)。
命令主體內(nèi)容包括命令、地址信息/參數(shù)和CRC校驗(yàn)三個(gè)部分。
命令號(hào):它固定占用6bit,所以總共有64個(gè)命令(代號(hào):CMD0~CMD63),每個(gè)命令都有特定的用途, 部分命令不適用于SD卡操作,只是專(zhuān)門(mén)用于MMC卡或者SD I/O卡。
地址/參數(shù):每個(gè)命令有32bit地址信息/參數(shù)用于命令附加內(nèi)容,例如,廣播命令沒(méi)有地址信息, 這32bit用于指定參數(shù),而尋址命令這32bit用于指定目標(biāo)SD卡的地址。
CRC7校驗(yàn):長(zhǎng)度為7bit的校驗(yàn)位用于驗(yàn)證命令傳輸內(nèi)容正確性, 如果發(fā)生外部干擾導(dǎo)致傳輸數(shù)據(jù)個(gè)別位狀態(tài)改變將導(dǎo)致校準(zhǔn)失敗,也意味著命令傳輸失敗,SD卡不執(zhí)行命令。
3.3.2 命令類(lèi)型
SD命令有4種類(lèi)型:
無(wú)響應(yīng)廣播命令(bc),發(fā)送到所有卡,不返回任務(wù)響應(yīng);
帶響應(yīng)廣播命令(bcr),發(fā)送到所有卡,同時(shí)接收來(lái)自所有卡響應(yīng);
尋址命令(ac),發(fā)送到選定卡,DAT線(xiàn)無(wú)數(shù)據(jù)傳輸;
尋址數(shù)據(jù)傳輸命令(adtc),發(fā)送到選定卡,DAT線(xiàn)有數(shù)據(jù)傳輸。
另外,SD卡主機(jī)模塊系統(tǒng)旨在為各種應(yīng)用程序類(lèi)型提供一個(gè)標(biāo)準(zhǔn)接口。在此環(huán)境中,需要有特定的客戶(hù)/應(yīng)用程序功能。為實(shí)現(xiàn)這些功能, 在標(biāo)準(zhǔn)中定義了兩種類(lèi)型的通用命令:特定應(yīng)用命令(ACMD)和常規(guī)命令(GEN_CMD)。要使用SD卡制造商特定的ACMD命令如ACMD6, 需要在發(fā)送該命令之前發(fā)送CMD55命令,告知SD卡接下來(lái)的命令為特定應(yīng)用命令。CMD55命令只對(duì)緊接的第一個(gè)命令有效, SD卡如果檢測(cè)到CMD55之后的第一條命令為ACMD則執(zhí)行其特定應(yīng)用功能,如果檢測(cè)發(fā)現(xiàn)不是ACMD命令,則執(zhí)行標(biāo)準(zhǔn)命令。
3.3.3 命令描述
SD卡系統(tǒng)的命令被分為多個(gè)類(lèi),每個(gè)類(lèi)支持一種“卡的功能設(shè)置”。表 SD部分命令描述 列舉了SD卡部分命令信息, 更多詳細(xì)信息可以參考SD簡(jiǎn)易規(guī)格文件說(shuō)明,表中填充位和保留位都必須被設(shè)置為0。
雖然沒(méi)有必須完全記住每個(gè)命令詳細(xì)信息,但越熟悉命令對(duì)后面編程理解非常有幫助。
命令序號(hào) | 類(lèi)型 | 參數(shù) | 響應(yīng) | 縮寫(xiě) | 描述 |
CMD0 | bc | [31:0] 填充位 | -- | GO_IDLE_STATE | 復(fù)位所有的卡到 idle 狀態(tài)。 |
CMD2 | bcr | [31:0] 填充位 | R2 | ALL_SEND_CID | 通知所有卡通過(guò) CMD 線(xiàn)返回 CID 值。 |
CMD3 | bcr | [31:0] 填充位 | R6 | SEND_RELATIVE_ADDR | 通知所有卡發(fā)布新 RCA。 |
CMD4 | bc |
[31:16]DSR[15:0] 填充位 |
-- | SET_DSR | 編程所有卡的 DSR。 |
CMD7 | ac |
[31:16]RCA[15:0] 填充位 |
R1b | SELECT/DESELECT_CARD | 選擇 / 取消選擇 RCA 地址卡。 |
CMD8 | bcr |
[31:12] 保留位 [11:8] VHS [7:0] 檢查模式 |
R7 | SEND_IF_COND | 發(fā)送 SD 卡接口條件,包含主機(jī)支持的電壓信息,并詢(xún)問(wèn)卡是否支持。 |
CMD9 | ac |
[31:16]RCA[15:0] 填充位 |
R2 | SEND_CSD | 選定卡通過(guò) CMD 線(xiàn)發(fā)送 CSD 內(nèi)容 |
CMD10 | ac |
[31:16]RCA[15:0] 填充位 |
R2 | SEND_CID | 選定卡通過(guò) CMD 線(xiàn)發(fā)送 CID 內(nèi)容 |
CMD12 | ac | [31:0] 填充位 | R1b | STOP_TRANSMISSION | 強(qiáng)制卡停止傳輸 |
CMD13 | ac |
[31:16]RCA[15:0] 填充位 |
R1 | SEND_STATUS | 選定卡通過(guò) CMD 線(xiàn)發(fā)送它狀態(tài)寄存器 |
CMD15 | ac |
[31:16]RCA[15:0] 填充位 |
-- | GO_INACTIVE_STATE | 使選定卡進(jìn)入 “inactive” 狀態(tài) |
面向塊的讀操作 (Class 2) | |||||
CMD16 | ac | [31:0] 塊長(zhǎng)度填充位 | R1 | SET_BLOCK_LEN | 對(duì)于標(biāo)準(zhǔn) SD 卡,設(shè)置塊命令的長(zhǎng)度,對(duì)于 SDHC 卡塊命令長(zhǎng)度固定為 512 字節(jié)。 |
CMD17 | adtc | [31:0] 數(shù)據(jù)地址 | R1 | READ_SINGLE_BLOCK | 對(duì)于標(biāo)準(zhǔn)卡,讀取 SEL_BLOCK_LEN 長(zhǎng)度字節(jié)的塊;對(duì)于 SDHC 卡,讀取 512 字節(jié)的塊。 |
CMD18 | adtc | [31:0] 數(shù)據(jù)地址 | R1 | READ_MULTIPLE_BLOCK | 連續(xù)從 SD 卡讀取數(shù)據(jù)塊,直到被 CMD12 中斷。塊長(zhǎng)度同 CMD17。 |
面向塊的寫(xiě)操作 (Class 4) | |||||
CMD24 | adtc | [31:0] 數(shù)據(jù)地址 | R1 | WRITE_BLOCK | 對(duì)于標(biāo)準(zhǔn)卡,寫(xiě)入 SEL_BLOCK_LEN 長(zhǎng)度字節(jié)的塊;對(duì)于 SDHC 卡,寫(xiě)入 512 字節(jié)的塊。 |
CMD25 | adtc | [31:0] 數(shù)據(jù)地址 | R1 | WRITE_MULTIPLE_BLOCK | 連續(xù)向 SD 卡寫(xiě)入數(shù)據(jù)塊,直到被 CMD12 中斷。每塊長(zhǎng)度同 CMD17。 |
CMD27 | adtc | [31:0] 填充位 | R1 | PROGRAM_CSD | 對(duì) CSD 的可編程位進(jìn)行編程 |
擦除命令 (Class 5) | |||||
CMD32 | ac | [31:0] 數(shù)據(jù)地址 | R1 | ERASE_WR_BLK_START | 設(shè)置擦除的起始?jí)K地址 |
CMD33 | ac | [31:0] 數(shù)據(jù)地址 | R1 | ERASE_WR_BLK_END | 設(shè)置擦除的結(jié)束塊地址 |
CMD38 | ac | [31:0] 填充位 | R1b | ERASE | 擦除預(yù)先選定的塊 |
加鎖命令 (Class 7) | |||||
CMD42 | adtc | [31:0] 保留 | R1 | LOCK_UNLOCK | 加鎖 / 解鎖 SD 卡 |
特定應(yīng)用命令 (Class 8) | |||||
CMD55 | ac |
[31:16]RCA[15:0] 填充位 |
R1 | APP_CMD | 指定下個(gè)命令為特定應(yīng)用命令,不是標(biāo)準(zhǔn)命令 |
CMD56 | adtc | [31:1] 填充位 [0] 讀 / 寫(xiě) | R1 | GEN_CMD | 通用命令,或特定應(yīng)用命令中用于傳輸數(shù)據(jù)塊,最低位為 1 表示讀數(shù)據(jù),0 表示寫(xiě)數(shù)據(jù) |
SD 卡特定應(yīng)用命令 | |||||
ACMD6 | ac |
[31:2] 填充位 [1:0] 總線(xiàn)寬度 |
R1 | SET_BUS_WIDTH | 定義數(shù)據(jù)總線(xiàn)寬度 ('00'=1bit,'10'=4bit)。 |
ACMD13 | adtc | [31:0] 填充位 | R1 | SD_STATUS | 發(fā)送 SD 狀態(tài) |
ACMD41 | Bcr |
[32] 保留位 [30]HCS(OCR[30]) [29:24] 保留位 [23:0] VDD 電壓 (OCR[23:0]) |
R3 | SD_SEND_OP_COND | 主機(jī)要求卡發(fā)送支持信息 (HCS) 和 OCR 寄存器內(nèi)容。 |
ACMD51 | adtc | [31:0] 填充位 | R1 | SEND_SCR | 讀取配置寄存器 SCR |
3.4 響應(yīng)
響應(yīng)由SD卡向主機(jī)發(fā)出,部分命令要求SD卡作出響應(yīng),這些響應(yīng)多用于反饋SD卡的狀態(tài)。SDIO總共有7個(gè)響應(yīng)類(lèi)型(代號(hào):R1~R7), 其中SD卡沒(méi)有R4、R5類(lèi)型響應(yīng)。特定的命令對(duì)應(yīng)有特定的響應(yīng)類(lèi)型,比如當(dāng)主機(jī)發(fā)送CMD3命令時(shí),可以得到響應(yīng)R6。與命令一樣, SD卡的響應(yīng)也是通過(guò)CMD線(xiàn)連續(xù)傳輸?shù)?。根?jù)響應(yīng)內(nèi)容大小可以分為短響應(yīng)和長(zhǎng)響應(yīng)。短響應(yīng)是48bit長(zhǎng)度, 只有R2類(lèi)型是長(zhǎng)響應(yīng),其長(zhǎng)度為136bit。各個(gè)類(lèi)型響應(yīng)具體情況如表 SD卡響應(yīng)類(lèi)型 。
除了R3類(lèi)型之外,其他響應(yīng)都使用CRC7校驗(yàn)來(lái)校驗(yàn),對(duì)于R2類(lèi)型是使用CID和CSD寄存器內(nèi)部CRC7。
4 SD卡的操作模式及切換
4.1 SD卡的操作模式
SD卡有多個(gè)版本,W55MH32控制器目前最高支持《Physical Layer Simplified Specification V2.0》定義的SD卡,W55MH32控制器對(duì)SD卡進(jìn)行數(shù)據(jù)讀寫(xiě)之前需要識(shí)別卡的種類(lèi):V1.0標(biāo)準(zhǔn)卡、V2.0標(biāo)準(zhǔn)卡、V2.0高容量卡或者不被識(shí)別卡。
SD卡系統(tǒng)(包括主機(jī)和SD卡)定義了兩種操作模式:卡識(shí)別模式和數(shù)據(jù)傳輸模式。在系統(tǒng)復(fù)位后,主機(jī)處于卡識(shí)別模式, 尋找總線(xiàn)上可用的SDIO設(shè)備;同時(shí),SD卡也處于卡識(shí)別模式,直到被主機(jī)識(shí)別到,即當(dāng)SD卡接收到SEND_RCA(CMD3)命令后, SD卡就會(huì)進(jìn)入數(shù)據(jù)傳輸模式,而主機(jī)在總線(xiàn)上所有卡被識(shí)別后也進(jìn)入數(shù)據(jù)傳輸模式。在每個(gè)操作模式下, SD卡都有幾種狀態(tài),參考表 SD卡狀態(tài)與操作模式 ,通過(guò)命令控制實(shí)現(xiàn)卡狀態(tài)的切換。
4.2 卡識(shí)別模式
在卡識(shí)別模式下,主機(jī)會(huì)復(fù)位所有處于“卡識(shí)別模式”的SD卡,確認(rèn)其工作電壓范圍,識(shí)別SD卡類(lèi)型, 并且獲取SD卡的相對(duì)地址(卡相對(duì)地址較短,便于尋址)。在卡識(shí)別過(guò)程中,要求SD卡工作在識(shí)別時(shí)鐘頻率FOD的狀態(tài)下。 卡識(shí)別模式下SD卡狀態(tài)轉(zhuǎn)換如圖 卡識(shí)別模式狀態(tài)轉(zhuǎn)換圖 。
主機(jī)上電后,所有卡處于空閑狀態(tài),包括當(dāng)前處于無(wú)效狀態(tài)的卡。主機(jī)也可以發(fā)送GO_IDLE_STATE(CMD0)讓所有卡軟復(fù)位從而進(jìn)入空閑狀態(tài),但當(dāng)前處于無(wú)效狀態(tài)的卡并不會(huì)復(fù)位。
主機(jī)在開(kāi)始與卡通信前,需要先確定雙方在互相支持的電壓范圍內(nèi)。SD卡有一個(gè)電壓支持范圍,主機(jī)當(dāng)前電壓必須在該范圍可能才能與卡正常通信。 SEND_IF_COND(CMD8)命令就是用于驗(yàn)證卡接口操作條件的(主要是電壓支持)??〞?huì)根據(jù)命令的參數(shù)來(lái)檢測(cè)操作條件匹配性,如果卡支持主機(jī)電壓就產(chǎn)生響應(yīng), 否則不響應(yīng)。而主機(jī)則根據(jù)響應(yīng)內(nèi)容確定卡的電壓匹配性。CMD8是SD卡標(biāo)準(zhǔn)V2.0版本才有的新命令,所以如果主機(jī)有接收到響應(yīng),可以判斷卡為V2.0或更高版本SD卡。
SD_SEND_OP_COND(ACMD41)命令可以識(shí)別或拒絕不匹配它的電壓范圍的卡。ACMD41命令的VDD電壓參數(shù)用于設(shè)置主機(jī)支持電壓范圍,卡響應(yīng)會(huì)返回卡支持的電壓范圍。 對(duì)于對(duì)CMD8有響應(yīng)的卡,把ACMD41命令的HCS位設(shè)置為1,可以測(cè)試卡的容量類(lèi)型,如果卡響應(yīng)的CCS位為1說(shuō)明為高容量SD卡,否則為標(biāo)準(zhǔn)卡。 卡在響應(yīng)ACMD41之后進(jìn)入準(zhǔn)備狀態(tài),不響應(yīng)ACMD41的卡為不可用卡,進(jìn)入無(wú)效狀態(tài)。ACMD41是應(yīng)用特定命令,發(fā)送該命令之前必須先發(fā)CMD55。
ALL_SEND_CID(CMD2)用來(lái)控制所有卡返回它們的卡識(shí)別號(hào)(CID),處于準(zhǔn)備狀態(tài)的卡在發(fā)送CID之后就進(jìn)入識(shí)別狀態(tài)。之后主機(jī)就發(fā)送
SEND_RELATIVE_ADDR(CMD3)命令, 讓卡自己推薦一個(gè)相對(duì)地址(RCA)并響應(yīng)命令。這個(gè)RCA是16bit地址,而CID是128bit地址,使用RCA簡(jiǎn)化通信??ㄔ诮邮盏紺MD3并發(fā)出響應(yīng)后就進(jìn)入數(shù)據(jù)傳輸模式, 并處于待機(jī)狀態(tài),主機(jī)在獲取所有卡RCA之后也進(jìn)入數(shù)據(jù)傳輸模式。
4.3 數(shù)據(jù)傳輸模式
只有SD卡系統(tǒng)處于數(shù)據(jù)傳輸模式下才可以進(jìn)行數(shù)據(jù)讀寫(xiě)操作。數(shù)據(jù)傳輸模式下可以將主機(jī)SD時(shí)鐘頻率設(shè)置為FPP,默認(rèn)最高為25MHz, 頻率切換可以通過(guò)CMD4命令來(lái)實(shí)現(xiàn)。數(shù)據(jù)傳輸模式下,SD卡狀態(tài)轉(zhuǎn)換過(guò)程見(jiàn)圖 數(shù)據(jù)傳輸模式卡狀態(tài)轉(zhuǎn)換 。
CMD7用來(lái)選定和取消指定的卡,卡在待機(jī)狀態(tài)下還不能進(jìn)行數(shù)據(jù)通信,因?yàn)榭偩€(xiàn)上可能有多個(gè)卡都是出于待機(jī)狀態(tài), 必須選擇一個(gè)RCA地址目標(biāo)卡使其進(jìn)入傳輸狀態(tài)才可以進(jìn)行數(shù)據(jù)通信。同時(shí)通過(guò)CMD7命令也可以讓已經(jīng)被選擇的目標(biāo)卡返回到待機(jī)狀態(tài)。
數(shù)據(jù)傳輸模式下的數(shù)據(jù)通信都是主機(jī)和目標(biāo)卡之間通過(guò)尋址命令點(diǎn)對(duì)點(diǎn)進(jìn)行的。 卡處于傳輸狀態(tài)下可以使用表 SD部分命令描述 中面向塊的讀寫(xiě)以及擦除命令對(duì)卡進(jìn)行數(shù)據(jù)讀寫(xiě)、擦除。 CMD12可以中斷正在進(jìn)行的數(shù)據(jù)通信,讓卡返回到傳輸狀態(tài)。CMD0和CMD15會(huì)中止任何數(shù)據(jù)編程操作, 返回卡識(shí)別模式,這可能導(dǎo)致卡數(shù)據(jù)被損壞。
5 W55MH32的SDIO功能框圖
W55MH32控制器有一個(gè)SDIO,由兩部分組成:SDIO適配器和AHB接口,見(jiàn)下圖,SDIO功能框圖。SDIO適配器提供SDIO主機(jī)功能, 可以提供SD時(shí)鐘、發(fā)送命令和進(jìn)行數(shù)據(jù)傳輸。AHB接口用于控制器訪(fǎng)問(wèn)SDIO適配器寄存器并且可以產(chǎn)生中斷和DMA請(qǐng)求信號(hào)。
SDIO使用兩個(gè)時(shí)鐘信號(hào),一個(gè)是SDIO適配器時(shí)鐘(SDIOCLK=HCLK=72MHz),另外一個(gè)是AHB總線(xiàn)時(shí)鐘的二分頻(HCLK/2,一般為36MHz)。 適配器寄存器和FIFO使用AHB總線(xiàn)一側(cè)的時(shí)鐘(HCLK/2),控制單元、命令通道和數(shù)據(jù)通道使用SDIO適配器一側(cè)的時(shí)鐘(SDIOCLK)。
SDIO_CK是SDIO接口與SD卡用于同步的時(shí)鐘信號(hào)。它使用SDIOCLK作為SDIO_CK的時(shí)鐘來(lái)源, 可以通過(guò)設(shè)置BYPASS模式直接得到,這時(shí)SDIO_CK = SDIOCLK=HCLK。若禁止BYPASS模式, 可以通過(guò)配置時(shí)鐘寄存器的CLKDIV位控制分頻因子,即SDIO_CK=SDIOCLK/(2+CLKDIV)= HCLK/(2+CLKDIV)。 配置時(shí)鐘時(shí)要注意,SD卡普遍要求SDIO_CK時(shí)鐘頻率不能超過(guò)25MHz。
W55MH32控制器的SDIO是針對(duì)MMC卡和SD卡的主設(shè)備,所以預(yù)留有8根數(shù)據(jù)線(xiàn),對(duì)于SD卡最多用四根數(shù)據(jù)線(xiàn)。
SDIO適配器是SD卡系統(tǒng)主機(jī)部分,是W55MH32控制器與SD卡數(shù)據(jù)通信中間設(shè)備。SDIO適配器由五個(gè)單元組成, 分別是控制單元、命令路徑單元、數(shù)據(jù)路徑單元、寄存器單元以及FIFO,見(jiàn)下圖,SDIO適配器框圖:
5.1 控制單元
控制單元包含電源管理和時(shí)鐘管理功能,結(jié)構(gòu)如圖 SDIO適配器控制單元 。 電源管理部件會(huì)在系統(tǒng)斷電和上電階段禁止SD卡總線(xiàn)輸出信號(hào)。時(shí)鐘管理部件控制CLK線(xiàn)時(shí)鐘信號(hào)生成。一般使用SDIOCLK分頻得到。
5.2 命令路徑
命令路徑控制命令發(fā)送,并接收卡的響應(yīng),結(jié)構(gòu)見(jiàn)下圖,SDIO適配器命令路徑:
關(guān)于SDIO適配器狀態(tài)轉(zhuǎn)換流程可以參考圖 卡識(shí)別模式狀態(tài)轉(zhuǎn)換圖 , 當(dāng)SD卡處于某一狀態(tài)時(shí),SDIO適配器必然處于特定狀態(tài)與之對(duì)應(yīng)。 W55MH32控制器以命令路徑狀態(tài)機(jī)(CPSM)來(lái)描述SDIO適配器的狀態(tài)變化,并加入了等待超時(shí)檢測(cè)功能, 以便退出永久等待的情況。CPSM的描述見(jiàn)下圖,CPSM狀態(tài)機(jī)描述圖:
5.3 數(shù)據(jù)路徑
數(shù)據(jù)路徑部件負(fù)責(zé)與SD卡相互數(shù)據(jù)傳輸,內(nèi)部結(jié)構(gòu)見(jiàn)下圖,SDIO適配器數(shù)據(jù)路徑:
SD卡系統(tǒng)數(shù)據(jù)傳輸狀態(tài)轉(zhuǎn)換參考圖 數(shù)據(jù)傳輸模式卡狀態(tài)轉(zhuǎn)換 , SDIO適配器以數(shù)據(jù)路徑狀態(tài)機(jī)(DPSM)來(lái)描述SDIO適配器狀態(tài)變化情況。 并加入了等待超時(shí)檢測(cè)功能,以便退出永久等待情況。發(fā)送數(shù)據(jù)時(shí),DPSM處于等待發(fā)送(Wait_S)狀態(tài),如果數(shù)據(jù)FIFO不為空, DPSM變成發(fā)送狀態(tài)并且數(shù)據(jù)路徑部件啟動(dòng)向卡發(fā)送數(shù)據(jù)。接收數(shù)據(jù)時(shí),DPSM處于等待接收狀態(tài),當(dāng)DPSM收到起始位時(shí)變成接收狀態(tài), 并且數(shù)據(jù)路徑部件開(kāi)始從卡接收數(shù)據(jù)。DPSM狀態(tài)機(jī)描述見(jiàn)下圖,DPSM狀態(tài)機(jī)描述圖:
5.4 數(shù)據(jù)FIFO
數(shù)據(jù)FIFO(先進(jìn)先出)部件是一個(gè)數(shù)據(jù)緩沖器,帶發(fā)送和接收單元??刂破鞯腇IFO包含寬度為32bit、 深度為32字的數(shù)據(jù)緩沖器和發(fā)送/接收邏輯。其中SDIO狀態(tài)寄存器(SDIO_STA)的TXACT位用于指示當(dāng)前正在發(fā)送數(shù)據(jù), RXACT位指示當(dāng)前正在接收數(shù)據(jù),這兩個(gè)位不可能同時(shí)為1。
當(dāng)TXACT為1時(shí),可以通過(guò)AHB接口將數(shù)據(jù)寫(xiě)入到傳輸FIFO。
當(dāng)RXACT為1時(shí),接收FIFO存放從數(shù)據(jù)路徑部件接收到的數(shù)據(jù)。
根據(jù)FIFO空或滿(mǎn)狀態(tài)會(huì)把SDIO_STA寄存器位值1,并可以產(chǎn)生中斷和DMA請(qǐng)求。
5.5 適配器寄存器
適配器寄存器包含了控制SDIO外設(shè)的各種控制寄存器及狀態(tài)寄存器,內(nèi)容較多, 可以通過(guò)SDIO提供的各種結(jié)構(gòu)體來(lái)了解,這些寄存器的功能都被整合到了結(jié)構(gòu)體或ST標(biāo)準(zhǔn)庫(kù)之中。
6 SDIO初始化結(jié)構(gòu)體
標(biāo)準(zhǔn)庫(kù)函數(shù)對(duì)SDIO外設(shè)建立了三個(gè)初始化結(jié)構(gòu)體,分別為SDIO初始化結(jié)構(gòu)體SDIO_InitTypeDef、SDIO命令初始化結(jié)構(gòu)體SDIO_CmdInitTypeDef和SDIO數(shù)據(jù)初始化結(jié)構(gòu)體SDIO_DataInitTypeDef。 這些結(jié)構(gòu)體成員用于設(shè)置SDIO工作環(huán)境參數(shù),并由SDIO相應(yīng)初始化配置函數(shù)或功能函數(shù)調(diào)用,這些參數(shù)將會(huì)被寫(xiě)入到SDIO相應(yīng)的寄存器,達(dá)到配置SDIO工作環(huán)境的目的。
初始化結(jié)構(gòu)體和初始化庫(kù)函數(shù)配合使用是標(biāo)準(zhǔn)庫(kù)精髓所在,理解了初始化結(jié)構(gòu)體每個(gè)成員意義基本上就可以對(duì)該外設(shè)運(yùn)用自如了。 初始化結(jié)構(gòu)體定義在w55mh32_sdio.h文件中,初始化庫(kù)函數(shù)定義在w55mh32_sdio.c文件中,編程時(shí)我們可以結(jié)合這兩個(gè)文件內(nèi)注釋使用。
SDIO初始化結(jié)構(gòu)體用于配置SDIO基本工作環(huán)境,比如時(shí)鐘分頻、時(shí)鐘沿、數(shù)據(jù)寬度等等。它被SDIO_Init()函數(shù)使用。
代碼清單:SDIO-1 SDIO初始化結(jié)構(gòu)體
typedef struct { uint32_t SDIO_ClockEdge; // 時(shí)鐘沿 uint32_t SDIO_ClockBypass; // 旁路時(shí)鐘 uint32_t SDIO_ClockPowerSave; // 節(jié)能模式 uint32_t SDIO_BusWide; // 數(shù)據(jù)寬度 uint32_t SDIO_HardwareFlowControl; // 硬件流控制 uint8_t SDIO_ClockDiv; // 時(shí)鐘分頻 } SDIO_InitTypeDef;
各結(jié)構(gòu)體成員的作用介紹如下:
SDIO_ClockEdge:主時(shí)鐘SDIOCLK產(chǎn)生CLK引腳時(shí)鐘有效沿選擇,可選上升沿或下降沿, 它設(shè)定SDIO時(shí)鐘控制寄存器(SDIO_CLKCR)的NEGEDGE位的值,一般選擇設(shè)置為高電平。
SDIO_ClockBypass:時(shí)鐘分頻旁路使用,可選使能或禁用,它設(shè)定SDIO_CLKCR寄存器的BYPASS位。如果使能旁路,SDIOCLK直接驅(qū)動(dòng)CLK線(xiàn)輸出時(shí)鐘; 如果禁用,使用SDIO_CLKCR寄存器的CLKDIV位值分頻SDIOCLK,然后輸出到CLK線(xiàn)。一般選擇禁用時(shí)鐘分頻旁路。
SDIO_ClockPowerSave:節(jié)能模式選擇,可選使能或禁用,它設(shè)定SDIO_CLKCR寄存器的PWRSAV位的值。如果使能節(jié)能模式, CLK線(xiàn)只有在總線(xiàn)激活時(shí)才有時(shí)鐘輸出;如果禁用節(jié)能模式,始終使能CLK線(xiàn)輸出時(shí)鐘。
SDIO_BusWide:數(shù)據(jù)線(xiàn)寬度選擇,可選1位數(shù)據(jù)總線(xiàn)、4位數(shù)據(jù)總線(xiàn)或8為數(shù)據(jù)總線(xiàn),系統(tǒng)默認(rèn)使用1位數(shù)據(jù)總線(xiàn), 操作SD卡時(shí)在數(shù)據(jù)傳輸模式下一般選擇4位數(shù)據(jù)總線(xiàn)。它設(shè)定SDIO_CLKCR寄存器的WIDBUS位的值。
SDIO_HardwareFlowControl:硬件流控制選擇,可選使能或禁用,它設(shè)定SDIO_CLKCR寄存器的HWFC_EN位的值。 硬件流控制功能可以避免FIFO發(fā)送上溢和下溢錯(cuò)誤。
SDIO_ClockDiv:時(shí)鐘分頻系數(shù),它設(shè)定SDIO_CLKCR寄存器的CLKDIV位的值, 設(shè)置SDIOCLK與CLK線(xiàn)輸出時(shí)鐘分頻系數(shù):
CLK線(xiàn)時(shí)鐘頻率=SDIOCLK/([CLKDIV+2])。
7 SDIO命令初始化結(jié)構(gòu)體
SDIO命令初始化結(jié)構(gòu)體用于設(shè)置命令相關(guān)內(nèi)容,比如命令號(hào)、命令參數(shù)、響應(yīng)類(lèi)型等等。它被SDIO_SendCommand()函數(shù)使用。
代碼清單:SDIO-2 SDIO命令初始化接口
typedef struct { uint32_t SDIO_Argument; // 命令參數(shù) uint32_t SDIO_CmdIndex; // 命令號(hào) uint32_t SDIO_Response; // 響應(yīng)類(lèi)型 uint32_t SDIO_Wait; // 等待使能 uint32_t SDIO_CPSM; // 命令路徑狀態(tài)機(jī) } SDIO_CmdInitTypeDef;
各個(gè)結(jié)構(gòu)體成員介紹如下:
SDIO_Argument:作為命令的一部分發(fā)送到卡的命令參數(shù), 它設(shè)定SDIO參數(shù)寄存器(SDIO_ARG)的值。
SDIO_CmdIndex:命令號(hào)選擇, 它設(shè)定SDIO命令寄存器(SDIO_CMD)的CMDINDEX位的值。
SDIO_Response:響應(yīng)類(lèi)型,SDIO定義兩個(gè)響應(yīng)類(lèi)型:長(zhǎng)響應(yīng)和短響應(yīng)。根據(jù)命令號(hào)選擇對(duì)應(yīng)的響應(yīng)類(lèi)型。 SDIO定義了四個(gè)32位的SDIO響應(yīng)寄存器(SDIO_RESPx,x=1..4),短響應(yīng)只用到SDIO_RESP1。
SDIO_Wait:等待類(lèi)型選擇,有三種狀態(tài)可選,一種是無(wú)等待狀態(tài),超時(shí)檢測(cè)功能啟動(dòng);一種是等待中斷, 另外一種是等待傳輸完成。它設(shè)定SDIO_CMD寄存器的WAITPEND位和WAITINT位的值。
SDIO_CPSM:命令路徑狀態(tài)機(jī)控制,可選使能或禁用CPSM。 它設(shè)定SDIO_CMD寄存器的CPSMEN位的值。
8 SDIO數(shù)據(jù)初始化結(jié)構(gòu)體
SDIO數(shù)據(jù)初始化結(jié)構(gòu)體用于配置數(shù)據(jù)發(fā)送和接收參數(shù),比如傳輸超時(shí)、數(shù)據(jù)長(zhǎng)度、傳輸模式等等。它被SDIO_DataConfig()函數(shù)使用。
代碼清單:SDIO-3 SDIO數(shù)據(jù)初始化結(jié)構(gòu)體
typedef struct { uint32_t SDIO_DataTimeOut; // 數(shù)據(jù)傳輸超時(shí) uint32_t SDIO_DataLength; // 數(shù)據(jù)長(zhǎng)度 uint32_t SDIO_DataBlockSize; // 數(shù)據(jù)塊大小 uint32_t SDIO_TransferDir; // 數(shù)據(jù)傳輸方向 uint32_t SDIO_TransferMode; // 數(shù)據(jù)傳輸模式 uint32_t SDIO_DPSM; // 數(shù)據(jù)路徑狀態(tài)機(jī) } SDIO_DataInitTypeDef;
各結(jié)構(gòu)體成員介紹如下:
SDIO_DataTimeOut:設(shè)置數(shù)據(jù)傳輸以卡總線(xiàn)時(shí)鐘周期表示的超時(shí)周期,它設(shè)定SDIO數(shù)據(jù)定時(shí)器寄存器(SDIO_DTIMER)的值。 在DPSM進(jìn)入Wait_R或繁忙狀態(tài)后開(kāi)始遞減,直到0還處于以上兩種狀態(tài)則將超時(shí)狀態(tài)標(biāo)志置1.
SDIO_DataLength:設(shè)置傳輸數(shù)據(jù)長(zhǎng)度, 它設(shè)定SDIO數(shù)據(jù)長(zhǎng)度寄存器(SDIO_DLEN)的值。
SDIO_DataBlockSize:設(shè)置數(shù)據(jù)塊大小,有多種尺寸可選, 不同命令要求的數(shù)據(jù)塊可能不同。它設(shè)定SDIO數(shù)據(jù)控制寄存器(SDIO_DCTRL)寄存器的DBLOCKSIZE位的值。
SDIO_TransferDir:數(shù)據(jù)傳輸方向,可選從主機(jī)到卡的寫(xiě)操作, 或從卡到主機(jī)的讀操作。它設(shè)定SDIO_DCTRL寄存器的DTDIR位的值。
SDIO_TransferMode:數(shù)據(jù)傳輸模式,可選數(shù)據(jù)塊或數(shù)據(jù)流模式。 對(duì)于SD卡操作使用數(shù)據(jù)塊類(lèi)型。它設(shè)定SDIO_DCTRL寄存器的DTMODE位的值。
SDIO_DPSM:數(shù)據(jù)路徑狀態(tài)機(jī)控制,可選使能或禁用DPSM。 它設(shè)定SDIO_DCTRL寄存器的DTEN位的值。要實(shí)現(xiàn)數(shù)據(jù)傳輸都必須使能SDIO_DPSM。
9 SD卡讀寫(xiě)測(cè)試
9.1 代碼解析
基于 W55MH32 的 SD 卡文件系統(tǒng)測(cè)試程序,借助 FATFS 文件系統(tǒng)庫(kù)對(duì) SD 卡進(jìn)行讀寫(xiě)、目錄創(chuàng)建與刪除等操作。下面是對(duì)代碼的詳細(xì)解釋?zhuān)?/p>
1. 頭文件包含
#include "w55mh32.h" #include ?stdio.h??> #include "bsp_sdio_sdcard.h" #include "sdio_test.h" #include "delay.h" #include "ff.h"
這些頭文件涵蓋了硬件相關(guān)的定義、標(biāo)準(zhǔn)輸入輸出庫(kù)、SD 卡驅(qū)動(dòng)、延時(shí)函數(shù)以及 FATFS 文件系統(tǒng)庫(kù)。
2. 函數(shù)聲明
void USART_Config(uint32_t bound); uint8_t GetCmd(void); void TestList(void); void ShowCardInfo(void); void SDInfoShow(void); void FatfsTest(void); void FatfsBigDataTest(void); void WriteFileTest(void); void CreateDir(void); void DeleteDirFile(void); void ViewRootDir(void);
這里聲明了一系列函數(shù),用于串口配置、命令獲取、測(cè)試列表顯示、SD 卡信息顯示、文件系統(tǒng)測(cè)試等。
3. 全局變量定義
FATFS fs; FIL fnew; FRESULT res_sd; UINT fnum; BYTE ReadBuffer[1024] = {0}; BYTE WriteBuffer[] = "WIZnet, create a new file system test filen"; #define TEST_FILE_LEN (2 * 1024 * 1024) #define BUF_SIZE (4 * 1024) uint8_t TestBuf[BUF_SIZE];
這些變量用于存儲(chǔ) FATFS 文件系統(tǒng)對(duì)象、文件對(duì)象、文件操作結(jié)果、讀寫(xiě)文件數(shù)量、讀寫(xiě)緩沖區(qū)等。
4. 主函數(shù) main()
int main(void) { uint8_t cmd = 0; RCC_ClocksTypeDef clocks; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); delay_init(); UART_Configuration(115200); RCC_GetClocksFreq(&clocks); printf("n"); printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn", (float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000, (float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000); printf("SDIO SD Card Fatfs Test.n"); TestList(); while (1) { cmd = GetCmd(); switch (cmd) { case '1': { printf("1.--->>>FatfsTestrn"); FatfsTest(); TestList(); break; } case '2': { printf("1.--->>>FatfsBigDataTestrn"); FatfsBigDataTest(); TestList(); break; } case '3': { printf("2.--->>>ViewRootDirrn"); ViewRootDir(); TestList(); break; } case '4': { printf("3.--->>>CreateDirrn"); CreateDir(); TestList(); break; } case '5': { printf("4.--->>>DeleteDirFilern"); DeleteDirFile(); TestList(); break; } } } }
主函數(shù)的功能如下:
初始化 CRC 時(shí)鐘、延時(shí)函數(shù)和串口。
打印系統(tǒng)時(shí)鐘信息。
顯示測(cè)試列表。
進(jìn)入無(wú)限循環(huán),不斷獲取用戶(hù)輸入的命令,并依據(jù)命令調(diào)用相應(yīng)的測(cè)試函數(shù)。
5. 測(cè)試列表函數(shù) TestList()
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"); }
該函數(shù)用于顯示 SD 卡測(cè)試的選項(xiàng)列表。
6. SD 卡信息顯示函數(shù) SDInfoShow()
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); }
此函數(shù)用于顯示 SD 卡的類(lèi)型、容量和塊大小等信息。
7. 獲取命令函數(shù) GetCmd()
uint8_t GetCmd(void) { uint8_t tmp = 0; if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) { tmp = USART_ReceiveData(USART1); } return tmp; }
該函數(shù)用于檢查串口是否接收到數(shù)據(jù),若接收到則返回該數(shù)據(jù)。
8. 串口配置函數(shù) UART_Configuration()
void UART_Configuration(uint32_t bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART_TEST, &USART_InitStructure); USART_Cmd(USART_TEST, ENABLE); }
該函數(shù)用于配置串口的 GPIO 引腳和串口參數(shù)。
9. 大數(shù)據(jù)讀寫(xiě)測(cè)試函數(shù) FatfsBigDataTest()
void FatfsBigDataTest(void) { uint32_t i; res_sd = f_mount(&fs, "0:", 1); 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"); } }
該函數(shù)用于進(jìn)行大數(shù)據(jù)量的文件寫(xiě)入測(cè)試,先掛載文件系統(tǒng),然后打開(kāi)文件,循環(huán)寫(xiě)入數(shù)據(jù)。
10. 文件系統(tǒng)測(cè)試函數(shù) FatfsTest()
void FatfsTest(void) { res_sd = f_mount(&fs, "0:", 1); 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(); 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"); } 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); }
該函數(shù)用于進(jìn)行文件系統(tǒng)的格式化、讀寫(xiě)測(cè)試,若 SD 卡沒(méi)有文件系統(tǒng)則進(jìn)行格式化,然后進(jìn)行文件的讀寫(xiě)操作。
11. 創(chuàng)建目錄函數(shù) CreateDir()
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); }
該函數(shù)用于在 SD 卡上創(chuàng)建目錄 /Dir1、/Dir2 和 /Dir1/Dir1_1。
12. 刪除目錄和文件函數(shù) DeleteDirFile()
void DeleteDirFile(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_unlink("/Dir1/Dir1_1"); if (res_sd == FR_OK) { printf("Delete subdirectory /Dir1/Dir1_1 successrn"); } else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH)) { printf("No file or directory found: %srn", "/Dir1/Dir1_1"); } else { printf("Deleting subdirectory/Dir1/Dir1_1 failed (errcode =% d) File read-only or directory not emptyrn", res_sd); } res_sd = f_unlink("/Dir1"); if (res_sd == FR_OK) { printf("Delete directory/Dir1 successfullyrn"); } else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH)) { printf("No file or directory found : %srn", "/Dir1"); } else { printf("Deleting subdirectory/Dir1/Dir1_1 failed (errcode =% d) File read-only or directory not emptyrn", res_sd); } res_sd = f_unlink("/Dir2"); if (res_sd == FR_OK) { printf("Delete/Dir2 successfullyrn"); } else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH)) { printf("No file or directory found : %srn", "/Dir2"); } else { printf("Deleting subdirectory/Dir1/Dir1_1 failed (errcode = %d) File read-only or directory is not emptyrn", res_sd); } res_sd = f_unlink("FatFs read and write test files.txt"); if (res_sd == FR_OK) { printf("Delete FatFs read and write test file.txt successfullyrn"); } else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH)) { printf("No file or directory found : %srn", "/FatFs read and write test files.txt"); } else { printf("Failed to delete FatFs read and write test file.txt(errcode = %d) File read-only or directory is not emptyrn", res_sd); } f_mount(NULL, "0:", 1); }
該函數(shù)用于刪除之前創(chuàng)建的目錄和文件。
13. 查看根目錄函數(shù) ViewRootDir()
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); }
14. 串口發(fā)送字符函數(shù) SER_PutChar() 和 fputc()
int SER_PutChar(int ch) { while (!USART_GetFlagStatus(USART_TEST, USART_FLAG_TC)); USART_SendData(USART_TEST, (uint8_t)ch); return ch; } int fputc(int c, FILE *f) { if (c == 'n') { SER_PutChar('r'); } return (SER_PutChar(c)); }
這段代碼借助 FATFS 文件系統(tǒng)庫(kù),實(shí)現(xiàn)了對(duì) SD 卡的文件讀寫(xiě)、目錄創(chuàng)建與刪除、查看根目錄等操作,并且提供了一個(gè)簡(jiǎn)單的菜單界面,方便用戶(hù)進(jìn)行測(cè)試。
9.2 下載驗(yàn)證
1. 程序上電運(yùn)行
2. 輸入命令測(cè)試
通過(guò)鍵盤(pán)輸入菜單中的數(shù)字鍵(1~5)執(zhí)行對(duì)應(yīng)功能:
(1) 測(cè)試 1: 基礎(chǔ)文件讀寫(xiě) (輸入 1)
功能:
創(chuàng)建文件 FatFs read and write test files.txt,寫(xiě)入文本并回讀。
(2) 測(cè)試 2: 大數(shù)據(jù)量讀寫(xiě) (輸入 2)
功能:
向文件中寫(xiě)入 2MB 數(shù)據(jù)(用于壓力測(cè)試),每寫(xiě)入 36KB 輸出一次進(jìn)度。
(3) 測(cè)試 3: 查看根目錄 (輸入 3)
功能:
顯示 SD 卡根目錄下的文件和子目錄。
(4) 測(cè)試 4: 創(chuàng)建目錄 (輸入 4)
功能:
創(chuàng)建 /Dir1, /Dir1/Dir1_1, /Dir2 目錄。
(5)測(cè)試 5: 刪除目錄/文件 (輸入 5)
功能:
刪除測(cè)試文件和目錄(需確保目錄為空)。
WIZnet 是一家無(wú)晶圓廠(chǎng)半導(dǎo)體公司,成立于 1998 年。產(chǎn)品包括互聯(lián)網(wǎng)處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術(shù),基于獨(dú)特的專(zhuān)利全硬連線(xiàn) TCP/IP。iMCU? 面向各種應(yīng)用中的嵌入式互聯(lián)網(wǎng)設(shè)備。
WIZnet 在全球擁有 70 多家分銷(xiāo)商,在香港、韓國(guó)、美國(guó)設(shè)有辦事處,提供技術(shù)支持和產(chǎn)品營(yíng)銷(xiāo)。
香港辦事處管理的區(qū)域包括:澳大利亞、印度、土耳其、亞洲(韓國(guó)和日本除外)。
-
單片機(jī)
+關(guān)注
關(guān)注
6067文章
44982瀏覽量
650271 -
控制器
+關(guān)注
關(guān)注
114文章
17097瀏覽量
184176 -
SD卡
+關(guān)注
關(guān)注
2文章
578瀏覽量
65653 -
SDIO
+關(guān)注
關(guān)注
2文章
76瀏覽量
19934
發(fā)布評(píng)論請(qǐng)先 登錄
第二十五章 FLASH

《DNK210使用指南 -CanMV版 V1.0》第二十五章 LCD圖片顯示實(shí)驗(yàn)
【正點(diǎn)原子FPGA連載】第二十七章gpio子系統(tǒng)下的LED驅(qū)動(dòng)實(shí)驗(yàn)-領(lǐng)航者ZYNQ之linux開(kāi)發(fā)指南
在顯示器上顯示出了靜態(tài)的彩條圖案
第二十五講 同步計(jì)數(shù)器

模擬電路網(wǎng)絡(luò)課件 第二十五節(jié):集成運(yùn)算放大器中的電流源

【正點(diǎn)原子FPGA連載】第二十五章HDMI方塊移動(dòng)實(shí)驗(yàn) -摘自【正點(diǎn)原子】新起點(diǎn)之FPGA開(kāi)發(fā)指南_V2.1

2023高交會(huì)|第二十五屆中國(guó)國(guó)際高新技術(shù)交易會(huì)·招商工作全面啟動(dòng)

火熱預(yù)定中2023第二十五屆中國(guó)國(guó)際高新技術(shù)交易會(huì)11.15-11.19日
火熱招商--2023第二十五屆中國(guó)國(guó)際高新技術(shù)交易會(huì)11.15-11.19日
中軟國(guó)際與深開(kāi)鴻邀您相約第二十五屆中國(guó)國(guó)際軟件博覽會(huì)
上海貝嶺榮獲“第二十五屆上市公司金信披獎(jiǎng)”
【GD32F303紅楓派開(kāi)發(fā)板使用手冊(cè)】第二十三講 SDIO-SD卡讀寫(xiě)實(shí)驗(yàn)

評(píng)論