天天看點

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

我們需要摸清i.MXRT啟動串行NOR Flash裝置到底是怎樣的初始化流程,搞清這個流程,将來定位啟動問題才能遊刃有餘

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程。

  從外部串行NOR Flash啟動問題是i.MXRT系列開發最高頻的話題,無論是開發調試XIP應用程式階段還是最終産品量産階段都繞不開NOR Flash選型以及為它設計一個比對的FDCB配置塊。如果不了解FDCB是什麼,先去看痞子衡之前的文章 《Bootable image格式與加載》。

  實際開發過程中,影響串行NOR Flash正常下載下傳/啟動的因素有很多,痞子衡已經寫過三篇:《16MB以上使用不當因素》、《SFDP因素》、《QE bit因素》,列舉了三個不同因素,當然這都是出了問題,具體調試分析才定位出來的,顯然還有很多未知因素等待陸續被發掘。

  如果總是被動去解決問題,那問題是解不完的。不如我們主動出擊,摸清i.MXRT啟動串行NOR Flash裝置到底是怎樣的初始化流程,搞清這個流程,将來定位啟動問題才能遊刃有餘,話不多說,開始今天的主題。

備注:本文主角是i.MXRT1050,但内容也同樣适用i.MXRT1020/1015,對于i.MXRT1010也算适用但有兩處微小差别(備援App啟動支援,Flash上電等待時間處理)。

  我們知道外部串行NOR Flash是接到i.MXRT的FlexSPI外設引腳上,有時串行NOR Flash啟動也叫FlexSPI NOR啟動。關于FlexSPI NOR啟動流程,i.MXRT1050參考手冊System Boot章節有如下流圖,藍框之外的流程屬于正常i.MXRT啟動XIP App流程,是個通用流程。藍框之内才是具體FlexSPI初始化步驟,這個步驟概括得比較精煉。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  為了讓大家對FlexSPI NOR裝置啟動初始化流程有個更具體的概念,痞子衡重新畫了一張更詳細的流程圖,圖中灰底框裡描述得是FlexSPI初始化流程,痞子衡将其分解成了六步,我們有必要深入這六步初始化流程。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  第一步是嘗試複位Flash晶片,這步是可選的,在fuse_0x6e0[7]裡配置,預設是不使能的。複位Flash目的是為了讓Flash處于一個确定的初始狀态,友善i.MXRT BootROM去配置通路。為什麼要強調Flash的初始狀态,因為很多時候i.MXRT未必是冷啟動(上電啟動),也有可能是軟複位啟動(比如調用NVIC_SystemReset),這時候外部Flash已經被軟複位前執行過的BootROM甚至使用者App配置過,是以Flash的狀态可能不是上電初始狀态(一般來說闆級設計裡Flash的RESET#引腳要麼懸空,要麼連接配接i.MXRT的POR#引腳),這可能會影響軟複位後BootROM去再次配置啟動這塊不定态的Flash。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  正常的Flash都提供了RESET#引腳來實作跟上電複位一樣的功能,對于普通8-pin的QSPI Flash,這個RESET#引腳往往是跟信号線IO3複用的(僅在QE bit沒使能情況下有效),而對于16-pin的QSPI Flash或者HyperFlash,其RESET#引腳都是獨立的。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  BootROM就是借助了Flash的RESET#引腳來實作的複位操作,實作代碼比較簡單,i.MXRT1050 BootROM直接指定了GPIO1[9]當做複位信号線,闆級設計裡需要你将GPIO1[9]連到Flash的RESET#引腳,然後BootROM就是簡單地拉低GPIO1[9]即可。RESET#信号都是低電平有效,BootROM直接拉低這個信号持續250us,這個低電平持續時間對于複位來說是夠夠的,很多Flash資料手冊裡其實僅要求幾us即可。

備注:對于BootROM的Flash複位功能來說,主要适用有獨立RESET#引腳的Flash。

  第二步是準備一個初始的FDCB配置塊(即flexspi_nor_config_t,大小為512位元組),這個初始FDCB配置塊将被用來做FlexSPI外設的第一次初始化,目的是為了能夠保證FlexSPI初始化之後CPU能夠使用AHB方式正常讀取Flash(通路性能不要求最高,但求穩定通路)。這個初始FDCB并不是一個完全定死的配置塊,部分值也是根據fuse來配置的,一共有三處fuse位置,其中最重要的是FLASH_TYPE:

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  初始FDCB配置塊中僅給memConfig設了值,這個memConfig才是用于配置FlexSPI外設本身。如下部分指派是固定的FDCB設定,不受fuse影響,從這個固定配置你可以看到,BootROM假定了所有外接Flash都是128MB,且通路時鐘(SCK)速度能支援30MHz,不要對這個假定感到焦慮,它隻是用于FlexSPI第一次初始化,目的隻求能正常通路Flash前4KB即可:

  然後便是從fuse裡擷取flashType,根據具體flashType來對初始FDCB配置塊做進一步動态指派,這進一步指派才用于區分不同Flash種類(Pad數量、DQS信号屬性、最重要的lookupTable等)。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  上圖中最重要的FDCB指派是config.memConfig.lookupTable,它是FlexSPI外設需要的核心配置,有了這個配置,CPU便可以直接從AHB總線讀取Flash的内容,因為FlexSPI會自動解析AHB總線讀請求然後翻譯成具體FlexSPI讀時序,底層讀時序需要的指令、位址位元組數、DUMMY周期都在lookupTable裡。BootROM預存了如下6大類Flash的lookupTable:

  第三步就是利用上述配置完成的初始FDCB塊對FlexSPI外設進行第一次初始化,就是下面代碼,這個流程跟官方SDK裡的flexspi_nor_flash_init()大同小異,這裡不予具體展開。如果在這裡初始化就傳回失敗(這裡一般不會失敗,因為僅僅是FlexSPI外設自身初始化,并不涉及操作外部Flash晶片的動作),BootROM則直接退出FlexSPI NOR裝置啟動,轉入SDP下載下傳。

  上述第一次FlexSPI初始化一般都會成功的,但這并不代表fuse裡的flashType等配置跟闆子上Flash型号是比對的,也就是說初始FDCB配置塊此時還沒有被充分驗證其是否适用闆載Flash型号。

  FlexSPI第一次初始化結束後,為了保證後續能正常AHB通路,BootROM裡做了一些善後工作,主要是兩件事:

做一些通路前的延時:根絕fuse 0x450[3:2] - HOLD TIME來調用microseconds_delay()做延時,以使FlexSPI外設完全準備好。 做一次無效AHB通路:類似這樣的代碼 volatile uint32_t dummy = *(uint32_t *)0x60000000;,無效AHB讀可以使Flash退出continuous read模式

  善後工作結束之後,此時CPU應該可以通過AHB正常通路Flash了,這個階段我們隻需要從Flash的偏移0位址處讀取使用者FDCB,驗證使用者FDCB是否存在,這裡才是對前面初始FDCB配置塊以及第一次FlexSPI外設初始化的真正考驗。

  驗證使用者FDCB是否存在就是簡單讀取FDCB的前四個位元組(tag),驗證這個tag是否合法。如果第一次驗證tag不成功(有可能是FlexSPI配置不正确,也有可能是使用者FDCB不存在),會嘗試做一次三位元組位址切換到四位元組位址的LUT更新(僅适用QSPI Flash),然後做第二次tag讀取驗證,如果此時還是驗證失敗(大機率是不存在使用者FDCB了),BootROM則直接退出FlexSPI NOR裝置啟動,轉入SDP下載下傳。

  上面代碼裡有flexspi_clear_cache()操作,這個其實就是利用FLEXSPI0->MCR0[SWRESET]做一個外設級别的軟複位,另外代碼裡還涉及到一個四位元組位址QSPI Flash的LUT表,即如下所示:

  到了這裡,基本代表第一次FlexSPI初始化是正确且可用的,并且能夠拿到有效的使用者FDCB配置塊。這時候就是利用使用者FDCB配置塊對FlexSPI外設做第二次初始化,初始化代碼流程跟第一次初始化是一模一樣的。

  這個第二次初始化是非常有必要的,因為它反映了使用者的真實需求,使用者FDCB配置塊裡會準确描述闆載Flash的全面特性(通路速度,真實存儲空間大小,特殊定制LUT等等),這些資訊必須由使用者來提供。

  需要注意的是,第二次FlexSPI初始化傳回成功并不代表使用者FDCB配置塊一定就是正确的,還是那句話,這僅僅是對FlexSPI外設自身的初始化。後續正常App解析流程裡才是對這個使用者FDCB配置塊的真正考驗。

  至此,深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程痞子衡便介紹完畢了,掌聲在哪裡~~~

文章會同時釋出到我的 部落格園首頁、CSDN首頁、知乎首頁、微信公衆号 平台上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程
痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程
痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程

  衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。

  專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/

  與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]

  可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。

  關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。

  痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。