利用基于閃存的MCU實(shí)現用戶(hù)數據存儲

發(fā)布時(shí)間:2010-3-5 15:20    發(fā)布者:李寬
關(guān)鍵詞: MCU , 閃存 , 數據存儲 , 用戶(hù)
采用微控制器的大多數設備還需要某種機制來(lái)存儲在斷電時(shí)仍要被記住的那些設置數據。例如,在更換電池后記不住預設電臺的收音機肯定不會(huì )在市場(chǎng)上取得很大的成功。用戶(hù)希望喜愛(ài)的電臺、預設溫度、參數選擇和其他永久性信息能長(cháng)久保存下來(lái)供每次開(kāi)機時(shí)直接取用。

為了滿(mǎn)足這種用戶(hù)需求,設計師一般使用串行EEPROM。這些器件又小又便宜,具有很長(cháng)的歷史,設計工程師用起來(lái)得心應手。但在今天對成本極其敏感的市場(chǎng)下,即使這樣一個(gè)廉價(jià)的器件也可能突破成本預算。因此許多設計師試圖尋求并利用已經(jīng)包含在微控制器芯片中的資源:程序閃存中剩余的空間。

過(guò)去,許多微控制器使用ROM或可紫外線(xiàn)擦除的EPROM來(lái)存儲程序指令。但現在越來(lái)越多的微控制器轉用閃存技術(shù)存儲代碼。選擇閃存的主要理由是,如果在程序代碼中發(fā)現錯誤,閃存數據很容易被擦除和更新。

大多數微控制器具有讀取程序空間中存儲數據的機制;隈T·諾伊曼架構的處理器,如TI MSP430,可以使用任何尋址模式讀取程序閃存。哈佛架構處理器一般利用特殊的機制將數據從程序空間傳送到數據空間。具有閃存管理功能的其他MCU包括:

1. 包含MOVEC(移動(dòng)常數)指令的非常流行的8051處理器系列;

2. 包含TBLRD和TBLWR(表讀和表寫(xiě))指令的Microchip PIC18系列;

3. 具有偽馮·諾伊曼架構的美信MAXQ微控制器系列,它們允許通過(guò)簡(jiǎn)單的MOVE指令訪(fǎng)問(wèn)閃存程序存儲空間(見(jiàn)圖1)。


圖1:在像美信MAXQ2000這樣的偽馮·諾伊曼MCU中采用的數據交換允許任何存儲器塊被用作代碼或數據存儲器。

但即使能夠從隨機閃存位置讀取數據,完整的非易失性存儲器子系統也必須能夠隨機修改閃存中的數據。這意味著(zhù)需要解決兩個(gè)問(wèn)題:首先,一旦某個(gè)閃存位置被寫(xiě)入,那個(gè)位置的數據只能通過(guò)擦除整個(gè)閃存塊(通常128字節或以上)進(jìn)行修改;其次,閃存的讀寫(xiě)次數非常有限。

本文將介紹如何構建一個(gè)能夠解決這些問(wèn)題、并使用閃存塊模擬隨機寫(xiě)入的機制。雖然本文的用例是MAX2000,但原理適用于支持讀寫(xiě)和擦除閃存的用戶(hù)代碼的任何處理器。本文討論的方案已經(jīng)被用于采用MAXQ3180三相模擬前端和MAXQ2000的三相電表參考設計。

閃存管理的基本知識

閃存是一種電可擦除的存儲器,通常主要用于讀操作,也就是說(shuō),雖然是可寫(xiě)的,但它不希望很頻繁地更新數據,因此對這種存儲器的操作大部分是讀操作。大多數閃存器件是以字(word)為單位寫(xiě)入數據的,但一次只能擦除整個(gè)塊。這使得它們不適用于頻繁變化的存儲應用,只適合存儲那些永遠不變的常數表。

一共有兩種閃存:NAND閃存和NOR閃存。NAND閃存經(jīng)常用于存儲卡和閃盤(pán)。一般來(lái)說(shuō),從NAND器件讀取數據需要幾個(gè)周期,并且大部分是用串行方式完成的。

因此NAND閃存不適于存儲程序代碼,因為存取時(shí)間太長(cháng)。而NOR閃存更像是傳統的字節或字寬的存儲器?梢韵褡xROM器件那樣讀NOR閃存中的數據:使片選和地址線(xiàn)有效,然后等待一段訪(fǎng)問(wèn)時(shí)間后從總線(xiàn)上讀取數據。

閃存塊通常被擦除到“1”狀態(tài),因此經(jīng)過(guò)擦除后,塊中的每個(gè)位置都是0xFFFF!熬幊獭币粋(gè)閃存位置是把某些位從“1”狀態(tài)改變?yōu)椤?”狀態(tài)。為了使編程過(guò)的位返回到“1”狀態(tài),整個(gè)塊必須被擦除。

