大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是串行NAND Flash的兩大特性導緻其在i.MXRT FlexSPI下無法XiP。
在嵌入式世界裡,當我們提起XiP裝置(支援代碼原地執行的存儲器),首先想到的應該是NOR Flash。比如中低端MCU内部通常會內建小容量并行NOR Flash(一般2MB以内),用于存放應用程式;而高性能MCU,往往内部不會內建Flash,需要在闆級設計時外挂一片稍大容量的NOR Flash(大部分是串行NOR,一般8MB以上)。
恩智浦i.MXRT系列屬于高性能MCU,需要外挂Flash。i.MXRT本身可以支援串/并行NOR、串/并行NAND四類裝置作為啟動裝置,但在官方參考設計闆EVK上,推薦的都是串行NOR Flash型号。官方沒有推薦并行NOR/NAND,這是可以了解的,畢竟相比串行接口Flash,引腳占用略多,這對I/O資源緊張的MCU項目來說不太讨喜。那官方為何不推薦串行NAND作為啟動裝置呢?這主要是串行NAND在i.MXRT下無法XiP,這對項目軟體設計來說有一些限制。NAND無法XiP的原因有兩點,既跟NAND自身特性有關,也跟FlexSPI外設特性有關,且聽痞子衡細說:
我們知道在i.MXRT中是FlexSPI外設負責實作串行NOR/NAND Flash裝置的讀寫通路支援,痞子衡寫過一篇文章 《從頭開始認識i.MXRT啟動頭FDCB裡的lookupTable》,文章詳述了FlexSPI是如何通過lookupTable來支援串行NOR Flash裝置XiP啟動的(這裡主要是讀通路支援)。
在lookupTable設計裡,其實AHB讀通路并不是NOR Flash裝置的專利,或者這麼說,FlexSPI外設本身并不在乎連接配接得是什麼類型的裝置,它就是完全根據使用者在lookupTable裡填入的指令時序按部就班工作而已。
對于四線QSPI NOR,僅需要在lookupTable裡填入一條指令時序(Read有很多種,但都能在一條Sequence裡實作)就可以支援AHB讀。而HyperFlash、HyperRAM和串行NAND等裝置,lookupTable裡一條指令時序搞不定完整讀操作,需要多條指令時序組合完成。
FlexSPI外設支援在lookupTable中聯合多條指令時序去實作AHB讀,通過FlexSPI->FLSHxxCR2寄存器裡的如下兩處功能位來實作。ARDSEQID位指明讀通路時序在lookupTable中的起始位置(index),ARDSEQNUM位指明讀通路時序共占用幾條指令時序(這也意味着幾條指令時序要按序放在一起)。

比如Micron MT29FxG01串行NAND系列,就需要如下三條指令時序(Page Read + Get Feature + Random Data Read)組合完成讀操作。但是理想很豐滿,現實卻骨感,即使組合這三條指令時序也無法在FlexSPI下實作NAND的XiP。
實際應用時,對于NAND的讀通路,都是在程式代碼中先通過IPCMD方式手動發送Page Read和Get Feature指令,然後借助lookupTable中的Random Data Read指令實作僅一個Page空間大小的AHB讀,做不到全部NAND空間的自動AHB讀(當然如果你覺得一個Page空間的AHB讀太雞肋,完全可以直接用IPCMD方式去讀Page資料)。
Note: 關于NAND僅一個Page空間的AHB讀支援再作下詳細解釋。比如NAND的Page大小為2KB,那麼系統裡僅需給NAND配置設定0x60000000 - 0x600007FF的AHB映射空間,每次對這個空間進行AHB讀之前,都需要先通過IPCMD發送Page Read和Get Feature,確定NAND處于Page資料輸出的Ready狀态,底下FlexSPI就可以完成這個Page内的任意AHB讀通路支援。而一旦切到新Page通路,需要重複上述過程,是以NAND所有Page的通路都可以在這個2KB的映射空間裡完成的。
到底串行NAND的什麼特性阻礙了XiP,現在痞子衡來揭秘,在揭秘前大家先看一下痞子衡的舊文 《Raw NAND簡介》,先對NAND型Flash有個初步了解。下面痞子衡以Micron MT29FxG01型号串行NAND為例介紹其阻礙XiP的兩大特性:
凡是NAND型Flash都繞不開壞塊(Bad Block)問題,這也是NAND Flash差別于NOR Flash的一個重要特點。NAND技術上允許壞塊的存在,這降低了NAND生産工藝要求,是以NAND機關容量價格比NOR低。
NAND内部按粒度從大到小劃分依次為Plane、Block、Page、Byte(如下圖所示),因為壞塊導緻了一些Block無法有效存儲資料,這些Block會被标記拉黑,是以從主裝置通路角度來看,NAND中的資料并不是按位址連續存儲的,壞塊占據的位址均為無效位址,這就是所謂的非線性存儲,而非線性儲存設備顯然無法作為XiP裝置。
非線性存儲器,對于寫入操作,無法保證應用程式一定放在指定連結的位址(即在Flash中的對應偏移位址),寫入過程中遇到壞塊,會跳過壞塊,而那些壞塊占據的無效位址極有可能就是應用程式實際連結位址。
我們現在假設一種理想情況,NAND中不存在任何壞塊,可以強行把NAND當作線性儲存設備,這種情況下是不是就可以被用作XiP裝置了呢?很遺憾,FlexSPI外設還是不能正面支援(有替代方法來支援)。
我們來看串行NAND的完整讀時序,0x13(Page Read)是FlexSPI發送的第一個指令,用于通知NAND主裝置想要通路Page了,随後發送列位址,指明要讀的Page位置,此時NAND便會将内部狀态寄存器裡Busy位标志起來并進入忙狀态。
在忙狀态時間裡,NAND會從記憶體塊裡将指定的Page資料全部拷貝到臨時緩存區(Cache memory),對這一整個Page資料進行ECC校驗,校驗完成後将狀态寄存器裡相應ECC标志起來以及将Busy位清除掉,然後結束忙狀态,進入資料輸出準備狀态。
由于不知道NAND什麼時候會結束忙狀态,是以FlexSPI需要不斷發送0x0F(Get Feature指令)去讀取狀态寄存器的值,直到狀态寄存器裡Busy位被清零才能去讀取Page資料,這種邏輯判斷行為在lookupTable裡無法自動實作(NOR讀時序裡無需邏輯判斷)。
如果特意省略讀狀态寄存器的步驟,避免邏輯判斷行為,在lookupTable直接填入Dummy周期來代替行不行呢?理論上倒是可以的。我們來算一下,比如NAND典型的50MHz時鐘頻率,一個Dummy Cycle周期耗時20ns,NAND Page Read等待典型值是45us,即2250個Dummy Cycle,lookupTable有16條Sequence,每個Seqence支援8個instruction,每個instruction如果都設為DUMMY_SDR,參數設最大255,則9個instruction就能滿足這個等待時間。
但即使這麼做能勉強實作NAND Flash的XiP,代碼實際執行效率也是非常低下的,畢竟涉及到跨Page的指令長跳轉(暫不讨論Cache因素)就需要等待45us,這在嵌入式世界裡是不短的時間,系統實時性無法保證,又有什麼意義呢?
至此,串行NAND Flash的兩大特性導緻其在i.MXRT FlexSPI下無法XiP痞子衡便介紹完畢了,掌聲在哪裡~~~
文章會同時釋出到我的 部落格園首頁、CSDN首頁、知乎首頁、微信公衆号 平台上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。
最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。
衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。
專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]
可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。