陳維蛇,姜文博,劉 洪
(陜西長(zhǎng)嶺電子科技有限責(zé)任公司,陜西 寶雞 721006)
Zynq-7000 SoC xilinx是新一代FPGA(Artix-7與Kintex-7FPGA)與Cortex-A9 ARM相結(jié)合的一款可擴(kuò)展處理平臺(tái)。它的可編程邏輯部分被稱為PL,采用了28 nm可編程技術(shù),使用戶可以利用它進(jìn)行系統(tǒng)可編程邏輯部分的開發(fā);ARM部分被稱為PS,為Cortex-A9雙精度浮點(diǎn)引擎的雙核ARM,集成了L1和L2緩存、DDR3控制器、以太網(wǎng)、串口和IIC總線等常用外設(shè)。用戶可以利用它進(jìn)行C語(yǔ)言部分開發(fā)。ARM核可以裸機(jī)運(yùn)行,也可以靈活搭載Linux、VxWorks等操作系統(tǒng)。Zynq-7000 SoC的PL與PS部分采用AXI總線系統(tǒng)進(jìn)行通信,xilinx公司提供了APB橋、DMA高速數(shù)據(jù)通道以及GPIO、UART等AXI總線標(biāo)準(zhǔn)外設(shè)通信模塊。用戶可以利用它們方便地搭載自己的可裁剪系統(tǒng)。
在包含Zynq7000的嵌入式系統(tǒng)工作過(guò)程中,有時(shí)需要記錄一些系統(tǒng)工作過(guò)程中的數(shù)據(jù),如AD采集的數(shù)據(jù)、系統(tǒng)工作狀態(tài)等。如果使用標(biāo)準(zhǔn)的數(shù)據(jù)記錄系統(tǒng),則需要額外的硬件軟件開銷,無(wú)形中增加了系統(tǒng)的成本和復(fù)雜性。本文介紹了一種簡(jiǎn)易記錄這些數(shù)據(jù)的方法。
本例硬件采用AX7020和其配套的AD卡,開發(fā)環(huán)境采用VIVADO2015.4,系統(tǒng)結(jié)構(gòu)如圖1所示。
圖1 系統(tǒng)結(jié)構(gòu)
打開開發(fā)環(huán)境,建立Zynq7000工程,然后添加ARM核,在配置界面中添加SD卡和UART1。ARM核的外圍設(shè)備如DMA模塊、APB橋等,這里不再進(jìn)行一一敘述。配置完P(guān)L部分后,編譯導(dǎo)出硬件,打開SDK,新建hello world模板工程。之后,在XILINX TOOLS→BOARD SUPPORT PACKAGE SETTING中設(shè)置選擇xilffs,版本為3.1。各參數(shù)采用默認(rèn)設(shè)置。
xilffs針對(duì)FAT32文件系統(tǒng)。對(duì)一個(gè)機(jī)械硬盤而言,柱面、磁頭和扇區(qū)確定唯一的扇區(qū)物理地址。在數(shù)據(jù)組織上看,總是按照主引導(dǎo)區(qū)→引導(dǎo)扇區(qū)→數(shù)據(jù)→引導(dǎo)扇區(qū)…來(lái)排列。一塊硬盤上,基本分區(qū)的最大數(shù)目為4個(gè),大于4個(gè)的被自動(dòng)分配為擴(kuò)展分區(qū)。SD卡的分區(qū)結(jié)構(gòu)和普通磁盤類似,沿用了普通機(jī)械硬盤的大多數(shù)概念術(shù)語(yǔ)。因?yàn)樗鼰o(wú)需啟動(dòng),所以MBR區(qū)沒(méi)有引導(dǎo)信息。
一個(gè)硬盤中主引導(dǎo)分區(qū)位于硬盤的起始扇區(qū),共512個(gè)字節(jié),包含了446字節(jié)的MBR和64字節(jié)的DPT,并以55 AA作為結(jié)束標(biāo)志。因?yàn)镾D卡不用啟動(dòng),所以MBR區(qū)域不包含引導(dǎo)數(shù)據(jù)。SD卡的MBR為小端模式,低字節(jié)在前,其中包含了2個(gè)重要數(shù)據(jù):偏移地址0x1C6開始的4字節(jié)決定了引導(dǎo)扇區(qū)DBR的位置;偏移地址0x1CA開始的4字節(jié)表示了SD卡的總扇區(qū)數(shù)。
引導(dǎo)扇區(qū)DBR共512個(gè)字節(jié),以55 AA結(jié)束。前11個(gè)字節(jié)為跳轉(zhuǎn)指令和文件系統(tǒng)類型、版本號(hào)信息。偏移地址0x0D標(biāo)記每簇的扇區(qū)數(shù)。文件系統(tǒng)中保存數(shù)據(jù)的最小單位為簇。只要本簇中寫入了當(dāng)前文件的數(shù)據(jù),它就不可以被其他文件使用。此外,偏移地址0xE~0xF標(biāo)記了本分區(qū)的保留扇區(qū)數(shù),偏移地址0x10~0x11標(biāo)記了FAT表的個(gè)數(shù),偏移地址0x24~0x27標(biāo)記了FAT表的大小。
信息分區(qū)FSINFO用以記錄文件系統(tǒng)中未使用的空閑簇的數(shù)量和下一個(gè)可用簇的簇號(hào)等信息,位于1號(hào)邏輯扇區(qū)。
從FAT表開始,是文件系統(tǒng)的核心內(nèi)容。文件占用磁盤的最小單位是簇。即使文件只有一個(gè)字節(jié),它也占用一個(gè)簇的磁盤空間。大文件會(huì)占用多個(gè)簇。
一個(gè)文件的數(shù)據(jù)在磁盤中并不是連續(xù)存儲(chǔ)的。它會(huì)根據(jù)磁盤簇的占用情況被分為很多段。文件系統(tǒng)需要記錄哪些磁盤簇已經(jīng)被占用,同時(shí)需要指明一個(gè)文件中已經(jīng)占用的簇的下一個(gè)簇的簇號(hào)。對(duì)于文件的最后一個(gè)簇,要指明本簇后面再?zèng)]有簇被占用,類似于數(shù)據(jù)結(jié)構(gòu)中的鏈表結(jié)構(gòu),所以被稱為文件的鏈?zhǔn)酱鎯?chǔ)。這些信息由FAT表來(lái)保存,F(xiàn)AT表分為FAT12、FAT16和FAT32。常用的FAT32表按4字節(jié)為一個(gè)表項(xiàng)進(jìn)行分割,從2號(hào)表項(xiàng)開始,每個(gè)表項(xiàng)與磁盤數(shù)據(jù)區(qū)的簇一一對(duì)應(yīng)。3號(hào)簇跟3號(hào)FAT表項(xiàng)映射,4號(hào)簇跟4號(hào)FAT表項(xiàng)映射,以此類推,直到數(shù)據(jù)區(qū)中的最后一個(gè)簇。它的內(nèi)容為空閑標(biāo)志、壞簇標(biāo)志或者一個(gè)文件的下一個(gè)簇號(hào)。
FAT表中每簇的地址固定為32 bit,按四字節(jié)對(duì)其進(jìn)行劃分,并由0開始進(jìn)行編號(hào)。0號(hào)和1號(hào)簇由系統(tǒng)保留作特殊使用,從2號(hào)簇開始,其分別對(duì)應(yīng)文件系統(tǒng)的實(shí)際數(shù)據(jù)區(qū)簇號(hào)。FAT表中的簇地址編號(hào)與數(shù)據(jù)區(qū)的簇號(hào)相同[1]。在創(chuàng)建文件系統(tǒng)(格式化)時(shí),所有的FAT表均被清空。FAT1和FAT2的0號(hào)、1號(hào)表項(xiàng)寫入特定值。2號(hào)表項(xiàng)常為根目錄,因此2號(hào)表被寫入結(jié)束標(biāo)志。
根目錄在文件系統(tǒng)建立時(shí)即已被創(chuàng)建,目的是存儲(chǔ)目錄(也稱文件夾)或文件的目錄項(xiàng)。目錄所在的扇區(qū),都以32 Bytes劃分為一個(gè)單位,每個(gè)單位稱為一個(gè)目錄項(xiàng)(DirectoryEntry),即每個(gè)目錄項(xiàng)的長(zhǎng)度都是32 Bytes。目錄項(xiàng)包含了文件名、文件大小、文件類型、創(chuàng)建時(shí)間和修改時(shí)間等文件信息。
首先,定義2個(gè)數(shù)據(jù)結(jié)構(gòu):
static FATFS fatfs;
FIL fil;
第一步,利用f_mount掛載SD卡,指令為:
rc=f_mount(&fatfs,"0:",0);\掛載SD卡
注意,函數(shù)中的第2個(gè)參數(shù)不能為空,必須要加上盤符,否則后續(xù)操作中將無(wú)法創(chuàng)建文件。
第二步,利用f_open函數(shù)打開或創(chuàng)建一個(gè)文件,指令為:
rc=f_open(&fil,FileName, FA_CREATE_ALWAYS|FA_WRITE);\創(chuàng)建文件
注意,文件名參數(shù)為短文件名,即不大于8個(gè)英文字符,長(zhǎng)文件名系統(tǒng)不支持。
第三步,將文件指針移動(dòng)到文件頭,指令為:
rc=f_lseek(&fil,0);\移動(dòng)文件指針
第四步,寫數(shù)據(jù)到文件中,指令為:
rc=f_write(&fil,(void*)SourceAddress,ByteLength,&bw);\寫數(shù)據(jù)
第五步,將數(shù)據(jù)更新到SD卡,指令為:
rc=f_sync(&fil);//更新數(shù)據(jù)到SD卡
如果系統(tǒng)采用直接斷電的方法關(guān)機(jī),需要用這條指令更新數(shù)據(jù)。這條指令的缺點(diǎn)在于,SD卡的寫入次數(shù)是有限的,如果數(shù)據(jù)更新周期較快,由于每次更新數(shù)據(jù)都要同步更新文件大小,那么在較短時(shí)間內(nèi)就會(huì)損壞目錄扇區(qū)。所以,盡量使用f_close指令關(guān)閉文件。
如果需要從SD卡中讀取一個(gè)文件,那么在第二步打開文件的時(shí)候需要執(zhí)行:
rc=f_open(&fil,FileName,FA_READ);//打開只讀文件
然后,同樣執(zhí)行第三步移動(dòng)文件指針,然后第四步讀取數(shù)據(jù):
rc=f_read(&fil,(void*)DestinationAddress,ByteLen gth,&br);//讀數(shù)據(jù)
一般可以將系統(tǒng)的工作模式、初始化參數(shù)等數(shù)據(jù)存儲(chǔ)到SD卡中,以達(dá)到方便修改系統(tǒng)參數(shù)的目的。
利用Zynq7000和xilffs文件系統(tǒng),可以較為方便地將系統(tǒng)工作過(guò)程中產(chǎn)生的各種數(shù)據(jù)存儲(chǔ)到SD卡中,其連續(xù)存儲(chǔ)速率不低于500 kb/s,也可以從SD卡中讀取系統(tǒng)工作的初始信息,方便配置系統(tǒng)的工作模式和初始化參數(shù)。
[1] 何 賓 .Xilinx All Programmable Zynq-7000 SoC 設(shè) 計(jì)指南[M].北京:清華大學(xué)出版社,2013.