加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

i.MXRT兩大陣營ROM API設(shè)計

2020/08/09
160
閱讀需 17 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是 i.MXRTxxx 系列 ROM API 設(shè)計細節(jié)。

痞子衡之前寫過兩篇文章 《利用 i.MXRT1xxx 系列 ROM 提供的 FlexSPI driver API 可輕松 IAP》、《其實 i.MXRT1050,1020,1015 系列 ROM 也提供了 FlexSPI driver API》 基本把 i.MXRT1xxx 全系列的 ROM API 及其 FlexSPI NOR 驅(qū)動設(shè)計都講清楚了,其實 i.MXRTxxx 系列的 ROM API 設(shè)計跟 i.MXRT1xxx 系列的設(shè)計思路差不多(其實本就是同一個恩智浦研發(fā)小組負責的),僅有一些微小區(qū)別,本文痞子衡主要就是點出那些區(qū)別。

一、ROM 基址差異

ROM API 代碼首先是在 BootROM 里,BootROM 代碼是出廠前固化在 ROM 區(qū)域的。因為架構(gòu)設(shè)計的關(guān)系,i.MXRTxxx 系列和 i.MXRT1xxx 系列的 ROM 區(qū)域在系統(tǒng)內(nèi)存里的映射地址不同。

下表是 i.MXRTxxx 系列代表型號 i.MXRT500 的部分系統(tǒng)內(nèi)存映射,可以看到 ROM 區(qū)域起始地址是 0x03000000(非安全域)。目前 i.MXRTxxx 都是 Cortex-M33 內(nèi)核,支持 TrustZone 特性,所以 0x13000000 也是 ROM 起始地址(安全域),為了通用性,我們認 0x03000000 就可以了,這個地址在安全狀態(tài)和非安全狀態(tài)下都能被訪問。

下表是 i.MXRT1xxx 系列代表型號 i.MXRT1060 的部分系統(tǒng)內(nèi)存映射,可以看到 ROM 區(qū)域起始地址是 0x00200000。i.MXRT1xxx 系列都是 Cortex-M7 內(nèi)核,沒有 TrustZone 特性,不存在 i.MXRTxxx 上那樣的兩種狀態(tài)域下的地址。

二、API 基址備份位置差異

在 i.MXRT1xxx 系列 ROM API 介紹的文章里,痞子衡介紹過 g_bootloaderTree 地址值被復(fù)制了一份放在了 BootROM 中斷向量表第 8 個向量的位置處(該向量為 ARMv7-M 架構(gòu)下未定義的系統(tǒng)向量),因此讀取 0x0020001c 處開始的 4bytes 便能找到 i.MXRT1xxx 系列的 g_bootloaderTree。

但是由于 i.MXRTxxx 是 Cortex-M33 內(nèi)核,屬于 ARMv8-M 架構(gòu),從下圖中可以看出 ARMv8-M 架構(gòu)下中斷向量表第 8 個向量是 SecureFault,已經(jīng)被定義了,因此 BootROM 把 g_bootloaderTree 地址值放到了第 9 個向量的位置處(該向量為 ARMv8-M 架構(gòu)下未定義的系統(tǒng)向量),故讀取 0x03000020 處開始的 4bytes 才能找到 i.MXRTxxx 系列的 g_bootloaderTree(這種方式在實際 API 調(diào)用中并不可取,至于原因嘛,先賣個關(guān)子)。

?

下面是 i.MXRT500 BootROM 工程的 startup 文件(IAR 版),g_bootloaderTree 確實在第 9 個向量處:

? ? ? ? MODULE ??cstartup

? ? ? ? ;; Forward declaration of sections.
? ? ? ? SECTION CSTACK:DATA:NOROOT(3)
? ? ? ? SECTION .intvec:CODE:NOROOT(2)

