大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是**藉助i.MXRT10xx系列INIT_VTOR功能可以縮短程式熱重啟時間**。 最近痞子衡寫了篇文章 [《i.MXRT從Serial NAND啟動時間測量》](https://www.cnblogs.com/henjay724/p/ ...
大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是藉助i.MXRT10xx系列INIT_VTOR功能可以縮短程式熱重啟時間。
最近痞子衡寫了篇文章 《i.MXRT從Serial NAND啟動時間測量》,這篇文章詳細測試了不同長度的 Non-XIP 程式在不同 NAND 訪問速度下由 BootROM 載入啟動所需要的時間,比如 240KB 的程式在 60MHz NAND 的訪問速度下啟動時間接近 30ms,這個啟動時間對於有些響應時間敏感的應用(比如汽車電子)來說還是比較長的。
對於 Non-XIP 程式,經過冷啟動後,其程式體本身已經被載入進晶元內部 SRAM 了,除非發生 POR,否則 SRAM 中的程式會一直保持著。假設程式在惡劣的電磁環境中運行,代碼里雖然包含異常複位的處理,但是每次程式複位啟動時間還是和冷啟動時間一樣長(每次都需要 BootROM 搬移載入),有點難以接受。那麼對於這種熱啟動的情況,程式啟動時間能夠縮短嗎?答案是可以的,今天痞子衡就介紹下 i.MXRT 上的 INIT_VTOR 特性:
- 備註1:本文主角是i.MXRT1050,但內容也基本適用其它i.MXRT10xx系列。
- 備註2:同樣的測試在i.MXRT1160/1170下無效,因為CM7_INIT_VTOR所在的IOMUXC_LPSR_GPR->GPR26在軟複位下不能保持。
一、INIT_VTOR功能簡介
在介紹 INIT_VTOR 功能之前,大家首先要對 ARM Cortex-M 內核的中斷向量表偏移寄存器 SCB->VTOR 功能有所瞭解,具體可以看痞子衡的舊文 《Cortex-M中斷向量表原理及其重定向方法》。
簡單來說,晶元上電啟動後內核都是從 SCB->VTOR 指向的地址處獲取程式中斷向量表裡的第二個向量即所謂的複位函數 Reset_Handler。有了複位函數,就找到了程式入口。
; 摘取自 startup_MIMXRT1052.s
__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler
DCD NMI_Handler
DCD HardFault_Handler
DCD MemManage_Handler
DCD BusFault_Handler
DCD UsageFault_Handler
...
對於 i.MXRT1050,我們知道晶元上電覆位都是執行 BootROM 代碼,BootROM 中斷向量表固定放在了 0x0020_0000 地址處。那麼這個 0x0020_0000 地址是怎麼被賦給 SCB->VTOR 寄存器的呢?這就引出了本文主角 IOMUXC_GPR->GPR16[32:7] - CM7_INIT_VTOR 位,這 25bits 的 CM7_INIT_VTOR 值每次複位都會被晶元系統自動載入進 SCB->VTOR[32:7] 中,其預設值即對應 BootROM 中斷向量表地址。
正如痞子衡舊文 《妙用i.MXRT1xxx里SystemReset不複位的GPR寄存器》 提及的那樣,IOMUXC_GPR 寄存器僅在 POR 複位或者整體重新上電時才會被置位,這就意味著我們在應用程式中只需要設置一次 CM7_INIT_VTOR 值,其後不管發生多少次類似 NVIC_SystemReset() 的複位,CM7_INIT_VTOR 值都不會改變。
二、使用INIT_VTOR加速程式熱重啟
有了上一節的理論基礎,我們來做個實驗。痞子衡找了一塊 MIMXRT1050-EVK12(Rev.A)板卡,將其啟動設備換成串列 NAND 啟動(電阻切換到使能 U33,並將 U33 替換成華邦 W25N01GV)。
然後按照串列 NAND 啟動時間測試方法那樣修改 \SDK_2_13_0_EVKB-IMXRT1050\boards\evkbimxrt1050\demo_apps\led_blinky\iar 常式(debug build,即代碼在 ITCM 運行,註意修改鏈接文件中的 m_interrupts_start = 0x00002000),併在 SystemInit() 函數里調用如下測試函數,根據是否設置 IOMUXC_GPR->GPR16 寄存器編譯出兩個不同鏡像文件(直接編輯 bin 文件將其均填充至 120KB)。
void set_led_gpio(void)
{
CLOCK_EnableClock(kCLOCK_Iomuxc);
gpio_pin_config_t USER_LED_config = {
.direction = kGPIO_DigitalOutput,
.outputLogic = 0U,
.interruptMode = kGPIO_NoIntmode
};
GPIO_PinInit(GPIO1, 9U, &USER_LED_config);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0x10B0U);
SystemCoreClockUpdate();
GPIO_PinWrite(GPIO1, 9U, 0U);
SDK_DelayAtLeastUs(5000, SystemCoreClock);
// 根據是否設置 CM7_INIT_VTOR 分別編譯兩個不同鏡像文件
// 設置 CM7_INIT_VTOR 指向地址 0x00002000,即用戶應用程式中斷向量表
IOMUXC_GPR->GPR16 = (IOMUXC_GPR->GPR16 & (~IOMUXC_GPR_GPR16_CM7_INIT_VTOR_MASK)) | IOMUXC_GPR_GPR16_CM7_INIT_VTOR(0x2000 >> 7);
NVIC_SystemReset();
while (1);
}
然後藉助 MCUBootUtility 工具將這兩個不同鏡像文件下載進串列 NAND flash,並測試相應啟動時間。這裡 Flash 運行速度就選擇 60MHz:
下麵是不設置 IOMUXC_GPR->GPR16 的程式啟動時間測試結果,無論是一開始的 POR 冷啟動還是後面 NVIC_SystemReset() 引起的熱啟動,啟動時間都需要約 18.66ms:
下麵是設置了 IOMUXC_GPR->GPR16 指向 0x2000 之後的程式啟動時間測試結果,只有一開始的 POR 冷啟動時間是 18.66ms,後面 NVIC_SystemReset() 引起的熱啟動時間僅需要約 5.26ms。
上述實驗結果證明,設置 IOMUXC_GPR->GPR16 指嚮應用程式中斷向量表之後確實能縮短程式熱啟動時間。有朋友可能會疑問,設置了從 ITCM 直接熱啟動後為何還是有 5.26ms 的啟動時間?這其實主要是從進入應用程式 Reset_Handler 到執行到測試 GPIO 拉低時的代碼所消耗的時間,並且需要註意的是由 BootROM 載入執行的程式預設是在 ROM 配置後的 396MHz 主頻下執行的(主頻夠快,測試代碼消耗時間可以忽略不計),而直接複位從 ITCM 里執行的程式是在預設主頻 12MHz 下執行的(主頻較慢,測試代碼消耗時間不得不計)。
最後再提一下,除了直接在應用程式里設置 IOMUXC_GPR->GPR16 之外,也可以藉助 BootROM 的 DCD 功能來設置,同樣可以藉助 MCUBootUtility 直接完成(詳細步驟可參考 《利用i.MXRT1xxx系列ROM集成的DCD功能可輕鬆配置指定外設》),痞子衡實測是有效的。
翻看 RT1050 參考手冊 System Boot 章節,IOMUXC_GPR 寄存器地址空間也確實在有效的 DCD 設置範圍。
至此,藉助i.MXRT10xx系列INIT_VTOR功能可以縮短程式熱重啟時間痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時發佈到我的 博客園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上。
微信搜索"痞子衡嵌入式"或者掃描下麵二維碼,就可以在手機上第一時間看了哦。
最後歡迎關註痞子衡個人微信公眾號【痞子衡嵌入式】,一個專註嵌入式技術的公眾號,跟著痞子衡一起玩轉嵌入式。
衡傑(痞子衡),目前就職於某知名外企半導體公司MCU系統部門,擔任嵌入式系統應用工程師。
專欄內所有文章的轉載請註明出處:http://www.cnblogs.com/henjay724/
與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]
可以關註痞子衡的Github主頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。
關於專欄文章有任何疑問請直接在博客下麵留言,痞子衡會及時回覆免費(劃重點)答疑。
痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。