zoukankan      html  css  js  c++  java
  • 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(2)


      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是超级下载算法开发笔记(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型号痞子衡便介绍完毕了,掌声在哪里~~~

    欢迎订阅

    文章会同时发布到我的 博客园主页CSDN主页知乎主页微信公众号 平台上。

    微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

  • 相关阅读:
    shell进行mysql统计
    java I/O总结
    Hbase源码分析:Hbase UI中Requests Per Second的具体含义
    ASP.NET Session State Overview
    What is an ISAPI Extension?
    innerxml and outerxml
    postman
    FileZilla文件下载的目录
    how to use webpart container in kentico
    Consider using EXISTS instead of IN
  • 原文地址:https://www.cnblogs.com/henjay724/p/13971756.html
Copyright © 2011-2022 走看看