本篇是开发笔记第二篇,咱们就重点聊聊如何让超级下载算法知道当前跑在哪个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系列的家族分类特性展示得淋漓尽致。

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

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]直接就是系列号的值。

二、确认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。

  我们可以很容易写出如下ufl_get_core_type()函数。

/* See Part number of core in Cortex-Mx Generic UG */#define CORE_ID_CM33 (0xD21)#define CORE_ID_CM7  (0xC27)typedef enum _core_type{    kCoreType_Invalid = 0U,    kCoreType_CM33    = 1U,    kCoreType_CM7     = 2U,} core_type_t;static core_type_t ufl_get_core_type(void){    core_type_t coreType = kCoreType_Invalid;    uint32_t coreid = (SCB->CPUID & SCB_CPUID_PARTNO_Msk) >> SCB_CPUID_PARTNO_Pos;    switch (coreid)    {        case CORE_ID_CM33:            coreType = kCoreType_CM33;            break;        case CORE_ID_CM7:            coreType = kCoreType_CM7;            break;        default:            break;    }    return coreType;}

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处的四字节数据来定位,如后期随着型号的增多,出现定位位置处数据全部雷同的巧合的话,可以更改定位位置保证定位数据一定不相同。

typedef enum _rt_chip_id{    kChipId_Invalid = 0xFFU,    kChipId_RT6xx   = 1U,    kChipId_RT106x  = 2U,} rt_chip_id_t;#define RT_ROM_BASE_CM33 (0x03000000u)#define RT_ROM_BASE_CM7  (0x00200000u)#define ROM_FP_OFFSET1 (0x8000)#define ROM_FP_OFFSET2 (0xa000)#define ROM_FP_OFFSET3 (0xc000)typedef struct _rom_fingerprint{    uint32_t chipId;    uint32_t content[3];} rom_fingerprint_t;static const rom_fingerprint_t s_romFingerprint[] = {    {kChipId_RT6xx,  {0xb108f82a, 0x0200f2c5, 0x0070f104} },        // From ROM 2.0rc5.1    {kChipId_RT106x, {0xb0893000, 0x80dbf000, 0xf2c44100} },        // From ROM 1.0rc3};rt_chip_id_t ufl_get_imxrt_chip_id(void){    rt_chip_id_t chipId = kChipId_Invalid;    core_type_t coreType;    uint32_t rtRomBase = 0;    coreType = ufl_get_core_type();    if (kCoreType_CM33 == coreType)    {        rtRomBase = RT_ROM_BASE_CM33;    }    else if (kCoreType_CM7 == coreType)    {        rtRomBase = RT_ROM_BASE_CM7;    }    else    {}    do    {        uint32_t content[3];        content[0] = *(uint32_t *)(rtRomBase + ROM_FP_OFFSET1);        content[1] = *(uint32_t *)(rtRomBase + ROM_FP_OFFSET2);        content[2] = *(uint32_t *)(rtRomBase + ROM_FP_OFFSET3);        uint32_t idx = sizeof(s_romFingerprint) / sizeof(rom_fingerprint_t);        while (idx--)        {            if (!memcmp(s_romFingerprint[idx].content, content, sizeof(content)))            {                chipId = (rt_chip_id_t)s_romFingerprint[idx].chipId;                break;            }        }    } while (0);    return chipId;}

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


©著作权归作者所有:来自51CTO博客作者痞子衡V的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 苹果A10及以后版本芯片KTRR原理及脆弱性分析
  2. 第10部分- Linux ARM汇编 寻址方式
  3. 第9部分- Linux ARM汇编 语法
  4. 第6部分- Linux ARM汇编 指令集概要
  5. 3分钟掌握思科路由器密码破解
  6. 计算系统基础(四)
  7. Android如何找到正确的ALSA底层kcontrol接口?
  8. Android(安卓)Camera Architecture
  9. Android培训班(103)内核入口汇编3

随机推荐

  1. Android(安卓)SDK版本号和名称对应表
  2. Android中RelativeLayout布局各个xml相对
  3. Android序列化Parcelable
  4. 引入布局
  5. android之SharedPreferences
  6. Android闪光灯的打开与关闭
  7. 关于Android(安卓)Studio安装完后activit
  8. library project 和android项目
  9. Android数据缓存
  10. Android:Could not GET xxxx Received sta