天天看點

痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP

痞子衡的技術交流群裡經常有群友提問: i.MXRT中的FlexSPI驅動API到底怎麼用啊?這個問題已經出現過好幾次了,本來痞子衡不打算專門為這個寫文章的,因為這部分内容在晶片手冊System Boot章節裡的最後一節ROM APIs裡其實介紹得非常詳細了,但是既然還是有不少朋友在問這個,看起來手冊裡的内容藏得有點深,這麼好的東西被埋沒太可惜了,那麼今天痞子衡就跟大家再認真聊一聊。

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT系列ROM中的FlexSPI驅動API實作IAP。

  痞子衡的技術交流群裡經常有群友提問: i.MXRT中的FlexSPI驅動API到底怎麼用啊?這個問題已經出現過好幾次了,本來痞子衡不打算專門為這個寫文章的,因為這部分内容在晶片手冊System Boot章節裡的最後一節ROM APIs裡其實介紹得非常詳細了,但是既然還是有不少朋友在問這個,看起來手冊裡的内容藏得有點深,這麼好的東西被埋沒太可惜了,那麼今天痞子衡就跟大家再認真聊一聊。

  i.MXRT系列都是Flashless(沒有内置NVM)的晶片,是以BootROM必不可少。BootROM是個很特殊的東西,本質上它是一個完整的C代碼寫成的系統級App,這個系統級App專門用于從外部存儲器中加載使用者級App執行。簡單地說,BootROM就是PC機裡的BIOS。

  BootROM代碼是存放在專門的ROM區域的(前面講i.MXRT系列沒有内置NVM,其實不夠準确,其實是有内部ROM空間的,隻不過這個ROM區域使用者無法下載下傳程式使用,是以等效于沒有NVM),ROM顧名思義Readonly,是以BootROM代碼隻能随着晶片一起Tapeout,代碼無法更改(其實也有ROM patch機制,以後再介紹)。

  ROM空間其實挺大的,從64KB到512KB不等,因晶片啟動功能複雜程度而異。下圖是i.MXRT1050系列的BootROM所占空間,ROM起始位址是0x200000(起始位址在i.MXRT上都一樣),ROM大小為96KB(這是标準啟動功能所要的代碼長度。在i.MXRT1010上是64KB - 精簡啟動功能,在i.MXRT1170上是256KB - 複雜啟動功能)。

痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP

  BootROM代碼其實并沒有占滿全部ROM空間,總有些剩餘空間(因為工藝原因,ROM空間都是8/16KB倍數),這部分空間浪費了着實可惜。如果我們能把SDK裡的一些常用子產品驅動(比如WDOG)順便放進去供使用者調用,既充分利用ROM空間,也為使用者節省Flash空間,豈不是一舉兩得。此外,BootROM功能代碼中也有一些現成子產品驅動(比如各種啟動裝置存儲器驅動接口)可以一并導出,這便是API由來。

  有了API想法,現在就是設計實作了。其實i.MXRT ROM API設計并不是重頭開始的,在這個MCU系列被主推之前,Kinetis系列也曾當紅過,Kinetis中也内置了ROM,并且提供了ROM API,痞子衡之前為此寫過一篇文章 《飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)》。 i.MXRT ROM API設計思路完全複用了Kinetis ROM API的設計。

  API說到底就是一個個功能函數的結合,我們知道工程代碼都是由連結器自動配置設定的,是以每個函數實際連結位址是無法預期的(在連結檔案裡給每個函數配置設定固定位址連結這種方法不在考慮範疇,當函數數量衆多時,這種方法太麻煩),業界上一個比較通用的做法是定義成員是函數指針的結構體,i.MXRT ROM API就是采用的業界通用方式,下面bootloader_api_entry_t便是i.MXRT1060中API原型,g_bootloaderTree就是執行個體:

  從上面代碼我們可以看出,bootloader_api_entry_t成員好像并不是函數指針,是的,為了分組友善,bootloader_api_entry_t成員還是一個個結構體,它的這些結構體成員(比如flexspi_nor_driver_interface_t)才是真正包含一個個函數指針的結構體。API從功能來分一共提供了7類:HAB、FlexSPI NOR、NAND ECC、Clock、RT-WDOG、WDOG、stdlib。

  設計到這裡,我們通過g_bootloaderTree結構體常量就可以調用所有的API函數了,最後剩下的問題就是如何在ROM裡找一個确定的地方儲存随機連結的g_bootloaderTree位址(隻要4位元組即可)。是的,還是Kinetis ROM API用的那個巧妙的方法,下面是BootROM工程的startup檔案(Keil版),BootROM将g_bootloaderTree的位址放到了中斷向量表第8個向量的位置處(該向量為ARM Cortex-M7未定義的系統向量),是以0x20001c處開始的4bytes便固定是g_bootloaderTree位址。

  了解了前面介紹的ROM API産生背景與設計實作,它的調用方法就非常簡單了,以WDOG API調用為例,隻需要如下簡單3句代碼:

痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP

  截止目前,i.MXRT1xxx系列一共出了7款型号,但并不是每個型号都開放了ROM API,最早誕生的三款型号(105x、1021、1015)就并沒有開放API(不是沒有API,而是沒有嚴格測試),其餘型号都支援API。

RT晶片型号

是否支援ROM API

是否全功能API

i.MXRT117x

支援

i.MXRT1064

i.MXRT106x

i.MXRT105x

未開放

N/A

i.MXRT1021

i.MXRT1015

i.MXRT1011

  前面鋪墊了太多ROM API設計細節,到這裡才算進入正題,本文其實主要是要跟大家聊如何利用API裡的FlexSPI NOR驅動實作IAP。痞子衡在前面鋪墊那麼多的原因其實主要是想告訴大家,API裡的每個驅動都是經過完善測試的,尤其是這個FlexSPI NOR驅動,更是經過了千錘百煉,無論是易用性、運作穩定性還是Flash型号的支援度上都是首屈一指的。

  對于JESD216标準下的串行SPI接口Flash驅動,大家知道更多的可能是RT-Thread技術總監朱天龍大神的開源 SFUD 項目,但痞子衡告訴你,i.MXRT ROM API裡的這個串行Flash驅動也毫不遜色(持續維護與優化了近6年,曆經多款MCU的ROM,是真正的産品級),隻是不如開源項目那麼知名,不過它的源代碼也是開源在SDK裡的(\SDK\middleware\mcu-boot\src\drivers\flexspi_nor),BSD-3-Clause許可證。

  flexspi_nor_driver_interface_t便是FlexSPI NOR驅動的原型,尋常的讀寫擦功能自然不在話下,除此以外,API裡面還有一個非常厲害的xfer()函數,這個函數可以用來實作其他定制化的Flash操作函數,有興趣的朋友可以進一步去研究。

  FlexSPI驅動使用基本三步走,先調用get_config()擷取完整FlexSPI子產品配置,然後調用init()函數去初始化FlexSPI以及通路Flash擷取SFDP表資訊,最後就是調用Flash操作函數(比如erase())。

  因為FlexSPI NOR驅動API來自于BootROM,是以其在使用上有一些小小的限制,也算是其特點吧。FlexSPI驅動API裡并沒有提供Flash連接配接的Pinmux配置,其Pinmux配置已經寫死在init()函數中,就是ROM支援啟動的FlexSPI PORTA上的那些pin(片選是SS0)。

  在上面的使用示例代碼中,你會看到option.option0.U = 0xC0000008代碼,這算是FlexSPI驅動最大的特點了,這是一個簡化的option配置word(其原型可在晶片手冊裡找到),通過這個簡化的option,使用者可以輕松配置來通路不同廠商的Flash,下面是常用的Flash模式配置值。

  IAP其實就是在App中實作Flash擦寫,單純從技術上來說并不是一個很難的東西。但i.MXRT上很多時候App代碼本身也在同一片Flash裡執行(也叫XIP),而市面上很多Flash都是不支援RWW(Read-While-Write)的,這就導緻一個問題,當你調用Flash操作函數去擦寫Flash時,CPU又需要繼續去Flash擷取指令,違反了RWW,是以你隻能把Flash相關操作函數全部放在RAM中去執行(這涉及分散加載了,對于初級嵌入式使用者來說稍微有點難)。

痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP

  現在我們有了ROM API,FlexSPI驅動代碼體全部都在ROM空間裡,并不占用Flash空間,是以不存在RWW問題,真是天然為IAP而生,再也不用再管什麼分散加載這麼麻煩的事了。

  前面1.4節講了,i.MXRT1010中并沒有全功能API,主要是因為其BootROM空間較小,無法存放多餘API代碼,下面是i.MXRT1010中API執行個體,可以看到提供的FlexSPI驅動函數相當少,關于其用法後面再單獨介紹。

  最後再介紹一下i.MXRT FlexSPI API在業界的應用,這個API其實并不小衆,目前已被主流IDE和調試工具用作i.MXRT Flash下載下傳算法。

  如果你的IAR版本夠新,能夠支援i.MXRT1060等型号,随便打開一個i.MXRT1060 SDK工程,在工程Option裡找到Debugger,然後進入Flashloader配置,你會看到頁面裡有Extra parameters一欄,在下面的解釋裡有這個參數的示例,它就是前面2.3節裡介紹的option0。有了這種方式設計的Flash下載下傳算法,你再也不用手動更新下載下傳算法檔案去支援不同的Flash了,改參數就行了。

痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP

  目前最新的Jlink驅動裡的下載下傳算法也是基于ROM API的,痞子衡有一個開源項目,收集了i.MXRT所有型号的下載下傳算法源代碼工程,其中jlink算法是最全的,其他IDE算法還在陸續完善中。

https://github.com/JayHeng/imxrt-tool-flash-algo

  至此,i.MXRT系列ROM中的FlexSPI驅動API實作IAP痞子衡便介紹完畢了,掌聲在哪裡~~~

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

痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP
痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP
痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP

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

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

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

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

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

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

繼續閱讀