易恒 武柯安
摘? 要:NOR Flash用于存儲運(yùn)行程序和應(yīng)用數(shù)據(jù),在嵌入式系統(tǒng)中應(yīng)用廣泛。針對NOR Flash的文件系統(tǒng)較為臃腫,在內(nèi)存較小的嵌入式系統(tǒng)中無法正常工作,導(dǎo)致NOR Flash的讀寫方式為直接地址訪問,人為地分配地址空間,管理數(shù)據(jù)不方便且容易出錯(cuò)。為解決這一問題,設(shè)計(jì)了一套針對NOR Flash的低內(nèi)存占有率的存儲訪問分區(qū)管理方法,滿足嵌入式系統(tǒng)中原始數(shù)據(jù)、靜態(tài)數(shù)據(jù)和動(dòng)態(tài)數(shù)據(jù)的管理要求。
關(guān)鍵詞:NOR Flash;分區(qū)管理;文件系統(tǒng);單片機(jī)
中圖分類號:TP333? 文獻(xiàn)標(biāo)識碼:A? 文章編號:2096-4706(2023)23-0079-04
Implementation of Low Cost Partition Management Based on NOR Flash
YI Heng, WU Kean
(No.30 Institute of CETC, Chengdu? 610041, China)
Abstract: NOR Flash is used to store running programs and application data, and is widely used in embedded systems. The file system for NOR Flash is relatively bulky and cannot function properly in embedded systems with small memory. It causes that the reading and writing method of NOR Flash is direct address access, address space is artificially allocated, and data management is inconvenient and prone to errors. To solve this problem, this paper designs a set of storage access partition management method with low memory usage for NOR Flash, which meets the management requirements of raw data, static data and dynamic data in embedded systems.
Keywords: NOR Flash; partition management; file system; Single-Chip Microcomputer
0? 引? 言
NOR Flash是一種非易失閃存技術(shù),是Intel在1988年創(chuàng)建。它是市場上兩種主要的非易失閃存技術(shù)之一。主要特點(diǎn)是芯片內(nèi)執(zhí)行(eXecute In Place, XIP),這樣應(yīng)用程序可以直接在NOR Flash閃存內(nèi)運(yùn)行,不必再把代碼讀到系統(tǒng)ram中。NOR Flash的傳輸效率很高,在1~4 MB的小容量時(shí)具有很高的成本效益。根據(jù)NOR Flash中常存放的數(shù)據(jù)類型,提煉出三種類型的數(shù)據(jù),同種類型的數(shù)據(jù)存放在一個(gè)區(qū)域,每個(gè)區(qū)域使用一種管理方法。
1? 系統(tǒng)設(shè)計(jì)
嵌入式系統(tǒng)的NOR Flash驅(qū)動(dòng)支持讀寫和擦除。將NOR Flash分為三個(gè)管理區(qū),分別為原始數(shù)據(jù)管理區(qū)、靜態(tài)數(shù)據(jù)管理區(qū)和動(dòng)態(tài)數(shù)據(jù)管理區(qū),每個(gè)管理區(qū)擁有自有的初始化、打開、讀、寫、擦除操作,且每個(gè)管理區(qū)均按最小擦除塊對齊,相同大小擦除塊的區(qū)域需劃分到一個(gè)管理區(qū)。每個(gè)管理區(qū)均含地址邊界管理,防止數(shù)據(jù)越界,確保讀寫數(shù)據(jù)的安全可靠。管理區(qū)示意圖如圖1所示。
每個(gè)管理區(qū)如圖2所示,起始頁地址和結(jié)束頁地址,均需要整除最小擦除塊,即n =頁起始地址/最小擦除塊大小,k =頁結(jié)束地址/最小擦除塊大小n,k = {0,1,2,3,…}。
管理區(qū)頭信息定義如表1所示。
1.1? 原始數(shù)據(jù)管理區(qū)
針對NOR Flash中存放原始數(shù)據(jù)的需求,該管理區(qū)的存儲區(qū)域全部用于存放數(shù)據(jù)。管理區(qū)頭信息中序號4和序號5中指定的區(qū)域即為該區(qū)可使用的存儲空間大小。邏輯區(qū)參數(shù)數(shù)據(jù)定義如表2所示。該管理區(qū)占用的管理內(nèi)存開銷如表2所示。
表2中序號1~3,根據(jù)表1中序號4和5指定的地址,在讀寫擦除操作時(shí)進(jìn)行邊界控制,表2中序號3根據(jù)表1中序號3指定大小,進(jìn)行擦除操作。
一次完整的原始數(shù)據(jù)管理區(qū)讀寫流程如圖3所示。
(a)讀流程
(b)寫流程
1.2? 靜態(tài)數(shù)據(jù)管理區(qū)
針對NOR Flash中存放已知大小數(shù)據(jù),且該區(qū)域數(shù)據(jù)不能再被保存到其他存儲區(qū)域,擦除時(shí)整塊擦除。最小管理單元為靜態(tài)節(jié)點(diǎn),在使用前先分配NOR Flash空間,且分配空間需要按擦除塊對齊,后期對同一靜態(tài)節(jié)點(diǎn)的讀寫擦除都需要在分配的空間內(nèi)進(jìn)行,每一個(gè)靜態(tài)節(jié)點(diǎn)的字符串描述通過crc16計(jì)算后的結(jié)果保存在節(jié)點(diǎn)校驗(yàn)碼位置,在檢索同一靜態(tài)節(jié)點(diǎn)時(shí)通過crc16結(jié)果碼進(jìn)行快速查找。初始化靜態(tài)數(shù)據(jù)管理區(qū)時(shí),動(dòng)態(tài)計(jì)算出該區(qū)最大的靜態(tài)節(jié)點(diǎn)個(gè)數(shù)及需要使用多少個(gè)擦除頁來存放和備份靜態(tài)節(jié)點(diǎn)信息。邏輯區(qū)參數(shù)數(shù)據(jù)定義如表3所示。該管理區(qū)占用的管理內(nèi)存開銷為表3所示內(nèi)容加上靜態(tài)節(jié)點(diǎn)個(gè)數(shù)乘表4所示內(nèi)容。
計(jì)算單個(gè)擦除塊可以存放的靜態(tài)節(jié)點(diǎn)個(gè)數(shù)k,k = 擦除塊大小/靜態(tài)節(jié)點(diǎn)描述信息大小,k為向下取整后的值,得出一個(gè)擦除塊可以存放的靜態(tài)節(jié)點(diǎn)個(gè)數(shù)。
靜態(tài)數(shù)據(jù)管理區(qū)需要使用的靜態(tài)節(jié)點(diǎn)描述個(gè)數(shù)j,j =(邏輯頁結(jié)束地址-邏輯頁開始地址)/擦除頁大小,其中j必然是正整數(shù)。
計(jì)算最多需要的靜態(tài)管理節(jié)點(diǎn)個(gè)數(shù)占用的擦除塊個(gè)數(shù)m,當(dāng)k≥j - 1,m = 1;當(dāng)k<j - 1,m>j / (K + 1),m向上取整。實(shí)際應(yīng)用中,需要用的擦除塊個(gè)數(shù)為2×m。靜態(tài)節(jié)點(diǎn)和可使用最小擦除塊在靜態(tài)管理區(qū)中的分布如圖4所示。
其中,j1 + j2 + j3 + … + jn = j。
當(dāng)k≥j - 1,m = j1,2m = j1 + j2,可用于存儲數(shù)據(jù)的最小擦除塊個(gè)數(shù)為j - 2。
當(dāng)k<j - 1,m≥j1 + j2,可用于存儲數(shù)據(jù)的最小擦除塊個(gè)數(shù)為j - 2m。
靜態(tài)節(jié)點(diǎn)初始化,靜態(tài)節(jié)點(diǎn)在m區(qū)為順序排列,首先掃描擦除區(qū)m和m + 1,根據(jù)表4所示內(nèi)容,找到節(jié)點(diǎn)起始地址位于表1中序號4和序號5指定的地址區(qū)間,并做統(tǒng)計(jì),比較m和m + 1中的統(tǒng)計(jì)結(jié)果,當(dāng)且僅當(dāng)m和m + 1中的統(tǒng)計(jì)結(jié)果都不為0時(shí),表示有異常斷電發(fā)生,使用統(tǒng)計(jì)結(jié)果計(jì)數(shù)大的為當(dāng)前靜態(tài)節(jié)點(diǎn)區(qū),并擦除另一區(qū)。當(dāng)兩個(gè)區(qū)統(tǒng)計(jì)結(jié)果都為0時(shí),表示該靜態(tài)管理區(qū)第一次使用,選擇m作為當(dāng)前靜態(tài)節(jié)點(diǎn)區(qū),當(dāng)一個(gè)區(qū)為0,另一區(qū)不為0時(shí),選擇不為0的區(qū)作為當(dāng)前節(jié)點(diǎn)靜態(tài)節(jié)點(diǎn)區(qū)。然后,掃描當(dāng)前靜態(tài)節(jié)點(diǎn)區(qū),根據(jù)表4中描述,節(jié)點(diǎn)回收為0x55的節(jié)點(diǎn)放到刪除節(jié)點(diǎn)鏈表,節(jié)點(diǎn)回收為0xff且節(jié)點(diǎn)初始化為0xaa的放到使用節(jié)點(diǎn)鏈表,并記錄最大的靜態(tài)節(jié)點(diǎn)的結(jié)束地址,最后,計(jì)算可以分配的最小擦除塊個(gè)數(shù)。
靜態(tài)節(jié)點(diǎn)打開,在靜態(tài)節(jié)點(diǎn)初始化完成后,根據(jù)靜態(tài)節(jié)點(diǎn)的名稱,計(jì)算crc16值,遍歷使用節(jié)點(diǎn)鏈表,成功,則返回節(jié)點(diǎn)信息,沒有匹配到,則判斷該節(jié)點(diǎn)所分配的最小擦除塊個(gè)數(shù)能否滿足,如果滿足,則創(chuàng)建該節(jié)點(diǎn)信息,追加到靜態(tài)節(jié)點(diǎn)區(qū)中,并將該節(jié)點(diǎn)插入使用節(jié)點(diǎn)鏈表尾部,否則,遍歷刪除節(jié)點(diǎn)鏈表,選擇條件滿足的擦除次數(shù)最少的靜態(tài)節(jié)點(diǎn),將其從刪除鏈表中取出,更新節(jié)點(diǎn)校驗(yàn)碼,設(shè)置節(jié)點(diǎn)回收為0xff,設(shè)置節(jié)點(diǎn)初始化為0xaa,將該靜態(tài)節(jié)點(diǎn)插入到使用節(jié)點(diǎn)鏈表,將使用節(jié)點(diǎn)鏈表和刪除節(jié)點(diǎn)鏈表上的靜態(tài)節(jié)點(diǎn)寫入另一個(gè)m區(qū),寫入完成后,擦除當(dāng)前m區(qū),設(shè)置更新后的m區(qū)為當(dāng)前靜態(tài)節(jié)點(diǎn)區(qū),記錄最大的靜態(tài)節(jié)點(diǎn)結(jié)束地址;找不到匹配的管理節(jié)點(diǎn),打開失敗。靜態(tài)節(jié)點(diǎn)和最小可擦除頁的映射關(guān)系如圖5所示。
在靜態(tài)節(jié)點(diǎn)打開成功以后,方可進(jìn)行靜態(tài)節(jié)點(diǎn)讀/寫/擦除/刪除操作。
靜態(tài)節(jié)點(diǎn)讀取/寫入:靜態(tài)數(shù)管理區(qū)讀操作方法/寫操作方法根據(jù)靜態(tài)節(jié)點(diǎn)中的節(jié)點(diǎn)起始地址和節(jié)點(diǎn)結(jié)束地址,任意讀取/寫入該區(qū)域的內(nèi)容。
靜態(tài)節(jié)點(diǎn)擦除:靜態(tài)數(shù)據(jù)管理區(qū)擦除操作方法根據(jù)靜態(tài)節(jié)點(diǎn)中節(jié)點(diǎn)起始地址和節(jié)點(diǎn)結(jié)束地址,進(jìn)行整塊擦除,并更新RAM中該靜態(tài)節(jié)點(diǎn)信息中的擦除次數(shù)。
靜態(tài)節(jié)點(diǎn)刪除:先使用靜態(tài)管理區(qū)擦除方法,將該區(qū)域數(shù)據(jù)擦除,然后將節(jié)點(diǎn)回收寫為0x55,最后,將該節(jié)點(diǎn)從使用節(jié)點(diǎn)鏈表刪除,并加入刪除節(jié)點(diǎn)鏈表。
1.3? 動(dòng)態(tài)數(shù)據(jù)管理區(qū)
針對NOR Flash中存放未知大小且支持讀寫、更新和擦除的數(shù)據(jù)。最小管理單元為動(dòng)態(tài)節(jié)點(diǎn),大小為4 096字節(jié),包含動(dòng)態(tài)節(jié)點(diǎn)信息和可寫入數(shù)據(jù)區(qū)。根據(jù)系統(tǒng)自身內(nèi)存容量,可以設(shè)置動(dòng)態(tài)節(jié)點(diǎn)為4 096字節(jié)的整數(shù)倍,典型值為8 192字節(jié)。每一個(gè)動(dòng)態(tài)節(jié)點(diǎn)的字符串描述通過crc16計(jì)算后,將結(jié)果保存于表6中的節(jié)點(diǎn)校驗(yàn)碼字段。在檢索同一動(dòng)態(tài)節(jié)點(diǎn)時(shí)通過crc16結(jié)果碼進(jìn)行快速查找。設(shè)置節(jié)點(diǎn)回收閾值,即最小擦除塊回收節(jié)點(diǎn)占整個(gè)擦除塊的比例,典型為70%。節(jié)點(diǎn)回收緩存區(qū)位于整個(gè)動(dòng)態(tài)管理區(qū)的最后位置,典型為4個(gè)最小擦除區(qū),根據(jù)自身NOR Flash大小,調(diào)節(jié)回收緩存區(qū)大小,因此,動(dòng)態(tài)數(shù)據(jù)管理區(qū)在分區(qū)時(shí),至少要大于節(jié)點(diǎn)緩存區(qū)。邏輯區(qū)參數(shù)數(shù)據(jù)如表5所示。該管理區(qū)占用的管理內(nèi)存開銷為表5所示加上最小管理區(qū)大小,典型為8 192字節(jié)。
動(dòng)態(tài)節(jié)點(diǎn)初始化:回收緩存區(qū)只有在異常斷電的時(shí)候,才會有數(shù)據(jù)。首先掃描回收緩存區(qū),統(tǒng)計(jì)上面的使用動(dòng)態(tài)節(jié)點(diǎn)個(gè)數(shù),如果大于零,則根據(jù)動(dòng)態(tài)節(jié)點(diǎn)信息中的節(jié)點(diǎn)起始地址,找到原始可擦除塊并進(jìn)行掃描,如果原始可擦除塊上數(shù)據(jù)不全是0xff,則統(tǒng)計(jì)其使用動(dòng)態(tài)節(jié)點(diǎn)個(gè)數(shù),與回收緩存區(qū)中的統(tǒng)計(jì)結(jié)果做比較,如果大于回收緩存區(qū)中的結(jié)果,則擦除對應(yīng)回收緩存區(qū),選擇另一個(gè)回收緩存區(qū)備份,然后擦除該塊,如果小于等于回收緩存區(qū)中的結(jié)果,則擦除該塊,將回收緩存區(qū)中的非回收動(dòng)態(tài)節(jié)點(diǎn)回寫到原位置,完成后擦除該回收緩存區(qū)。然后,掃描動(dòng)態(tài)管理區(qū)有效數(shù)據(jù)區(qū)域,以動(dòng)態(tài)節(jié)點(diǎn)大小為步長,將動(dòng)態(tài)節(jié)點(diǎn)地址為0xffffffff的節(jié)點(diǎn)設(shè)置為其現(xiàn)在的地址,不合法的動(dòng)態(tài)節(jié)點(diǎn)地址或者節(jié)點(diǎn)校驗(yàn)碼為非0xffff且節(jié)點(diǎn)屬性為非法的,將其及其子節(jié)點(diǎn)設(shè)置為回收。
動(dòng)態(tài)節(jié)點(diǎn)打開:在動(dòng)態(tài)節(jié)點(diǎn)初始化完成后,根據(jù)動(dòng)態(tài)節(jié)點(diǎn)名稱,計(jì)算節(jié)點(diǎn)名稱crc16值,掃描動(dòng)態(tài)管理區(qū)內(nèi)的所有動(dòng)態(tài)節(jié)點(diǎn),找到節(jié)點(diǎn)校驗(yàn)碼匹配的節(jié)點(diǎn),且節(jié)點(diǎn)屬性為0xee且節(jié)點(diǎn)回收為0xff,記錄該節(jié)點(diǎn)信息。如果沒有找到,則隨機(jī)查找一個(gè)初始化的空閑動(dòng)態(tài)節(jié)點(diǎn)信息,設(shè)置節(jié)點(diǎn)校驗(yàn)碼,將節(jié)點(diǎn)屬性設(shè)置為0xee,記錄該節(jié)點(diǎn)信息。
動(dòng)態(tài)節(jié)點(diǎn)讀?。焊鶕?jù)打開的動(dòng)態(tài)節(jié)點(diǎn)信息,讀取動(dòng)態(tài)節(jié)點(diǎn)鏈上的數(shù)據(jù)。
動(dòng)態(tài)節(jié)點(diǎn)寫入:如果動(dòng)態(tài)節(jié)點(diǎn)是全新節(jié)點(diǎn),寫入數(shù)據(jù)在動(dòng)態(tài)管理節(jié)點(diǎn)大小以內(nèi),直接寫入數(shù)據(jù),如果數(shù)據(jù)大于動(dòng)態(tài)管理節(jié)點(diǎn)大小,則寫滿一個(gè)動(dòng)態(tài)管理節(jié)點(diǎn)后,隨機(jī)分配一個(gè)未使用的動(dòng)態(tài)管理節(jié)點(diǎn),將該動(dòng)態(tài)管理節(jié)點(diǎn)的子節(jié)點(diǎn)地址設(shè)置為新分配的動(dòng)態(tài)管理節(jié)點(diǎn)的子節(jié)點(diǎn)起始地址,并將該節(jié)點(diǎn)crc16的值寫入子節(jié)點(diǎn)中的節(jié)點(diǎn)校驗(yàn)碼,設(shè)置子節(jié)點(diǎn)屬性為0x77,將待寫入數(shù)據(jù)寫入子節(jié)點(diǎn),同理,子節(jié)點(diǎn)寫完還不夠,則繼續(xù)分配子節(jié)點(diǎn),子節(jié)點(diǎn)分配失敗,則啟動(dòng)動(dòng)態(tài)節(jié)點(diǎn)回收,回收完成后,再進(jìn)行子節(jié)點(diǎn)分配,仍然不成功,則寫入失?。蝗绻麆?dòng)態(tài)管理節(jié)點(diǎn)是已經(jīng)有數(shù)據(jù)的,根據(jù)寫入數(shù)據(jù),找到需要寫入的管理節(jié)點(diǎn)區(qū)域,如果該區(qū)域的數(shù)據(jù)區(qū)為全0xff,則直接寫入數(shù)據(jù),否則,將該區(qū)備份到回收緩存區(qū)中,將需要寫的動(dòng)態(tài)節(jié)點(diǎn)整個(gè)區(qū)更新到內(nèi)存,然后擦除原可擦除區(qū),將備份的數(shù)據(jù)除了需要更新的都回寫到原區(qū)域。最后,將更新到內(nèi)存中的數(shù)據(jù)塊寫入原區(qū)域。
動(dòng)態(tài)節(jié)點(diǎn)刪除:將打開的動(dòng)態(tài)節(jié)點(diǎn)及其子節(jié)點(diǎn)中的節(jié)點(diǎn)回收設(shè)置為0x55。
2? 結(jié)? 論
常用的文件系統(tǒng)臃腫,在嵌入式系統(tǒng)中有些無法工作,且功能強(qiáng)大,其中很多功能在應(yīng)用中用不到。相對于復(fù)雜的文件系統(tǒng),本文提出的方法,適用于低內(nèi)存的嵌入式系統(tǒng)中,為NOR Flash訪問隱藏地址信息,讓操作更容易,其中三個(gè)不同的管理區(qū),適用于不同的使用場景,為此類系統(tǒng)提供一種讀寫訪問NOR Flash的方法。
參考文獻(xiàn):
[1] 朱海東,王新社.基于扇區(qū)映射的NOR flash磁盤模擬方法 [J].計(jì)算機(jī)工程與設(shè)計(jì),2007(24):5899-5902.
[2] 陳桂生,李志剛.嵌入式Flash文件系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn) [J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2010,19(5):36-40+62.
[3] 杜偉慶,蘇凱雄.嵌入式系統(tǒng)中NOR Flash的分塊管理與實(shí)現(xiàn) [J].計(jì)算機(jī)與數(shù)字工程,2009,37(12):80-82.
[4] 馬資道,魏貴鵬,謝演.一種基于FLASH的智能卡文件系統(tǒng)的實(shí)現(xiàn)方法 [J].通信技術(shù),2019,52(4):1020-1024.
[5] 張明磊,尚利宏.幾種源碼開放的嵌入式文件系統(tǒng)分析與比較 [J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2007(11):15-18.
作者簡介:易恒(1990—),男,漢族,四川蒲江人,工程師,本科,研究方向:嵌入式系統(tǒng)應(yīng)用。