大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是串行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外設特性有關,且聽痞子衡細說:
一、FlexSPI對於NAND的支持
我們知道在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的兩大特性
到底串行NAND的什么特性阻礙了XiP,現在痞子衡來揭秘,在揭秘前大家先看一下痞子衡的舊文 《Raw NAND簡介》,先對NAND型Flash有個初步了解。下面痞子衡以Micron MT29FxG01型號串行NAND為例介紹其阻礙XiP的兩大特性:
2.1 壞塊導致的非線性存儲
凡是NAND型Flash都繞不開壞塊(Bad Block)問題,這也是NAND Flash區別於NOR Flash的一個重要特點。NAND技術上允許壞塊的存在,這降低了NAND生產工藝要求,因此NAND單位容量價格比NOR低。
NAND內部按粒度從大到小划分依次為Plane、Block、Page、Byte(如下圖所示),因為壞塊導致了一些Block無法有效存儲數據,這些Block會被標記拉黑,所以從主設備訪問角度來看,NAND中的數據並不是按地址連續存儲的,壞塊占據的地址均為無效地址,這就是所謂的非線性存儲,而非線性存儲設備顯然無法作為XiP設備。
- 非線性存儲器,對於寫入操作,無法保證應用程序一定放在指定鏈接的地址(即在Flash中的對應偏移地址),寫入過程中遇到壞塊,會跳過壞塊,而那些壞塊占據的無效地址極有可能就是應用程序實際鏈接地址。
2.2 ECC校驗導致的Page Read等待
我們現在假設一種理想情況,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主頁、知乎主頁、微信公眾號 平台上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。