痞子衡嵌入式:了解i.MXRTxxx系列ROM API及其与i.MXRT1xxx系列的差异
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRTxxx系列ROM API设计细节。
痞子衡之前写过两篇文章 《利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP》、《其实i.MXRT1050,1020,1015系列ROM也提供了FlexSPI driver API》 基本把i.MXRT1xxx全系列的ROM API及其FlexSPI NOR驱动设计都讲清楚了,其实i.MXRTxxx系列的ROM API设计跟i.MXRT1xxx系列的设计思路差不多(其实本就是同一个恩智浦研发小组负责的),仅有一些微小区别,本文痞子衡主要就是点出那些区别。
一、ROM基址差异
ROM API代码首先是在BootROM里,BootROM代码是出厂前固化在ROM区域的。因为架构设计的关系,i.MXRTxxx系列和i.MXRT1xxx系列的ROM区域在系统内存里的映射地址不同。
下表是i.MXRTxxx系列代表型号i.MXRT500的部分系统内存映射,可以看到ROM区域起始地址是0x03000000(非安全域)。目前i.MXRTxxx都是Cortex-M33内核,支持TrustZone特性,所以0x13000000也是ROM起始地址(安全域),为了通用性,我们认0x03000000就可以了,这个地址在安全状态和非安全状态下都能被访问。
下表是i.MXRT1xxx系列代表型号i.MXRT1060的部分系统内存映射,可以看到ROM区域起始地址是0x00200000。i.MXRT1xxx系列都是Cortex-M7内核,没有TrustZone特性,不存在i.MXRTxxx上那样的两种状态域下的地址。
二、API基址备份位置差异
在i.MXRT1xxx系列ROM API介绍的文章里,痞子衡介绍过g_bootloaderTree地址值被复制了一份放在了BootROM中断向量表第8个向量的位置处(该向量为ARMv7-M架构下未定义的系统向量),因此读取0x0020001c处开始的4bytes便能找到i.MXRT1xxx系列的g_bootloaderTree。
但是由于i.MXRTxxx是Cortex-M33内核,属于ARMv8-M架构,从下图中可以看出ARMv8-M架构下中断向量表第8个向量是SecureFault,已经被定义了,因此BootROM把g_bootloaderTree地址值放到了第9个向量的位置处(该向量为ARMv8-M架构下未定义的系统向量),故读取0x03000020处开始的4bytes才能找到i.MXRTxxx系列的g_bootloaderTree(这种方式在实际API调用中并不可取,至于原因嘛,先卖个关子)。
下面是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驱动,还有iap api、USB low-level driver、otp driver等(我们知道,i.MXRTxxx与LPC系列同根同源,LPC系列ROM里一般都会集成很多经典SDK驱动,比如内部flash、low power驱动,有了这些稳定的驱动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链接地址没有一致的规律可循(这也是为什么要在中断向量表里固定位置统一保存一份),而这点在i.MXRTxxx上有了改进,i.MXRTxxx里将g_bootloaderTree放到了 .rom_api_tree_section 段里,在链接文件里将该段固定链接在ROM区域最后4KB处(BootROM代码没有把全部ROM空间用尽)。
下面是i.MXRTxxx BootROM源文件中g_bootloaderTree的定义,加了段修饰。此外还有额外的k_romcrc,标示API实例区域的结束。
__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属于上电启动第一级,负责芯片系统的安全和启动,当然是工作在安全状态下,可以访问安全域地址空间。
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 };
基于上面的设计,你才会在i.MXRT500参考手册里Non-Secure Boot ROM章节看到如下ROM API地址及结构信息图(图中仅标了常用的API功能函数),实际ROM API调用时,App的执行其实都是经过ROM引导和认证的,App中既可以访问安全域地址(0x1302f000)来调用API,也可以访问非安全域地址(0x0302f000)来调用API。
最后再来回答前面卖的关子,为什么i.MXRTxxx系列通过BootROM中断向量表第9个向量值来访问ROM API这种方式并不可取?其实从BootROM煞费苦心地将g_bootloaderTree固定链接在ROM区域最后4KB处,你就能看出其用意。如果你挂上调试器直接访问i.MXRTxxx的ROM区域前20KB的空间,你会发现无法访问,在App里AHB方式读这个区域,也会直接产生HardFault,因为BootROM里做了特殊设计故意隐藏了前20KB空间,这个空间里存放了BootROM想要保护的数据和代码,至于内容是啥,纯属机密,恕不奉告,哈哈。
至此,i.MXRTxxx系列ROM API设计细节痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。
痞子衡嵌入式:了解i.MXRTxxx系列ROM API及其与i.MXRT1xxx系列的差异的更多相关文章
- 痞子衡嵌入式:在SBL项目实战中妙用i.MXRT1xxx里SystemReset不复位的GPR寄存器
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx里SystemReset不复位的GPR寄存器的小妙用. 我们知道稍大规模的项目代码设计一般都是多人协作完成的,在项目 ...
- 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...
- 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(2) - 识别当前i.MXRT型号
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(2)之识别当前i.MXRT型号. 文接上篇 <超级下载算法(RT-UFL)开发笔记(1) - 执行在不同CM ...
- 痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列ROM中的FlexSPI驱动API实现IAP. 痞子衡的技术交流群里经常有群友提问: i.MXRT中的FlexSPI驱动 ...
- 痞子衡嵌入式:了解i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择. 关于 i.MXRT 系列 BootROM 中串行 NOR ...
- 痞子衡嵌入式:深扒i.MXRTxxx系列ROM中集成的串行NOR Flash启动SW Reset功能及其应用场合
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM中集成的串行NOR Flash启动SW Reset功能及其应用场合. 在串行 NOR Flash 热启动过程 ...
- 痞子衡嵌入式:揭秘i.MXRTxxx系列上串行NOR Flash双程序可交替启动设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT500/600上串行NOR Flash双程序可交替启动设计. 在上一篇文章 <i.MXRT1170上串行NOR Fla ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(2)- KBOOT形态(ROM/Bootloader/Flashloader)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT形态. 痞子衡在前一篇文章里简介了 KBOOT架构,我们知道KBOOT是一个完善的Bootl ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(11)- KBOOT特性(ROM API)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之ROM API特性. KBOOT的ROM API特性主要存在于ROM Bootloader ...
随机推荐
- 数据可视化之powerBI技巧(二十二)利用这个方法,帮你搞定Power BI"增量刷新"
Power BI的增量刷新功能现在已经对Pro用户开通,但由于种种限制,很多人依然无法使用无这个功能,所以,每一次刷新,都要彻底更新数据集.这对于量级比较大的数据集来说,着实是一件耗费时间的事情. 拿 ...
- Spring配置类深度剖析-总结篇(手绘流程图,可白嫖)
生命太短暂,不要去做一些根本没有人想要的东西.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习 ...
- 用Vue实现一个简单的图片轮播
本文已收录至https://github.com/likekk/studyBlog欢迎大家star,共同学习,共同进步.如果文章有错误的地方,欢迎大家指出.后期将在将GitHub上规划前端学习的路线和 ...
- Python Ethical Hacking - VULNERABILITY SCANNER(3)
Polish the Python code using sending requests in a session Class Scanner. #!/usr/bin/env python impo ...
- This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary lo的解决办法
创建存储过程时,出错信息: ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA ...
- p70_域名解析系统DNS
一.DNS作用 二.域名 www.cskaoyan.com. www 三级域名 cskaoyan 二级域名 com 顶级域名 三.域名服务器 根域名服务器:知道所有顶级域名服务器的域名和ip地址 顶级 ...
- 设计模式:composite模式
目的:使容器和内容具备一致性 实现:将对象组合成树形结构以表示“部分-整体”的层次结构 实例:文件夹中可以包含文件夹也可以包含文件 例子: class Item //接口定义 { public: vi ...
- 超简单的jq图片上传
<label class="file_img" for="file_imgs"> <input class="file_imgs&q ...
- CAS实现SSO 单点登录
结构 CAS分为两部分,CAS Server和CAS Client CAS Server用来负责用户的认证工作,就像是把第一次登录用户的一个标识存在这里,以便此用户在其他系统登录时验证其需不需要再次登 ...
- 基于Scrapy的B站爬虫
基于Scrapy的B站爬虫 最近又被叫去做爬虫了,不得不拾起两年前搞的东西. 说起来那时也是突发奇想,想到做一个B站的爬虫,然后用的都是最基本的Python的各种库. 不过确实,实现起来还是有点麻烦的 ...