痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记番外(1) – JLinkScript妙用


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是超级下载算法开发笔记番外篇之JLinkScript妙用

  JLinkScript 文件是配套 J-Link 调试器使用的脚本,这个脚本适用于需要定制 J-Link 执行操作的场景,它可以帮助用户完成 J-Link 标准工具做不到的一些事情(比如 J-Link 连接顺序或者执行复位的方式,或者一些定制的硬件板需要一些特殊处理),关于 JLinkScript 文件详细解释参见痞子衡旧文 《JLink Script文件基础》

  痞子衡在开发 《RT-UFL – 一个适用全平台i.MXRT的超级下载算法设计》 项目时,遇到几个难点问题,幸好有 JLinkScript 文件帮忙才得以轻松解决,今天痞子衡就跟大家分享一下解决问题过程:

一、解决默认RAM空间分配不适的问题

  超级下载算法工程是 MIMXRT_FLEXSPI_UV5.uvprojx,基于 Keil MDK uVision5,在工程选项设置里,IROM空间是 0x1000 地址开始的 60KB(0x0 – 0xFFF空间留有它用)、IRAM 空间是 0x20000000 开始的 64KB,总空间大小是 124KB。

  在整个 i.MXRT 系列里,i.MXRT1011的内部 RAM 空间最小,但也有 128KB,大小符合超级下载算法需求。但是其默认 RAM 分配是 32KB ITCM(0x0 – 0x7FFF), 32KB DTCM(0x20000000 – 0x20007FFF), 64KB OCRAM(0x20200000 – 0x2020FFFF),这就不符合超级下载算法需求了。PS: 除了i.MXRT1011之外,其他 i.MXRT 型号默认 RAM 空间都符合算法要求。

  如何解决这个默认 RAM 空间分配不适的问题?当然是调整 FlexRAM 配置了,在《百变星君FlexRAM》 一文里,我们知道 i.MXRT1011 里有两种调整 FlexRAM 分配的方式,一种是烧写 eFuse(静态方式,一次性地,冷启动系统自动完成),另一种是改写 IOMUXC_GPR 寄存器(动态方式,可多次,软复位仍然保持有效),所以很自然地我们想到了通过 JLinkScript 文件来改写 IOMUXC_GPR 寄存器方式来达成目的,这样对芯片后续运行没有根本性影响。文件路径在 JLinkDevices.xml 里指定:

  iMXRT1011_CortexM7.JLinkScript 内容就比较简单了,按要求改写 IOMUXC_GPR16/17 即可:

void ReconfigFlexRAM()
{
    unsigned int base;
    unsigned int value;

    base = 0x400AC000;

    value = 0xFA;
    MEM_WriteU32(base + 0x44, value);
    value = MEM_ReadU32(base + 0x44);
    JLINK_SYS_Report1("GPR17:", value);

    value = MEM_ReadU32(base + 0x40);
    value |= 0x4;
    MEM_WriteU32(base + 0x40, value);
    value = MEM_ReadU32(base + 0x40);
    JLINK_SYS_Report1("GPR16:", value);

    JLINK_SYS_Report("J-Link script: FlexRAM has been reconfigured to 64KB ITCM, 64KB DTCM");
}

void SetupTarget(void) {
  ReconfigFlexRAM();
}

void AfterResetTarget(void) {
  ReconfigFlexRAM();
}
  • Note:这种方法也可以用来解决客户应用程序存在动态调整 FlexRAM 的代码导致软复位后 IDE 无法再次下载的问题,因为下载算法需要的 RAM 空间被重新分配掉了,我们需要在 JLinkScript 再将其改回来。

二、解决ROM空间不重叠带来的型号识别问题

  在 《 识别当前i.MXRT型号》 一文中,痞子衡详细描述了超级下载算法设计里是如何识别具体 i.MXRT 型号的,简单概括就是因为芯片本身没有固定地址寄存器来标明型号,因此我们用比对 ROM 空间里指定地址内容的方式来替代(每个 i.MXRT 型号 ROM 内容都不一样,且同内核型号 ROM 起始地址是一致的),文中仅用 RT600 和 RT1060 两个型号来做了示例,但在增加 i.MXRT1010 和 i.MXRT1170 两款型号支持时,我们发现这两款 ROM 可读空间竟然没有重叠。

  i.MXRT1011 的 ROM 空间是 0x200000 – 0x20FFFF(64KB),i.MXRT117x 的 ROM 空间是 0x200000 – 0x23FFFF(256KB),乍一看,这不是有重叠的嘛。但是很可惜的是,i.MXRT117x 前 64KB ROM 空间被刻意保护起来了,代码无法访问,因此比对 ROM 空间内容的方法对 i.MXRT1170 来说就失效了,必须新找其他方法来做型号识别。

  痞子衡有考虑过用读芯片外设寄存器的方式来区分 i.MXRT 型号(找有差异的那个即可),但是在 Memory Map 里找了一圈也没找到合适寄存器,因为 i.MXRT10xx 与 i.MXRT11xx 在外设寄存器地址分配上差异很大,也是几乎没有地址重叠的外设。

  无奈之下,痞子衡又想到了通过 JLinkScript 文件来在固定 RAM 地址处写标识的方式来达成目的,痞子衡选择了 0xFFFC – 0xFFFF 地址空间里的四个字节来存放标识,因此我们在超级下载算法工程选项设置里将这个地址先留出来:

  然后对超级下载算法源代码里 ufl_get_imxrt_chip_id() 函数做一点小改动,这里我们用了 0x5AA60FF0 来标识 I.MXRT1170,实测是可行的,当然如果觉得不放心,可以将标识空间再拓大一些,标识符也相应长一些。

#define FP_FLAG_ADDR     (0x0000FFFCu)
#define FP_FLAG_RT117X   (0x5AA60FF0u)

rt_chip_id_t ufl_get_imxrt_chip_id(void)
{
    rt_chip_id_t chipId = kChipId_Invalid;
    core_type_t coreType;

    coreType = ufl_get_core_type();
    if (kCoreType_CM7 == coreType)
    {
        uint32_t rt117xFlag = *(uint32_t *)FP_FLAG_ADDR;
        if (rt117xFlag == FP_FLAG_RT117X)
        {
            return kChipId_RT117x;
        }
        else 
        {
            // 代码省略...
        }
    }
    else if (kCoreType_CM33 == coreType)
    {}

    // 代码省略...

  与第一小节一样,在 JLinkDevices.xml 里指定好 JLinkScript 文件路径,然后 iMXRT117x_CortexM7.JLinkScript 内容也比较简单,按要求将标识符写进 RAM 里即可:

void SetFlagInITCM()
{
    MEM_WriteU32(0xFFFC, 0x5AA60FF0);

    JLINK_SYS_Report("J-Link script: 0x5AA60FF0 has been written to address 0xFFFC");
}

void SetupTarget(void) {
  SetFlagInITCM();
}

void AfterResetTarget(void) {
  SetFlagInITCM();
}
  • Note:标识符似乎不能放在 0x0 – 0xFFF 空间里,这个空间在当前超级下载算法设计里被 JLink 占用了,痞子衡测试了 0x0 – 0x3 和 0xFFC – 0xFFF 两处空间地址,均失败了。

  至此,超级下载算法开发笔记番外篇之JLinkScript妙用痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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