大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT1xxx裡SystemReset不複位的GPR寄存器的小妙用。
我們知道稍大規模的項目代碼設計一般都是多人協作完成的,在項目開始階段的總體設計時,項目組長通常會将代碼按功能進行劃分,每個功能塊代碼之間盡量做到耦合度低、互不依賴、互不影響,這樣各功能可以獨立進行單元測試,項目得以并行開發,後期通過事先定義好的接口/協定進行功能塊內建即可。
但上述方法在嵌入式軟體項目裡有時候會遇到功能塊內建後互相幹擾的問題,因為嵌入式項目很多時候并不是純軟體設計,也會跟片内外設資源打交道,而片内外設屬于硬體範疇,硬體子產品的工作是有前後狀态依賴的(這點在片内時鐘的配置上展現得尤其明顯),出了問題傳統方法是具體分析具體解決,來一個就解決一個,但任何代碼的改動或者後期新特性的增加都可能會帶來新的潛在幹擾問題。
那麼對于上述困境,有沒有一個一勞永逸的解決方法?其實是有的!那就是每個功能塊在設計時都不要依賴晶片初始狀态,按照進入時先清理系統環境,然後做功能設計,退出時做一下系統恢複。這種方法雖然保險,但是會引入內建後項目整體運作低效的問題。今天痞子衡要在具體項目實戰中介紹一種利用i.MXRT晶片内System Reset後不複位的GPR寄存器來解決屬性上互斥的功能代碼塊內建互相幹擾問題的方法。
Note: 文中示例 SNVS GPR 讀寫代碼主要适用 i.MXRT1015/1020/1024/1050/1060/1064 型号,如果是 i.MXRT1010/1160/1170型号參見 《不一樣的SNVS GPR寄存器讀寫控制設計》 。
恩智浦MCU SE團隊近期一直在加班加點趕一個大項目,這個項目是為客戶産品OTA需求而生的。我們知道線上更新是每個智能産品都不可繞開的話題,恩智浦SE團隊為了友善客戶在基于i.MXRT/LPC的産品上做線上更新,特别推出OTA參考設計,下面是功能架構簡圖:項目分為SBL + SFW兩部分,SBL負責ISP本地更新(UART/USB)以及App切換管理;SFW是一個示例App,其除了客戶項目業務功能外,也內建了遠端更新功能(WiFi、以太、U盤、SD卡四種更新方式)。

在SBL代碼設計裡,主要有兩大子功能子產品:一個是ISP本地更新 (isp_boot_main),另一個是App切換管理(sbl_boot_main),其中ISP本地更新屬于可選項,而App切換管理是必選。
SBL的主流程是上電啟動運作後,先執行ISP本地更新功能塊,在逾時時間内,如果有收到來自Host的ISP指令,則進入ISP指令處理,此後除非執行ISP複位指令或者有闆級複位,否則不會退出ISP;
如果在逾時時間内沒有收到ISP指令,則轉到App切換管理功能塊。在驗證App時,如果發現Flash裡有合法App,則跳轉過去執行;如果沒有發現合法的App,會重新傳回ISP本地更新(此時是無限逾時)。大概主邏輯代碼如下:
上述SBL設計裡,你會發現ISP本地更新和App切換管理兩個功能塊在執行上是互斥的,是Flash裡的App處理需求将它們聯系在了一起。從軟體內建角度來說,這兩個功能本不該互相影響,但實際上它們之間産生了互相影響,因為各自在設計時沒有遵循進入時清理系統、退出時恢複現場的準則,是以 isp_boot_main() 在逾時結束後跳到 sbl_boot_main() 對其部分驗簽功能産生了影響,而 sbl_boot_main() 執行後沒找到合法App跳回 isp_boot_main() 時又出現ISP功能不正常的情況,我們需要解決這個問題。
第一小節裡描述的問題,可以通過功能塊退出時恢複現場來解決,但是每個子產品代碼量都比較大,使用代碼去逐一恢複現場不太容易。痞子衡想到的一個好辦法就是調用 NVIC_SystemReset() 函數來簡單粗暴地将晶片系統複位,我們所需要做的就是尋找一個區域,能夠臨時存放标志位,并且這個區域内容不受系統軟複位的影響,晶片複位回來之後在SBL裡增加對标志位的判斷處理,處理結束後再将标志位清掉。
在尋找這個不受系統軟複位影響的區域前,我們先對i.MXRT裡面的電源管理架構作個基本了解。下圖是i.MXRT1060的電源架構,除了USB和ADC子產品特殊供電需求外,晶片一共有四種電源輸入。在闆級供電設計時,通常VDD_SNVS_IN需要單獨一路外部輸入(設計上應由電池供電),其他三路電源VDD_HIGH_IN / DCDC_IN / VDD_SOC_IN可共用一路外部輸入(晶片POR_B引腳往往連在這個外部輸入控制上)。
從晶片系統複位等級上來分,一共有三類複位:第一類是借助Cortex-M7核心SCB子產品的AIRCR寄存器中內建的SYSRESETREQ複位的支援、第二類是DCDC重新上電(POR_B複位)、第三類是整體重新上電。依據這三種不同程度的複位,痞子衡整理了i.MXRT上所有可存放标志位的區域受不同複位類型影響情況如下:
子產品 \ 複位類型
NVIC_SystemReset()
POR_B和DCDC重新上電
整體重新上電
TCM
OCRAM
IOMUXC_GPR
SRC_GPR
保持
複位
IOMUXC_SNVS_GPR
SNVS_LPGPR
Flash, eFuse
根據上表,我們先排除掉NVM屬性的Flash和eFuse,它們不符合臨時存放、輕松讀寫的需求。TCM / OCRAM可用,但需要在SBL工程裡做特殊處理,配置設定一塊.noinit區,并且要确定BootROM沒有使用這個區域,用起來還是有點麻煩。IOMUXC_GPR / SRC_GPR用起來簡單,但它們已被SoC / BootROM占用了,不能随便使用,對晶片産生的影響未知。IOMUXC_SNVS_GPR / SNVS_LPGPR這兩個都不錯,但後者在使能加密時有時會被用來存放使用者密鑰。是以 IOMUXC_SNVS_GPR 寄存器才是最佳選擇,這也是真正意義上開放給使用者自由使用的GPR寄存器。
現在我們找到了理想的 IOMUXC_SNVS_GPR 寄存器,那麼可在SBL代碼中增加兩個函數 isp_cleanup_enter()、isp_cleanup_exit(),前者用于觸發軟複位前标記狀态,後者用于軟複位後讀取标記的狀态做相應處理。最終修改後的SBL主邏輯代碼如下:
至此,i.MXRT1xxx裡SystemReset不複位的GPR寄存器的小妙用痞子衡便介紹完畢了,掌聲在哪裡~~~
文章會同時釋出到我的 部落格園首頁、CSDN首頁、知乎首頁、微信公衆号 平台上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。
最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。
衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。
專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]
可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。