大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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:

// 适用i.MXRT500/600/1015/1020/1050
typedef struct
{
void (*runBootloader)(void *arg);
uint32_t version;
const char *copyright;
// 省略
} bootloader_api_entry_t; // 适用i.MXRT1010/1060/1064/1170
typedef struct
{
const uint32_t version;
const char *copyright;
void (*runBootloader)(void *arg);
// 省略
} bootloader_api_entry_t;

  关于这个runBootloader API函数可在参考手册中找到相关解释,从文档中来看,这个函数的作用主要有两个:一、IAP后直接去启动新更新的App;二、重新进ROM串行下载模式去更新App。这第二个功能不正是我们要的效果吗,让我们试一试。

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

// 适用i.MXRT500
#define g_bootloaderTree ((bootloader_api_entry_t *)0x0302f000)
// 适用i.MXRT600
#define g_bootloaderTree ((bootloader_api_entry_t *)0x0303f000)
// 适用i.MXRT1010/1015/1020/1050/1060/1064/1170
#define g_bootloaderTree (*(bootloader_api_entry_t **)0x0020001c) void runBootloader(void* arg)
{
g_bootloaderTree->runBootloader(arg);
}

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

// 适用i.MXRTxxx
uint32_t arg = 0xeb130000;
// 适用i.MXRT1xxx
uint32_t arg = 0xeb100000; // 进入ROM USB下载模式
runBootloader(&arg);

  下图是i.MXRT500中arg位定义,进入USB下载模式参数值应是0xeb130000:

  下图是i.MXRT1060中arg位定义,进入USB下载模式参数值应是0xeb100000或0xeb110000:

  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()实现

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

void bootloader_user_entry(void *arg)
{
SET_USER_APP_BOOT_OPTIONS(*(uint32_t *)arg); NVIC_SystemReset();
}

附2、i.MXRT1060 BootROM中run_bootloader()实现

enum
{
kEnterBootloader_Tag = 0xEB,
kEnterBootloader_Mode_Default = 0,
kEnterBootloader_Mode_SerialDownloader = 1, kEnterBootloader_SerialInterface_Auto = 0,
kEnterBootloader_SerialInterface_USB = 1,
kEnterBootloader_SerialInterface_UART = 2, kEnterBootloader_ImageIndex_Max = 3,
}; typedef union
{
struct
{
uint32_t imageIndex:4;
uint32_t reserved:12;
uint32_t serialBootInterface:4;
uint32_t bootMode:4;
uint32_t tag:8;
}B;
uint32_t U;
}run_bootloader_ctx_t; void run_bootloader(void *arg)
{
const run_bootloader_ctx_t *ctx = (const run_bootloader_ctx_t*)arg;
if (ctx->B.tag != kEnterBootloader_Tag)
{
break;
}
if (ctx->B.bootMode > kEnterBootloader_Mode_SerialDownloader)
{
break;
}
if (ctx->B.imageIndex > kEnterBootloader_ImageIndex_Max)
{
break;
} SRC->GPR[3] = ctx->U; __DSB();
__ISB(); NVIC_SystemReset();
}

  至此,i.MXRT下在App中利用ROM API进ISP/SDP模式的方法痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法的更多相关文章

  1. 痞子衡嵌入式:其实i.MXRT下改造FlexSPI driver同样支持AHB方式去写入NOR Flash

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下改造FlexSPI driver以AHB方式去写入NOR Flash. 痞子衡前段时间写过一篇 <串行NAND Fl ...

  2. 痞子衡嵌入式:在i.MXRT启动头FDCB里调整Flash工作频率也需同步设Dummy Cycle

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是Flash工作频率与Dummy Cycle的联系. 上一篇文章 <从头开始认识i.MXRT启动头FDCB里的lookupTable ...

  3. 痞子衡嵌入式:在i.MXRT启动头FDCB里使能串行NOR Flash的DTR模式

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在FDCB里使能串行NOR Flash的DTR模式. 前两篇文章 <IS25WP系列Dummy Cycle设置> 与 < ...

  4. 痞子衡嵌入式:关于i.MXRT中FlexSPI外设lookupTable里配置Normal read的一个小误区

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT中FlexSPI外设lookupTable里配置Normal read的一个小误区. 关于串行四线NOR Flash,当其作 ...

  5. 痞子衡嵌入式:在i.MXRT启动头FDCB里使能串行NOR Flash的Continuous read模式

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在FDCB里使能串行NOR Flash的Continuous read模式. 前面关于串行Flash传输时序的文章 <Fast R ...

  6. 痞子衡嵌入式:对比i.MXRT与LPC在RTC外设GPREG寄存器使用上的异同

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是对比i.MXRT与LPC在RTC外设GPREG寄存器使用上的异同. 本篇是 <在SBL项目实战中妙用i.MXRT1xxx里Syst ...

  7. 痞子衡嵌入式:介绍i.MXRT定时器PIT的多通道链接模式及其在coremark测试工程里的应用

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT定时器PIT的多通道链接模式及其在coremark测试里的应用. 早在 2018 年 i.MXRT 系列跨界处理器刚推出的时 ...

  8. 痞子衡嵌入式:在i.MXRT启动头FDCB里使能串行NOR Flash的QPI/OPI模式

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在FDCB里使能串行NOR Flash的QPI/OPI模式. 我们知道 Flash 读时序里有五大子序列 CMD + ADDR + MO ...

  9. 痞子衡嵌入式:理解i.MXRT中FlexSPI外设lookupTable里配置访问行列混合寻址Memory的参数值

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT中FlexSPI外设lookupTable里配置访问行列混合寻址Memory的参数值. 关于 FlexSPI 外设的 loo ...

