費 超,趙英俊
(華中科技大學 機械科學與工程學院,湖北 武漢 430074)
嵌入式實時操作系統μC/OS具有源代碼公開、良好的實時性等優點,廣泛應用于各種嵌入式系統中,特別是實時數據采集與處理的嵌入式系統。這種嵌入式系統往往需要存儲大量的數據,并且需要將存儲的數據方便地轉移到PC平臺進行后續的離線分析。
常見的嵌入式系統往往采用EEPROM外部存儲芯片,容量小、速度慢而且不便于數據的移動,因此需要結合硬件平臺選擇一種大容量且具有移動靈活性的存儲設備。另外,考慮到在PC平臺的離線處理的便捷需要,存儲系統采用廣泛應用的FAT文件系統。
由于S3C2440具有專門的SDIO接口,且SD卡具有容量大、速度快、移動靈活和安全性高等優點[1]。綜合考慮,選擇采用SD卡作為移動存儲設備。
軟件設計上,首先要實現在μC/OS下的SD卡驅動,同時要保證兼容標準SD卡和SDHC卡。完成SD卡驅動后,還要在基于μC/OS的嵌入式系統中方便地實現對FAT文件系統下的文件的多種操作。如果從無到有設計FAT文件系統軟件模塊,將費時費力并且難以保證軟件模塊的可靠性。因此,最好的方案是采用通用的FAT文件系統軟件模塊,只需要進行較少的移植工作,完成項目效率大大增加。
通用的 FAT 文件系統主要有 μC/FS、FatFs、EFSL、ZLG/FS、znFAT等。其中μC/FS是Micrium公司開發的一個商業用途的文件系統,兼容性、穩定性較好。ZLG/FS和znFAT主要面向學習用途。而FatFs是免費開源的項目,具有代碼精簡、易于移植、支持RTOS、支持Unicode長文件名等特點,特別是其提供的底層讀寫函數,具有讀寫塊數量的參數,可以一次命令讀寫多個扇區,在速度與效率上具有明顯優勢,而μC/FS和EFSL都不提供塊數量參數。因此,選擇FatFs作為文件系統軟件模塊。

圖1 系統總體結構圖Fig.1 Structure diagram of the system
總體方案采用基于SDIO接口的SD卡存儲設備和FatFs文件系統,其系統總體結構如圖1所示。SD卡從S3C2440微處理器的SDIO接口接入硬件層,通過SD卡驅動程序提供給FatFs文件系統進行管理,然后用戶在功能層調用FatFs提供的文件接口函數進行數據存儲等任務。
如圖2所示為本次SD卡硬件電路圖,其中S3C2440微處理器上有SDIO控制器,連接的SD總線包括時鐘線CLK、命令線CMD及4根數據線 (DAT0~DAT3)[2]。S3C2440通過SDIO接口與SD卡座相連,其中卡座上除了6根SD總線外,還有3根電源線,以及無卡檢測引腳nCD和寫保護引腳WP。其中nCD和WP是連接到卡座上的兩個常開型機械開關,開關的另一端接地。當插入SD卡時,開關合上,nCD從高電平變為低電平,當插入的是未寫保護的SD卡時,另一個開關也會合上,WP從高電平變為低電平,而未插入SD卡以及插入寫保護的SD卡時,WP被上拉成高電平。SD卡側面的寫保護的撥動開關實現寫保護的原理不是通過開閉SD卡內部的線路,而是通過不同位置作用于SD卡座內的機械彈性開關的開閉。SD卡有9個引腳,支持SD和SPI兩種總線方式,其中SD總線方式又分為1位數據模式和4位數據模式,本文設計采用采用4位數據模式,可以獲得更高傳輸速率,具體過程在SD卡驅動中實現。