? ? ? ? EXTERN ?__iar_program_start
? ? ? ? EXTERN ?g_bootloaderTree
? ? ? ? PUBLIC ?__vector_table
? ? ? ? PUBLIC ?__vector_table_0x1c

? ? ? ? DATA

__vector_table
? ? ? ? DCD ? ? sfe(CSTACK)
? ? ? ? DCD ? ? Reset_Handler
? ? ? ? DCD ? ? DefaultISR
? ? ? ? DCD ? ? HardFault_Handler
? ? ? ? DCD ? ? DefaultISR
? ? ? ? DCD ? ? DefaultISR
? ? ? ? DCD ? ? UsageFault_Handler
__vector_table_0x1c
? ? ? ? DCD ? ? SecureFault_Handler
? ? ? ? DCD ? ? g_bootloaderTree
? ? ? ? DCD ? ? 0
? ? ? ? DCD ? ? 0
? ? ? ? DCD ? ? SVC_Handler
? ? ? ? DCD ? ? DefaultISR
? ? ? ? DCD ? ? 0
? ? ? ? DCD ? ? DefaultISR
? ? ? ? DCD ? ? SysTick_Handler
? ? ? ? ? ? ? ? ;; ...

三、API 原型定義差異

下面是 i.MXRTxxx 系列 ROM API 原型定義及其實例(適用 i.MXRT500/600),基本形式跟 i.MXRT1xxx 差不多,但是 API 功能更豐富,除了 FlexSPI NOR 驅(qū)動,還有 iap api、USB low-level driver、otp driver 等(我們知道,i.MXRTxxx 與 LPC 系列同根同源,LPC 系列 ROM 里一般都會集成很多經(jīng)典 SDK 驅(qū)動,比如內(nèi)部 flash、low power 驅(qū)動,有了這些穩(wěn)定的驅(qū)動 API,LPC 系列的用戶手冊里甚至都會省去這些 IP 的寄存器介紹,直接就是 API 的介紹)。

typedef struct
{
? ? void (*runBootloader)(void *arg);
? ? uint32_t version;
? ? const char *copyright;
? ? const bootloader_context_t *runtimeContext;
? ? const kb_interface_t *kbApi;
? ? const usb_driver_interface_t *usbDriver;
? ? const USBD_API_T *lpcUsbDriver;
? ? const flexspi_nor_flash_driver_t *flexspiNorDriver;
? ? const ocotp_driver_t *otpDriver;
? ? const skboot_authenticate_interface_t *skbootAuthenticate;
} bootloader_api_entry_t;

//! @brief Static API tree.
__root const bootloader_api_entry_t g_bootloaderTree @".rom_api_tree_section" = {
? ? .runBootloader = bootloader_user_entry,
? ? .version = MAKE_VERSION('K', 3, 0, 0),
? ? .copyright = "Copyright 2019 NXP.",
? ? .runtimeContext = &g_bootloaderContext,
? ? .kbApi = &g_romApiInterface,
? ? .usbDriver = &g_usbDriverInterface,
? ? .flexspiNorDriver = &g_flexspiNorFlashDriverInterface,
? ? .otpDriver = &g_otpDriverInterface,
? ? .skbootAuthenticate = &g_skbootAuthenticateInterface,
};

四、API 實例鏈接差異

i.MXRT1xxx 系列 ROM API 實例 g_bootloaderTree 都是讓鏈接器自由鏈接的,因此每個具體型號的實際 ROM API 鏈接地址沒有一致的規(guī)律可循(這也是為什么要在中斷向量表里固定位置統(tǒng)一保存一份),而這點在 i.MXRTxxx 上有了改進,i.MXRTxxx 里將 g_bootloaderTree 放到了 .rom_api_tree_section 段里,在鏈接文件里將該段固定鏈接在 ROM 區(qū)域最后 4KB 處(BootROM 代碼沒有把全部 ROM 空間用盡)。

下面是 i.MXRTxxx BootROM 源文件中 g_bootloaderTree 的定義,加了段修飾。此外還有額外的 k_romcrc,標示 API 實例區(qū)域的結(jié)束。