任何電可擦除的存儲器件都面臨壽命的問(wèn)題。根據所用技術(shù)的不同,一個(gè)閃存單元在永久失效以前可以承受的擦除-編程次數少則1000次,多則100萬(wàn)次。使用閃存存儲數據的任何方案都必須確保寫(xiě)入次數在整個(gè)單元陣列上獲得均勻分布,沒(méi)有一個(gè)位置會(huì )出現太多的擦除和編程次數。

大多數閃存器件都允許將前次編程中那些未被編程的位從“1”改為“0”狀態(tài)。例如,大多數器件允許用0xFFFE編程過(guò)的那個(gè)位置再用0x7FFE進(jìn)行編程,因為這種操作不會(huì )將任何位從“0”改變到“1”。然而如圖1所示的處理器架構中使用的閃存不允許這樣做。這種寫(xiě)入操作的結果是失敗,內存中的數據仍然是0xFFFE。

理由很簡(jiǎn)單:因為要被編程的存儲塊主要用作代碼空間,通常禁止對前面寫(xiě)過(guò)的位置作任何寫(xiě)操作。因為指令0xFFFF代表的是無(wú)效的源子譯碼(source sub-decode),不可能出現在有效的代碼塊中。這樣,阻止向以前編過(guò)程的位置寫(xiě)入數據有助于保持代碼塊的完整性。

提供非易失性存儲器服務(wù)

以下是提供非易失性存儲器服務(wù)的兩種方案。第一種方案側重于簡(jiǎn)單性,第二種方案比較靈活,但代價(jià)是較復雜。

方案1

問(wèn)題:校準信息、MAC地址或制造數據等配置數據必須要存儲在產(chǎn)品中。雖然這些通常是固定不變的信息,但在整個(gè)產(chǎn)品生命周期內配置數據需要多次更新的可能性還是存在的。

解決方案:下面是實(shí)際中最容易想到的例子。有兩個(gè)塊,一個(gè)塊在字地址0x7E00處,另一個(gè)在0x7F00處,都用于數據存儲。在第一次收到保存配置數據的命令時(shí),處理器會(huì )檢查這兩個(gè)塊,在發(fā)現它們都是空塊后,配置數據被就存入第一個(gè)塊。

保存配置數據的第二條命令同樣會(huì )使處理器再一次檢查這兩個(gè)塊。當發(fā)現塊0已經(jīng)有數據后,它就將配置數據拷貝到塊1,然后擦除塊0中的數據。

當收到恢復配置的請求時(shí)(比如在上電時(shí)),處理器會(huì )同時(shí)讀取兩個(gè)塊的數據并確定哪個(gè)塊在用。只要是沒(méi)被擦除的塊就是在用塊。

這種方案的主要優(yōu)點(diǎn)是簡(jiǎn)單:如果設備在上電(或其他配置恢復事件)時(shí)需要塊中的配置數據,這是很好的一種方案。讀數程序會(huì )接受一個(gè)字長(cháng)的指針,返回該地址的數值,寫(xiě)入程序則接受一個(gè)字長(cháng)的指針,然后嘗試向該地址進(jìn)行寫(xiě)入操作。擦除程序只是同時(shí)擦除兩個(gè)塊。

這種方案的主要缺點(diǎn)就是主要優(yōu)點(diǎn)的反面:程序的思路太過(guò)簡(jiǎn)單。沒(méi)有操作去判斷寫(xiě)入數據是否成功—在發(fā)出寫(xiě)入命令后,如果寫(xiě)入失敗,處理器不會(huì )做任何事去解決問(wèn)題。這也是為什么這個(gè)方案只是用來(lái)寫(xiě)入已知是空的閃存塊的原因。

方案2

問(wèn)題:要求用非易失性存儲技術(shù)來(lái)跟蹤用電量和其他經(jīng)常變化的數據。更新經(jīng)常是一周數次或一天數次發(fā)生。

解決方案:這是即使傳統EEPROM也需要尋求幫助的場(chǎng)合。問(wèn)題是:更新的頻率和所有非易失性存儲器有限的寫(xiě)入壽命這樣的事實(shí)不允許反復寫(xiě)入和擦除單個(gè) EEPROM單元?紤]一個(gè)小時(shí)更新一次的情況,具有1萬(wàn)次寫(xiě)入-擦除次數限制的EEPROM只需一年時(shí)間就會(huì )失效,這個(gè)時(shí)間比電表所需的十年設計目標少得太多了。

