请选择 进入手机版 | 继续访问电脑版
查看: 42|回复: 1

[分享] 超级下载算法如何识别当前i.MXRT型号?

[复制链接]
  • TA的每日心情
    开心
    前天 16:19
  • 签到天数: 91 天

    [LV.6]常住居民II

    1665

    主题

    3140

    帖子

    0

    金豆

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    15705
    最后登录
    2021-2-26
    发表于 4 天前 | 显示全部楼层 |阅读模式

    超级下载算法如何识别当前i.MXRT型号?



    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是超级下载算法开发笔记(2)之识别当前i.MXRT型号。


    文接上篇 《超级下载算法(RT-UFL)开发笔记(1) - 执行在不同CM内核下》,我们已经解决了超级下载算法能够在i.MXRT全系列下执行的问题,现在我们往前继续推进项目。因为这个超级下载算法将来要跑在很多个芯片型号上,有时候因为型号间差异,我们不得不针对性地弄出不同代码处理分支,而这一切的前提是我们能动态地获取当前芯片型号。


    本篇是开发笔记第二篇,咱们就重点聊聊如何让超级下载算法知道当前跑在哪个i.MXRT型号下。


    一、寻找i.MXRT家族的ID信息
    恩智浦当前MCU产品线众多,i.MXRT是2018年才开始推出的新系列,在这之前恩智浦主推的MCU是经典的Kinetis和LPC系列,痞子衡对这两个系列产品也非常熟,型号信息在Kinetis和LPC上都有展现。


    1.1 回顾Kinetis和LPC
    Kinetis系列有一个专门存放型号信息的寄存器即SIM->SDID,这个寄存器设计得非常经典,其FAMILYID + SUBFAMID + SERIESID区域组合将Kinetis系列的家族分类特性展示得淋漓尽致。

    12.png

    LPC系列存放型号信息的寄存器是SYSCON->DEVICE_ID0,这个寄存器是另外一种设计风格,低20bit直接就是LPC系列号的值,比如LPC54114xxx型号其SYSCON->DEVICE_ID0[19:0] = 0x54114,是不是简单粗暴。
    13.png

    1.2 查找i.MXRT的ID寄存器
    我们知道i.MXRT从架构上分为四位数和三位数两大阵营,四位数源自i.MX应用处理器,三位数源自LPC系列,我们分别来看。

    翻看i.MXRT四位数典型型号i.MXRT1060的参考手册,并没有找到任何有关型号信息的寄存器,仅有UID寄存器,但UID跟芯片型号无关。四位数上找不到型号信息寄存器,也跟其源于i.MX有关,毕竟MPU不像MCU那样会细分特别多的型号。

    再看i.MXRT三位数典型型号i.MXRT600的参考手册,我们找到了型号信息,在SYSCTL0->PRODUCT_ID寄存器中,细看其寄存器设计,还是能看出LPC的影子的,SYSCTL0->PRODUCT_ID[15:4]直接就是系列号的值。
    14.png

    二、确认i.MXRT型号的替代方法
    根据上一节的分析,我们几乎不能用传统Kinetis或LPC上型号信息寄存器那一套方式来统一获取i.MXRT型号,那有没有替代方法呢?答案当然是有。灵感来自于痞子衡之前研究i.MXRT的ROM API时写过的一篇文章 《了解i.MXRTxxx系列ROM API及其与i.MXRT1xxx系列的差异》,i.MXRT系列全部都有BootROM,每个型号的ROM区域内容并不尽然相同,我们可以通过读几个ROM区域不同位置的值来定位型号。

    2.1 读SCB->CPUID得到内核版本
    i.MXRT四位数(都是CM7内核)的ROM基址是0x200000,而i.MXRT三位数(都是CM33内核)的ROM基址是0x3000000,基址是有差异的,所以我们首先需要先找出一种方法来区分基址,这里可以借助ARM Cortex-M内核模块SCB里的CPUID寄存器。

    翻看ARM Cortex-M内核的Generic User Guide,可以找到如下CPUID寄存器的定义,其中CPUID[PartNo]中记录了内核版本,CM7的值是0xC27,CM33的值是0xD21。
    15.png

    我们可以很容易写出如下ufl_get_core_type()函数。
    1. /* See Part number of core in Cortex-Mx Generic UG */
    2. #define CORE_ID_CM33 (0xD21)
    3. #define CORE_ID_CM7  (0xC27)

    4. typedef enum _core_type
    5. {
    6.     kCoreType_Invalid = 0U,
    7.     kCoreType_CM33    = 1U,
    8.     kCoreType_CM7     = 2U,
    9. } core_type_t;

    10. static core_type_t ufl_get_core_type(void)
    11. {
    12.     core_type_t coreType = kCoreType_Invalid;
    13.     uint32_t coreid = (SCB->CPUID & SCB_CPUID_PARTNO_Msk) >> SCB_CPUID_PARTNO_Pos;

    14.     switch (coreid)
    15.     {
    16.         case CORE_ID_CM33:
    17.             coreType = kCoreType_CM33;
    18.             break;

    19.         case CORE_ID_CM7:
    20.             coreType = kCoreType_CM7;
    21.             break;

    22.         default:
    23.             break;
    24.     }

    25.     return coreType;
    26. }
    复制代码
    2.2 通过ROM内容定位i.MXRT型号
    有了ufl_get_core_type()函数,我们便可以进一步写出如下ufl_get_imxrt_chip_id()函数,s_romFingerprint[]结构体数组预先存放全部i.MXRT型号的ROM定位信息(此处仅示例了RT600和RT1060),我们选了ROM偏移0x8000、0xa000、0xc000处的四字节数据来定位,如后期随着型号的增多,出现定位位置处数据全部雷同的巧合的话,可以更改定位位置保证定位数据一定不相同。

    1. typedef enum _rt_chip_id
    2. {
    3.     kChipId_Invalid = 0xFFU,
    4.     kChipId_RT6xx   = 1U,
    5.     kChipId_RT106x  = 2U,
    6. } rt_chip_id_t;

    7. #define RT_ROM_BASE_CM33 (0x03000000u)
    8. #define RT_ROM_BASE_CM7  (0x00200000u)

    9. #define ROM_FP_OFFSET1 (0x8000)
    10. #define ROM_FP_OFFSET2 (0xa000)
    11. #define ROM_FP_OFFSET3 (0xc000)

    12. typedef struct _rom_fingerprint
    13. {
    14.     uint32_t chipId;
    15.     uint32_t content[3];
    16. } rom_fingerprint_t;

    17. static const rom_fingerprint_t s_romFingerprint[] = {
    18.     {kChipId_RT6xx,  {0xb108f82a, 0x0200f2c5, 0x0070f104} },        // From ROM 2.0rc5.1
    19.     {kChipId_RT106x, {0xb0893000, 0x80dbf000, 0xf2c44100} },        // From ROM 1.0rc3
    20. };

    21. rt_chip_id_t ufl_get_imxrt_chip_id(void)
    22. {
    23.     rt_chip_id_t chipId = kChipId_Invalid;
    24.     core_type_t coreType;
    25.     uint32_t rtRomBase = 0;

    26.     coreType = ufl_get_core_type();
    27.     if (kCoreType_CM33 == coreType)
    28.     {
    29.         rtRomBase = RT_ROM_BASE_CM33;
    30.     }
    31.     else if (kCoreType_CM7 == coreType)
    32.     {
    33.         rtRomBase = RT_ROM_BASE_CM7;
    34.     }
    35.     else
    36.     {}

    37.     do
    38.     {
    39.         uint32_t content[3];
    40.         content[0] = *(uint32_t *)(rtRomBase + ROM_FP_OFFSET1);
    41.         content[1] = *(uint32_t *)(rtRomBase + ROM_FP_OFFSET2);
    42.         content[2] = *(uint32_t *)(rtRomBase + ROM_FP_OFFSET3);

    43.         uint32_t idx = sizeof(s_romFingerprint) / sizeof(rom_fingerprint_t);
    44.         while (idx--)
    45.         {
    46.             if (!memcmp(s_romFingerprint[idx].content, content, sizeof(content)))
    47.             {
    48.                 chipId = (rt_chip_id_t)s_romFingerprint[idx].chipId;
    49.                 break;
    50.             }
    51.         }
    52.     } while (0);

    53.     return chipId;
    54. }
    复制代码
    至此,超级下载算法开发笔记(2)之识别当前i.MXRT型号痞子衡便介绍完毕了,掌声在哪里~~

    签到
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 1344 天

    [LV.10]以坛为家III

    5

    主题

    2696

    帖子

    23

    金豆

    金牌会员

    Rank: 6Rank: 6

    积分
    6163
    最后登录
    2021-2-27
    发表于 4 天前 | 显示全部楼层
    收藏+顶一下
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2021-2-27 20:32 , Processed in 0.090309 second(s), 17 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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