__root const bootloader_api_entry_t g_bootloaderTree @".rom_api_tree_section" = {
? ? .runBootloader = bootloader_user_entry,
? ? .version = MAKE_VERSION('K', 3, 0, 0),
? ? .copyright = "Copyright 2019 NXP.",
? ? .runtimeContext = &g_bootloaderContext,
? ? // ...
};

__root const uint32_t k_romcrc @".romcrc" = 0xdeadbeef;

下面是 i.MXRTxxx 鏈接文件(IAR 工程)中 .rom_api_tree_section 段的處理(i.MXRT500 型號示例,ROM 空間是 192KB)。你可能好奇為啥 ROM_API_TREE_xx 等值是放在 0x13000000 開始的安全域 ROM 空間映射,BootROM 屬于上電啟動第一級,負責芯片系統(tǒng)的安全和啟動,當然是工作在安全狀態(tài)下,可以訪問安全域地址空間。

define symbol __ICFEDIT_region_ROM_API_TREE_start__ ? ? = 0x1302f000;
define symbol __ICFEDIT_region_ROM_API_TREE_end__ ? ? ? = 0x1302f0ff;
define symbol __ICFEDIT_region_ROM_CRC_CHECKSUM_start__ = 0x1302fffc;
define symbol __ICFEDIT_region_ROM_CRC_CHECKSUM_end__ ? = 0x1302ffff;

define region ROM_API_TREE_region = mem:[from ?__ICFEDIT_region_ROM_API_TREE_start__ to ?__ICFEDIT_region_ROM_API_TREE_end__];
define region ROM_CRC_CHECKSUM = mem:[from ?__ICFEDIT_region_ROM_CRC_CHECKSUM_start__ to ?__ICFEDIT_region_ROM_CRC_CHECKSUM_end__];

place in ROM_API_TREE_region { section .rom_api_tree_section };
place in ROM_CRC_CHECKSUM { section .romcrc };

基于上面的設(shè)計,你才會在 i.MXRT500 參考手冊里 Non-Secure Boot ROM 章節(jié)看到如下 ROM API 地址及結(jié)構(gòu)信息圖(圖中僅標了常用的 API 功能函數(shù)),實際 ROM API 調(diào)用時,App 的執(zhí)行其實都是經(jīng)過 ROM 引導(dǎo)和認證的,App 中既可以訪問安全域地址(0x1302f000)來調(diào)用 API,也可以訪問非安全域地址(0x0302f000)來調(diào)用 API。

最后再來回答前面賣的關(guān)子,為什么 i.MXRTxxx 系列通過 BootROM 中斷向量表第 9 個向量值來訪問 ROM API 這種方式并不可???其實從 BootROM 煞費苦心地將 g_bootloaderTree 固定鏈接在 ROM 區(qū)域最后 4KB 處,你就能看出其用意。如果你掛上調(diào)試器直接訪問 i.MXRTxxx 的 ROM 區(qū)域前 20KB 的空間,你會發(fā)現(xiàn)無法訪問,在 App 里 AHB 方式讀這個區(qū)域,也會直接產(chǎn)生 HardFault,因為 BootROM 里做了特殊設(shè)計故意隱藏了前 20KB 空間,這個空間里存放了 BootROM 想要保護的數(shù)據(jù)和代碼,至于內(nèi)容是啥,純屬機密,恕不奉告,哈哈。

至此,i.MXRTxxx 系列 ROM API 設(shè)計細節(jié)痞子衡便介紹完畢了,掌聲在哪里~~~

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

碩士畢業(yè)于蘇州大學電子信息學院,目前就職于恩智浦(NXP)半導(dǎo)體MCU系統(tǒng)部門,擔任嵌入式系統(tǒng)應(yīng)用工程師。痞子衡會定期分享嵌入式相關(guān)文章