解決這個(gè)問(wèn)題的方法之一是實(shí)現某種形式的“損耗均衡”。這意味著(zhù)不會(huì )有單個(gè)位置被反復寫(xiě)數據。相反,寫(xiě)入操作將呈類(lèi)似合理指數分布的方式分散到整個(gè)存儲器陣列。

損耗均衡是一種很好理解的技術(shù),在閃存器件中使用就是出于這個(gè)目的。但它的算法非常復雜和難以理解,不過(guò)對我們來(lái)說(shuō),一個(gè)更簡(jiǎn)單的原理介紹就足夠了。

存儲陣列中的數據項是由數據單元(data element)號引用的,而不是地址。

數據單元號是一個(gè)唯一識別數據單元的任意8位數,因此在這種方案中,最多有255個(gè)數據單元(數據單元0是保留單元)。

每個(gè)數據單元有一個(gè)雙字節的頭部(見(jiàn)圖2),包含了數據單元號和數據單元長(cháng)度以及留給差錯管理使用的足夠空間,其中長(cháng)度是一個(gè)兩位代碼,可表示1個(gè)、2個(gè)、3個(gè)或4個(gè)16位的字。


圖2:數據單元的頭部結構。

寫(xiě)一個(gè)數據單元需要知道寫(xiě)入數據的地址、寫(xiě)入數據的單元號和長(cháng)度。寫(xiě)函數先尋找陣列結尾,然后緊跟最后一個(gè)記錄之后寫(xiě)入新的數據單元。

如果閃存頁(yè)中沒(méi)有足夠的空間容納指定長(cháng)度的記錄,一個(gè)表示結尾的頁(yè)標記將被寫(xiě)入,并會(huì )打開(kāi)一個(gè)新的頁(yè)。有關(guān)典型數據頁(yè)的結構請見(jiàn)圖3。


圖3:典型的數據頁(yè)。

在展開(kāi)的數據頁(yè)中,先寫(xiě)入經(jīng)常要更新的數據單元1,再寫(xiě)入從不更新的數據單元4,然后寫(xiě)入需要多次更新的數據單元3。最后,寫(xiě)入從不更新的數據單元2。

出現頁(yè)的結尾標記表明過(guò)進(jìn)行過(guò)一次數據寫(xiě)入嘗試,但由于數據單元太長(cháng)而無(wú)法將數據單元裝進(jìn)該頁(yè),因此打開(kāi)了一個(gè)新頁(yè)來(lái)容納該數據單元。整個(gè)數據結構的結尾設定為空白單元,這個(gè)位置有望成為單元頭部。

值得注意的是,我還沒(méi)有說(shuō)明重復記錄的問(wèn)題。這是因為在這種方案中重復記錄不是問(wèn)題。事實(shí)上,讀寫(xiě)程序是完全忽略重復記錄的。

在寫(xiě)數據時(shí),新的記錄會(huì )寫(xiě)在陣列的最后,而不管是否有相同號碼的記錄存在。在讀數據時(shí),只有匹配請求記錄號的最后,也就是最近的記錄被讀出來(lái)。

從陣列中讀出一個(gè)數據單元要比寫(xiě)入稍微復雜一些。讀函數首先接受應被寫(xiě)入數據單元內容的單元號碼和地址。當被調用時(shí),讀函數從頭開(kāi)始搜索陣列。

當它找到與請求數據單元相匹配的記錄時(shí),它將對應的地址先存起來(lái),然后繼續搜索。如果它找到另外一條匹配的記錄,它就用新的地址代替剛才存儲的地址。

當到達陣列結尾時(shí),最終存儲的地址將指向最近寫(xiě)入拷貝的請求記錄。讀函數隨即在被調用時(shí)將這個(gè)數據拷貝到緩存。

復用存儲器空間

現在,我們已經(jīng)有了一種以讀取為主的可行機制用于從存儲陣列中存取記錄。剩下只有一個(gè)問(wèn)題:我們還沒(méi)有建立起復用被廢棄的記錄拷貝占用的空間。(我們也還沒(méi)有建立刪除記錄的機制,但由于是用在嵌入式應用中,這可能不是一個(gè)很重要的特性)

如果不恢復空間,分配的空間將很快用完;謴涂臻g意味著(zhù)擦除整個(gè)頁(yè),因為閃存只能一次擦除一整頁(yè)。但閃存頁(yè)被隨意擦除時(shí)將會(huì )出現刪除有用信息的風(fēng)險。唯一的方法是在擦除舊頁(yè)時(shí)將有效信息拷貝到新的頁(yè)。

從廢棄記錄恢復空間要分三步走:首先,打開(kāi)新的閃存頁(yè),將每個(gè)數據單元的最新版拷貝到新的頁(yè);然后,刪除舊頁(yè);最后,在新頁(yè)上放置頁(yè)標記以便讀程序能找到它們。