圖2 硬件電路圖Fig.2 Hardware circuit diagram
SD卡驅動程序的功能是給FatFs文件系統提供對SD卡的讀寫操作接口,屏蔽掉上層軟件對硬件的直接操作,其中主要包括初始化SD卡、讀數據、寫數據等。現在市場上的SD卡有SD1.0協議下的標準容量卡、SD2.0協議下的標準容量卡和高容量卡(SDHC),為了使驅動程序兼容性好,必須同時支持這些類型。
在初始化SD卡時,要識別并記錄SD卡的類型,然后在讀寫數據時,根據不同類型進行操作。SD卡通信是由主機控制,通過CMD線發出不同類型的命令(Command),然后被尋址的SD卡在CMD線上產生相應的響應(Response),當CMD線上是數據傳輸命令時,數據線DAT0或DAT0~DAT3接著進行數據傳輸。
SD卡初始化流程圖如圖 3所示,最開始初始化SD卡控制器時,配置SD卡工作在傳輸效率較高的4位數據傳輸模式。命令CMD0實現復位SD卡,使其進入到空閑狀態,命令CMD8是SD2.0協議新增加的接口條件檢查命令,用來檢查電壓匹配和擴展SD1.0協議中某些原有命令的功能,例如命令ACMD41在參數中增加了HCS(Host Capacity Support)位,在響應中增加了CCS(Card Capacity Status)位,同時也能根據SD卡是否產生響應來判斷SD卡版本,SD1.0版本的SD卡不能識別該命令,不會產生響應。同時通過SD卡返回的響應中的CCS位來判斷是否為SDHC卡。另外,針對讀寫SD卡時的差異,將SD卡總結為兩種類型,標準容量SD卡 (包括SD1.0和SD2.0標準容量卡)和高容量SD卡,在后面進行讀寫數據時,要分別處理。最后發送命令CMD2和CMD3使SD卡從卡識別模式進入數據傳輸模式,處于等待狀態,后面可以發送相關存儲器訪問命令。
在本設計中,結合FatFs的移植需要,將用到的存儲器訪問 命 令 有 塊 讀 取 命 令 (CMD17,CMD18), 塊 寫 入 命 令(CMD24,CMD25),其中 CMD17和 CMD24為單塊操作命令,CMD18和CMD25為連續多塊操作命令[3]。以下為標準容量SD卡和高容量SD卡在存儲器訪問命令上的主要功能區別。
1)存儲器訪問的命令參數(Command Argument)。標準容量SD卡的32位命令參數是對字節尋址,高容量SD卡的命令參數是對塊尋址。
2)塊長度。標準容量SD卡的塊長度根據CMD16命令設置大小,而高容量SD卡的塊大小固定為512字節,必須設置塊大小寄存器為0x200。
除此之外,兩者還有局部尋址、寫保護、讀寫超時等方面的區別,針對以上主要區別,采用以下解決辦法實現同時兼容兩種SD卡。讀寫數據函數給上層文件系統模塊提供對SD卡的塊地址訪問,并統一塊大小為512Byte。如圖 4為SD卡讀取單塊數據的流程圖,在發送讀取命令CMD17前先根據初始化SD卡時確定的卡類型來進行處理。



圖3 SD卡初始化流程圖Fig.3 SD cardinitialization flow chart
提供的變量是塊地址,因此可以直接作為高容量卡的命令參數,而標準容量SD卡的命令參數是字節單位,需要塊地址乘以塊大小(512Byte),即左移9位,轉換為字節地址。其他塊讀寫命令CMD18、CMD24、CMD25處理辦法與此相同,實現多塊讀取函數、單塊寫入函數、多塊寫入函數。

