查看: 1981|回复: 1

[分享] 一种i.MXRT下从App中进入ROM串行下载模式的方法

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

    [LV.8]以坛为家I

    3300

    主题

    6547

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32030
    最后登录
    2024-4-26
    发表于 2020-8-11 10:41:21 | 显示全部楼层 |阅读模式
    一种i.MXRT下从App中进入ROM串行下载模式的方法


    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法。


    我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRTxxx系列和CM7内核的i.MXRT1xxx系列,但是这两个阵营都有一个共性,那就是都没有内部非易失性存储器(NVM)并且BootROM里都集成了串行下载功能。


    串行下载功能即BootROM中实现了通过串行接口(UART/USB...)与上位机通讯,将客户App数据烧录进外部启动设备中,这个功能主要用于量产,但在实际应用过程中,通过首推的启动引脚(ISP[2:0] / BT_MODE[1:0])配置进入串行下载模式的方式有时候不方便,因为引脚状态不方便切换,本文痞子衡将给大家介绍一种不需要切换启动引脚进入串行下载模式的方法。


    一、配置启动引脚进串行下载模式
    痞子衡很早前写过两篇文章,详细介绍了 《i.MXRTxxx的串行下载模式(ISP)》、《i.MXRT1xxx的串行下载模式(SDP)》,此处再简单回顾一下。


    1.1 i.MXRTxxx之ISP
    i.MXRTxxx系列用于配置进入串行下载模式的启动引脚有3个,即ISP[2:0],这三个引脚在系统软复位后由BootROM直接进行软采样,BootROM根据ISP[2:0]值判断是否进入串行下载模式,串行接口支持UART/SPI/USB-HID三种,烧录算法是直接集成在BootROM中的,可以直接烧录App。


    1.2 i.MXRT1xxx之SDP
    i.MXRT1xxx系列用于配置进入串行下载模式的启动引脚有2个,即BT_MODE[2:0],这两个引脚仅在系统POR复位时由系统硬采样保存到非易失性寄存器SRC->SBMR2中,BootROM从SRC->SBMR2寄存器中获取BT_MODE[2:0]值判断是否进入串行下载模式,串行接口支持UART/USB-HID两种,因为BootROM中没有集成烧录算法,所以需要加载一个专用的Flashloader来烧录App。


    二、切换启动引脚带来的不便
    在恩智浦官方i.MXRT开发板设计上,外部启动引脚是连接的拨码开关,因此我们可以通过切换拨码开关并复位的方式来进入ROM串行下载模式,但实际应用场景下,客户板卡并不会留有拨码开关,更多的是用上下拉电阻的方式确定启动模式,而且默认设置的启动模式是从Flash启动。


    当客户板卡首次上电,且连接的启动Flash是空白时,即使启动模式设置的是从Flash启动,但由于Flash里并没有App,因此BootROM在启动App失败后还是会自动进入串行下载模式,这意味着至少可以进一次串行下载模式。当成功使用串行下载模式将App烧录进启动Flash之后,再次上电,此时板卡便会从ROM跳转到App执行,这种情况下,除非改变启动引脚输入状态,不然永远不会再次进入串行下载模式。而在客户板卡上改变启动引脚状态便意味着要重新焊接板子,改变启动引脚的上下拉电阻,这当然很不方便。


    三、借助ROM API进入串行下载模式
    那么有没有不改变启动引脚状态就进入ROM串行下载模式的方法呢?答案当然是有。痞子衡之前写过一篇文章 《了解i.MXRTxxx系列ROM API及其与i.MXRT1xxx系列的差异》,把i.MXRT全系列ROM API都捋了一遍。如果你足够细心会发现它们都有一个共同的API,名字叫runBootloader:

    1. // 适用i.MXRT500/600/1015/1020/1050
    2. typedef struct
    3. {
    4.     void (*runBootloader)(void *arg);
    5.     uint32_t version;
    6.     const char *copyright;
    7.     // 省略
    8. } bootloader_api_entry_t;


    9. // 适用i.MXRT1010/1060/1064/1170
    10. typedef struct
    11. {
    12.     const uint32_t version;
    13.     const char *copyright;
    14.     void (*runBootloader)(void *arg);
    15.     // 省略
    16. } bootloader_api_entry_t;
    复制代码
    关于这个runBootloader API函数可在参考手册中找到相关解释,从文档中来看,这个函数的作用主要有两个:一、IAP后直接去启动新更新的App;二、重新进ROM串行下载模式去更新App。这第二个功能不正是我们要的效果吗,让我们试一试。


    根据前面介绍的ROM API知识,让我们在App中把runBootloader函数重定义一下,runBootloader函数原型与API中原型保持一致,其函数实现就直接调用API:

    1. // 适用i.MXRT500
    2. #define g_bootloaderTree ((bootloader_api_entry_t *)0x0302f000)
    3. // 适用i.MXRT600
    4. #define g_bootloaderTree ((bootloader_api_entry_t *)0x0303f000)
    5. // 适用i.MXRT1010/1015/1020/1050/1060/1064/1170
    6. #define g_bootloaderTree (*(bootloader_api_entry_t **)0x0020001c)

    7. void runBootloader(void* arg)
    8. {
    9.     g_bootloaderTree->runBootloader(arg);
    10. }
    复制代码
    App中有了runBootloader函数,下一步就是传参调用。先说调用,其实这里就相当于切换启动引脚操作了,因为我们不想切换启动引脚,所以我们需要在App中插入一段runBootloader函数调用代码,并且需要为它设计一个专用的触发方式(比如可以是某个引脚中断,也可以是串口收到某个命令等等,这里客户自由发挥)。解决了调用问题,下一步就是传什么参数,参考手册里有详细的参数各bit定义,下面是进入USB下载模式的示例代码:

    1. // 适用i.MXRTxxx
    2. uint32_t arg = 0xeb130000;
    3. // 适用i.MXRT1xxx
    4. uint32_t arg = 0xeb100000;

    5. // 进入ROM USB下载模式
    6. runBootloader(&arg);
    复制代码
    下图是i.MXRT500中arg位定义,进入USB下载模式参数值应是0xeb130000:
    1.png
    下图是i.MXRT1060中arg位定义,进入USB下载模式参数值应是0xeb100000或0xeb110000:
    2.png
    runBootloader(&arg)函数执行完之后,此时在USB OTG1口上插上USB线应该可以看到电脑设备上重新枚举了HID设备,然后就可以使用配套上位机工具(比如MCUBootUtility)进行App更新下载了。


    四、附录
    附录收录了i.MXRT两大阵营代表型号的ROM API中runBootloader具体实现,其中i.MXRTxxx系列对应实例是bootloader_user_entry()函数,i.MXRT1xxx系列对应实例是run_bootloader()函数,这两个函数的核心思想都是在芯片某个非易失性(软复位不置位)的寄存器中将用户传入的参数值保存下来,然后调用NVIC软复位函数重新进入BootROM,由BootROM来处理用户传入的参数:


    附1、i.MXRT500 BootROM中bootloader_user_entry()实现

    1. #define SET_USER_APP_BOOT_OPTIONS(val) ((*(volatile uint32_t *)(SYSCTL0_BASE + 0x384)) = val)

    2. void bootloader_user_entry(void *arg)
    3. {
    4.     SET_USER_APP_BOOT_OPTIONS(*(uint32_t *)arg);

    5.     NVIC_SystemReset();
    6. }
    复制代码
    附2、i.MXRT1060 BootROM中run_bootloader()实现
    1. enum
    2. {
    3.     kEnterBootloader_Tag = 0xEB,
    4.     kEnterBootloader_Mode_Default = 0,
    5.     kEnterBootloader_Mode_SerialDownloader = 1,

    6.     kEnterBootloader_SerialInterface_Auto = 0,
    7.     kEnterBootloader_SerialInterface_USB = 1,
    8.     kEnterBootloader_SerialInterface_UART = 2,

    9.     kEnterBootloader_ImageIndex_Max = 3,
    10. };

    11. typedef union
    12. {
    13.     struct
    14.     {
    15.         uint32_t imageIndex:4;
    16.         uint32_t reserved:12;
    17.         uint32_t serialBootInterface:4;
    18.         uint32_t bootMode:4;
    19.         uint32_t tag:8;
    20.     }B;
    21.     uint32_t U;
    22. }run_bootloader_ctx_t;

    23. void run_bootloader(void *arg)
    24. {
    25.     const run_bootloader_ctx_t *ctx = (const run_bootloader_ctx_t*)arg;
    26.         if (ctx->B.tag != kEnterBootloader_Tag)
    27.         {
    28.                 break;
    29.         }
    30.         if (ctx->B.bootMode > kEnterBootloader_Mode_SerialDownloader)
    31.         {
    32.                 break;
    33.         }
    34.         if (ctx->B.imageIndex > kEnterBootloader_ImageIndex_Max)
    35.         {
    36.                 break;
    37.         }

    38.         SRC->GPR[3] = ctx->U;

    39.         __DSB();
    40.         __ISB();

    41.         NVIC_SystemReset();
    42. }
    复制代码
    至此,i.MXRT下在App中利用ROM API进ISP/SDP模式的方法痞子衡便介绍完毕了,掌声在哪里~~~


    文章出处:痞子衡嵌入式

    签到签到
    回复

    使用道具 举报

  • TA的每日心情

    2021-1-22 17:33
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    30

    主题

    85

    帖子

    0

    高级会员

    Rank: 4

    积分
    640
    最后登录
    2023-12-12
    发表于 2020-8-20 14:17:54 | 显示全部楼层
    rt1052进入USB下载模式参数值应该是多少,参考手册也没有的,按照上面的方法,没进入到usb下载模式,信息倒是打印出来了。 1.png 打印版本号等信息:
    3.png
    打印结果
    2.png
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-4-26 15:45 , Processed in 0.121334 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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