随机推荐

  1. 一张图就可以完美解决Java面试频次最高、GG最高的题目!快点收藏

    如果要问Java面试频次最高的题目,那么我想应该是HashMap相关了. 提到HahMap,必然会问到是否线程安全?然后牵扯出ConcurrentHashMap等,接着提及1.7和1.8实现上的区分, ...

  2. win7下建立docker共享文件夹

    前言 建立本机(win7)和VirtualBox中docker虚拟机的共享文件夹,注:下面的命令都是以root身份运行的,使用sudo -i切换到root身份,如无法切换,请自行在命令前加上sudo命 ...

  3. 9.CSMA_CD协议

    先听再说,边听边说 载波监听多点接入/碰撞检测CSMA/CD( carrier sense multiple access with collision detection) CD:碰撞检测(冲突检测 ...

  4. 字符串学习总结(Hash & Manacher & KMP)

    前言 终于开始学习新的东西了,总结一下字符串的一些知识. NO.1 字符串哈希(Hash) 定义 即将一个字符串转化成一个整数,并保证字符串不同,得到的哈希值不同,这样就可以用来判断一个该字串是否重复 ...

  5. 软件测试面试题,十年HR面试经验分享

    WeChat[代码小姐],快和我们一起进大厂,挑战高薪吧. 问:你在测试中发现了一个  bug ,但是开发经理认为这不是一个  bug ,你应该怎样解决. 1.将问题提交到缺陷管理库里面进行备案.2. ...

  6. spring-cloud-alibaba-sentinel和feign配合使用,启动报Caused by: java.lang.AbstractMethodError: com.alibaba.cloud.sentinel.feign.SentinelContractHolder.parseAndValidateMetadata(Ljava/lang/Class;)Ljava/util/List

    背景 我在学习spring-cloud-alibaba技术栈期间,在学习服务熔断与限流的时候,服务启动发生了以下异常 #这是控制台最上面的 sun.misc.Unsafe.park(Native Me ...

  7. WebApiClientCore简约调用百度AI接口

    WebApiClientCore WebApiClient.JIT/AOT的netcore版本,集高性能高可扩展性于一体的声明式http客户端库,特别适用于微服务的restful资源请求,也适用于各种 ...

  8. DJANGO-天天生鲜项目从0到1-014-订单-订单评论

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  9. Dcoker docker: Error starting userland proxy: Bind for 0.0.0.0:80: unexpected error (Failure EADDRINUSE).

    https://stackoverflow.com/questions/46533482/error-starting-userland-proxy-bind-for-0-0-0-080-unexpe ...

  10. laravel开发调试工具laravel-debugbar的安装

    一.使用 Composer 安装该扩展包 composer require barryvdh/laravel-debugbar --dev 二.(可选)修改配置文件app/config.php Lar ...