查看: 1350|回复: 1

[分享] 我们不一样 - i.MXRT两大阵营ROM API设计

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3299

    主题

    6546

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32024
    最后登录
    2024-4-25
    发表于 2020-8-7 11:13:14 | 显示全部楼层 |阅读模式
    我们不一样 - i.MXRT两大阵营ROM API设计


    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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区域在系统内存里的映射地址不同。
    4.png
    下表是i.MXRTxxx系列代表型号i.MXRT500的部分系统内存映射,可以看到ROM区域起始地址是0x03000000(非安全域)。目前i.MXRTxxx都是Cortex-M33内核,支持TrustZone特性,所以0x13000000也是ROM起始地址(安全域),为了通用性,我们认0x03000000就可以了,这个地址在安全状态和非安全状态下都能被访问。
    5.png

    二、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调用中并不可取,至于原因嘛,先卖个关子)。
    6.png
    下面是i.MXRT500 BootROM工程的startup文件(IAR版),g_bootloaderTree确实在第9个向量处:
    1.   MODULE  ?cstartup

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

    5.         EXTERN  __iar_program_start
    6.         EXTERN  g_bootloaderTree
    7.         PUBLIC  __vector_table
    8.         PUBLIC  __vector_table_0x1c

    9.         DATA

    10. __vector_table
    11.         DCD     sfe(CSTACK)
    12.         DCD     Reset_Handler
    13.         DCD     DefaultISR
    14.         DCD     HardFault_Handler
    15.         DCD     DefaultISR
    16.         DCD     DefaultISR
    17.         DCD     UsageFault_Handler
    18. __vector_table_0x1c
    19.         DCD     SecureFault_Handler
    20.         DCD     g_bootloaderTree
    21.         DCD     0
    22.         DCD     0
    23.         DCD     SVC_Handler
    24.         DCD     DefaultISR
    25.         DCD     0
    26.         DCD     DefaultISR
    27.         DCD     SysTick_Handler
    28.                 ;; ...
    复制代码
    三、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的介绍)。
    1. typedef struct
    2. {
    3.     void (*runBootloader)(void *arg);
    4.     uint32_t version;
    5.     const char *copyright;
    6.     const bootloader_context_t *runtimeContext;
    7.     const kb_interface_t *kbApi;
    8.     const usb_driver_interface_t *usbDriver;
    9.     const USBD_API_T *lpcUsbDriver;
    10.     const flexspi_nor_flash_driver_t *flexspiNorDriver;
    11.     const ocotp_driver_t *otpDriver;
    12.     const skboot_authenticate_interface_t *skbootAuthenticate;
    13. } bootloader_api_entry_t;

    14. //! @brief Static API tree.
    15. __root const bootloader_api_entry_t g_bootloaderTree @".rom_api_tree_section" = {
    16.     .runBootloader = bootloader_user_entry,
    17.     .version = MAKE_VERSION('K', 3, 0, 0),
    18.     .copyright = "Copyright 2019 NXP.",
    19.     .runtimeContext = &g_bootloaderContext,
    20.     .kbApi = &g_romApiInterface,
    21.     .usbDriver = &g_usbDriverInterface,
    22.     .flexspiNorDriver = &g_flexspiNorFlashDriverInterface,
    23.     .otpDriver = &g_otpDriverInterface,
    24.     .skbootAuthenticate = &g_skbootAuthenticateInterface,
    25. };
    复制代码
    四、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实例区域的结束。
    1. __root const bootloader_api_entry_t g_bootloaderTree @".rom_api_tree_section" = {
    2.     .runBootloader = bootloader_user_entry,
    3.     .version = MAKE_VERSION('K', 3, 0, 0),
    4.     .copyright = "Copyright 2019 NXP.",
    5.     .runtimeContext = &g_bootloaderContext,
    6.     // ...
    7. };

    8. __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属于上电启动第一级,负责芯片系统的安全和启动,当然是工作在安全状态下,可以访问安全域地址空间。
    1. define symbol __ICFEDIT_region_ROM_API_TREE_start__     = 0x1302f000;
    2. define symbol __ICFEDIT_region_ROM_API_TREE_end__       = 0x1302f0ff;
    3. define symbol __ICFEDIT_region_ROM_CRC_CHECKSUM_start__ = 0x1302fffc;
    4. define symbol __ICFEDIT_region_ROM_CRC_CHECKSUM_end__   = 0x1302ffff;

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

    7. place in ROM_API_TREE_region { section .rom_api_tree_section };
    8. 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。
    7.png
    最后再来回答前面卖的关子,为什么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设计细节痞子衡便介绍完毕了,掌声在哪里~~~




    文章出处:痞子衡嵌入式

    签到签到
    回复

    使用道具 举报

    该用户从未签到

    656

    主题

    6312

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    20015
    最后登录
    2024-4-25
    发表于 2020-8-7 13:53:59 | 显示全部楼层
    妥妥的干货分享!非常赞!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-26 01:44 , Processed in 0.111511 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表