圖4 讀取單塊數據流程圖Fig.4 Flow chart of reading a block
SD卡驅動程序還支持SD卡插拔檢測和寫保護功能。配置無卡檢測接入引腳為外部中斷方式,并設計中斷處理函數,隨時通知軟件系統當前SD卡的插拔狀態。SD卡的寫保護采用軟件方式實現,實現方法有兩種,一種是在SD卡的兩個寫數據的驅動函數開始處加入查詢寫保護引腳狀態,一旦寫保護開啟,則通知軟件系統,并取消執行后面寫數據流程。另一種可選方法是在FatFs文件系統層實現。
FatFS是一個為小型嵌入式系統設計的通用FAT文件系統模塊。FatFs的編寫遵循ANSI C,并且完全與磁盤I/O層分開。因此,它獨立于硬件架構。它可以被嵌入到低成本的微控制器中而不需要做任何修改。FatFs已經封裝了對文件系統層和磁盤管理層的操作。對它的移植,主要在于配置FatFs功能和寫好SD卡驅動接口[4]。
FatFs的配置選項在ffconf.h中,實現文件系統接口函數的剪裁,需要結合嵌入式系統硬件平臺和具體應用來設置。由于本次系統平臺是小端模式,為了獲得較好的軟件性能,_WORD_ACCESS設為1,配置為字訪問,比字節訪問快;由于SD卡屬于Menory Card,_MAX_SS必須設為512,代表塊大小最大為512 Byte;其他采用默認設置即可。
底層接口函數有6個,位于diskio.c中,主要是調用SD卡驅動程序實現。
1)disk_initialize():磁盤初始化函數,調用 SD 卡初始化函數實現。
2)disk_read:讀扇區函數,調用SD卡塊讀取函數實現。
3)disk_write:寫扇區函數,調用SD卡塊寫入函數實現。
4)disk_status:狀態檢測函數,共包含三種返回狀態,包括STA_NOINIT ( 未 初 始 化 )、STA_NODISK ( 無 磁 盤 )、STA_PROCTECTED(卡保護)。可以在此處查詢SD卡寫保護引腳的狀態,返回STA_POCTECTED卡保護狀態。正常返回0即可。
5)disk_ioctl:磁盤控制函數,包括獲取磁盤容量等,在文件系統實現一些復雜功能時會用到,簡單應用直接返回0即可。
6)get_fattime:獲取當前系統時間,查詢 S3C2440的實時時鐘[5],并轉換為32位無符號整數返回即可。
完成FatFs移植后,上層應用經常訪問的API有:f_mount()注冊或注銷一個工作區域、f_open()打開或創建一個文件、f_close()關閉文件、f_read()讀取數據、f_write()寫數據、f_lseek()移動讀寫指針等。
在μC/OS系統下增加數據存儲任務測試FatFs文件系統能否滿足本次數據采集系統數據保存的需要。其中數據采集部分是采用一個具有SPI接口的TLC2543模數轉換器以200 Hz的采樣頻率采集12位精度的數據。數據存儲任務實現將采集任務發送過來的緩存數據保存到SD卡中,存儲任務[6]設計如圖5所示。
采集并保存半小時的數據到SD卡中,關機后,將SD卡取出插入到計算機中,將文件中的數據繪制曲線,與數據采集輸入的信號吻合,驗證了FAT文件系統能夠正常工作,并且已經滿足當前數據采集系統數據存儲和數據轉移的需求。另外,系統運行過程中,由于軟件實現了無卡檢測功能,支持熱插拔,系統可以長時間工作仍能穩定運行。

圖5 數據存儲任務流程圖Fig.5 Flow chart of data storage task
本設計在硬件上采用S3C2440的SDIO接口實現底層驅動,軟件上采用FatFs實現μC/OS下FAT文件系統的管理,滿足數據存儲和數據移動的需求。其中兼容標準SD卡和SDHC卡的驅動實現方法可以應用到其他具有SDIO接口的硬件平臺,通用性好。另外,FatFs經過了大量用戶的使用和測試,運行穩定可靠,并且其具有較多的上層接口,可以應用于更多復雜文件管理功能的任務。
[1]劉榮林,程曉東.基于ARM和μC/OS的SD卡文件系統設計[J].內蒙古大學學報:自然科學版,2009, 40(3):309-314.
LIU Rong-lin,CHENG Xiao-dong.Design of the SD card file systems based on ARM and μC/OS-Ⅱ [J].Journ al of Inner Mongolia University:Natural Science,2009,40(3):309-314.
[2]師超.SDIO接口的軟硬件實現及性能評估[D].南京:東南大學,2006.
[3]SD Card Association.SD SpecificationsPart1:Physical LayerSimplifiedSpecification Version 2.00[EB/OL].(2006-09-25)[2013-03-10].https://www.sdcard.org/downloads/pls/simplified_specs/archive/part1_200.pdf.
[4]李世奇,董浩斌,李榮生.基于FatFs文件系統的SD卡存儲器設計[J].測控技術,2011(12):79-81.
LI Shi-ji,DONG Hao-bin,LI Rong-sheng.Design of SD memory card based on FatFs file system[J].Measurement&Control Technology,2011(12):79-81.
[5]Samsungsemiconductor.S3C2440A32-BitCMOSMicrocontroller User’s Manual[EB/OL].(2004-06-03)[2013-3-11]http://wenku.baidu.com/view/2adfbaea5ef7ba0d 4a733b54.html.
[6]周慈航.基于嵌入式實時操作系統的程序設計技術[M].2版.北京:北京航空航天大學出版社,2011.