第一步有些技巧,因此我們稍詳細地進(jìn)行介紹。執行這一步的簡(jiǎn)單方法是將它分成兩小步:第一步,使用RAM陣列存儲記錄號和陣列中最新記錄的地址;第二步,穿過(guò)RAM陣列將最新的記錄拷貝到新的閃存頁(yè)。這個(gè)過(guò)程很快,相對也比較順利。

這種方案的問(wèn)題是所用處理器(見(jiàn)圖1)的RAM為1K字。這種方案將限制可存儲進(jìn) RAM中的單一數據數量,因為這個(gè)RAM還要節省下來(lái)用作緩存。這是明顯不能接受的。

這種解決方案非常耗時(shí),但不管存儲陣列多大(在合理范圍內)都能正常工作。該方案不會(huì )在RAM中創(chuàng )建一份指針列表,而是針對每個(gè)單一條目(entry)在源陣列中作多次穿越。因此壓縮算法變?yōu)椋?br />
1. 從源陣列中讀一個(gè)單元;

2. 在目標陣列中尋找該單元。如果找到了,表示這個(gè)單元已經(jīng)被寫(xiě)入。增加源指針值,回到第(1)步;

3. 掃描源陣列尋找單元的最新拷貝;

4. 將數據單元的最新拷貝寫(xiě)入目標陣列;

5. 增加源指針,并回到第(1)步。

最終,在目標陣列中每個(gè)數據單元都有一個(gè)唯一的條目。圖4描述了一個(gè)已填滿(mǎn)的頁(yè)。源頁(yè)現在可以被安全地刪除,頁(yè)的頭部被寫(xiě)入到目標陣列。


圖4:在空間恢復之后的圖2所示數據頁(yè)內容

這個(gè)過(guò)程的構建使得存儲的數據非常安全。在使用閃存器件時(shí)必須面對的危險是寫(xiě)入或擦除操作期間發(fā)生電源故障。

如果發(fā)生電源故障,則有可能一個(gè)或多個(gè)頁(yè)被破壞(在寫(xiě)入時(shí)),或未被完全刪除(在刪除操作時(shí))。但上述壓縮操作本身是安全的。因為:

1. 如果在寫(xiě)入操作期間發(fā)生電源故障,源頁(yè)是完全不受影響的。在電源恢復后,新寫(xiě)的頁(yè)很容易被識別(它們沒(méi)有頁(yè)頭),將其擦除后重新開(kāi)始寫(xiě)入操作。

2. 如果在舊頁(yè)被擦除期間發(fā)生電源故障,它們可能包含無(wú)效的頭部。這些頁(yè)可以被刪除,然后將頭部增加到新的頁(yè)中。

3. 如果在頁(yè)頭部被寫(xiě)入新頁(yè)時(shí)發(fā)生電源故障,數據是不受影響的。頁(yè)頭部的更新操作可以重新開(kāi)始。

總之,應該沒(méi)有什么情況能讓意外事件造成無(wú)可挽救地破壞陣列數據。

性能增強

目前的存儲子系統沒(méi)有差錯檢測機制。在數據單元識別符中目前有6個(gè)比特是保留未用的。

設計師可以使用CRC6算法(x6+x+1)計算整個(gè)數據單元的CRC以確保不會(huì )產(chǎn)生任何讀或寫(xiě)錯誤。雖然這不是一個(gè)特別可靠的算法(它會(huì )從64個(gè)多位差錯中漏掉一個(gè)),但它能檢測實(shí)際中可能發(fā)生的大多數差錯。

上述系統的另外一個(gè)限制是讀取訪(fǎng)問(wèn)時(shí)間必需很長(cháng)。為了尋找最新的記錄,每一次讀取都必須讀遍陣列中的每個(gè)記錄。有三種方法可以用來(lái)改善訪(fǎng)問(wèn)時(shí)間:

1. 在數據單元中留一個(gè)空的字用于前向指針。當數值更新時(shí),在前向指針中填入指向新條目的內容。這樣這個(gè)表可以當作一個(gè)鏈接列表。

2. 向后穿越表格,F在你可以簡(jiǎn)單停留在第一次出現的請求單元上。

3. 如果只有少量的單一單元,可以在上電時(shí)就創(chuàng )建一個(gè)包含單元ID和指針的RAM陣列。隨后的訪(fǎng)問(wèn)將非常迅速—只要讀取RAM陣列就可以發(fā)現到哪里去獲得數據單元。

作者:Maxim公司工程經(jīng)理 Ben Smith 來(lái)源:電子工程專(zhuān)輯 2008-6
本文地址:http://selenalain.com/thread-8930-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页