痞子衡嵌入式:大话双核i.MXRT1170之Cortex-M7与Cortex-M4互相激活之道
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M7与Cortex-M4内核互相激活的方法。
痞子衡最近在深耕i.MXRT1170这颗划时代的MCU,已经写了不少篇相关技术文章,涉及整体特点、Raw NAND启动、FlexRAM模块、ECC特性等,文章写得越多越发觉得i.MXRT1170是座宝矿,值得大家去仔细探索。话不多说,咱们继续挖矿吧,今天痞子衡为大家介绍i.MXRT1170双核间互相激活的方法。
一、双核功能简介
双核是i.MXRT1170除了1GHz主频之外的第二个显著特点,i.MX RT系列也是从RT1170开始首次引入了双核架构。i.MXRT1170包含了一个Cortex-M7内核(1GHz)以及一个Cortex-M4内核(400MHz),超强的Cortex-M7内核专注于音视频识别与处理、千兆以太网通讯控制等复杂任务上;低功耗Cortex-M4内核则做一些相对简单的键盘响应、传感器采集、电机控制等任务,即如下图所示:
二、双核激活方法
i.MXRT1170虽然是双核(Cortex-M7与Cortex-M4),但这两个核并没有确定的主从关系,i.MXRT1170系统设计里每个核都既可以当主核也可以当从核(默认CM7是主核,CM4是从核),用户设置了主从关系之后,芯片上电后先从主核启动,然后由主核来激活从核启动。
2.1 选定主核
主核是在eFuse中选定的,fusemap中0x960[13:12]对应的是BT_CORE_CTRL和BT_CORE_SEL bit,默认两个bit都是0,即从CM7是主核,上电CM7启动,如果需要更改主核为CM4,则需要烧写eFuse。
这里顺便插一句,我们知道芯片上电都是先执行BootROM代码,既然CM7和CM4都可以当主核,那么这个BootROM代码需要既可以在CM4下执行,也可以在CM7下执行。这里借助的是Cortex-M处理器向下兼容、软件二进制向上兼容的特性,BootROM代码使用Cortex-M4指令集去编译即可。
2.2 加载从核App(可选)
选定了主核之后,主核App由BootROM加载执行,我们需要在主核App里添加代码来启动从核。启动从核的第一步是加载从核App,App从加载执行位置上可分为两种,一种是在Flash里原地执行,另一个是拷贝到RAM里执行,只有后者才需要先加载再执行。
关于从核App执行位置,这里有必要好好聊一下,下面是CM7和CM4下各自系统内存映射表,从表里可以看到除了各自内核TCM空间仅对自己可见外,其余地址空间对两个核均是可见的(并且映射地址也是相同的)。如果加载的从核App是在TCM里执行的,主核需要将从核App加载到从核TCM对应的OCRAM空间(此种情况仅适用CM4当从核,其TCM对应的是OCRAM(M4)空间;CM7当从核时其TCM对应的空间CM4是无法访问的);如果加载的从核App不是在TCM里执行的,那么情况就比较简单,直接加载到那个目标映射地址空间即可。


下面是加载从核App示例代码,appBuffer是从核App Image在外部Flash里存放的首地址,vectorAddr是加载的目标RAM首地址。为了防止Cache干扰后续从核取复位向量执行,主核在加载App前后最好均要清一下DCache。
void copy_app_image(uint8_t *appBuffer, uint32_t appLength, uint32_t vectorAddr)
{
#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_CleanInvalidateDCache_by_Addr((void *)vectorAddr, appLength);
#endif
/* Copy app image to dest addrress. */
memcpy((void *)vectorAddr, appBuffer, appLength);
#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_CleanInvalidateDCache_by_Addr((void *)vectorAddr, appLength);
#endif
}
2.3 指定从核初始中断向量表地址
加载从核App完成之后,接下来便是设置从核启动所需的中断向量表位置,从核需要从中断向量表里取出初始栈地址(SP)和复位向量(PC)来执行。
CM7启动初始向量表地址设置在IOMUXC_LPSR_GPR26里(对应SCB->VTOR[31:7]),CM4启动初始向量表地址设置在IOMUXC_LPSR_GPR0/1里(对应SCB->VTOR[31:3])。
- Note: A0版本芯片CM7启动初始向量表设置在IOMUXC_GPR19里;B0版本芯片CM7启动初始向量表设置改到了IOMUXC_LPSR_GPR26里。

下面是设置从核启动初始中断向量表地址的示例代码:
void set_cm4_vector(uint32_t vectorAddr)
{
IOMUXC_LPSR_GPR->GPR0 = IOMUXC_LPSR_GPR_GPR0_CM4_INIT_VTOR_LOW(vectorAddr);
IOMUXC_LPSR_GPR->GPR1 = IOMUXC_LPSR_GPR_GPR1_CM4_INIT_VTOR_HIGH(vectorAddr >> 16);
}
void set_cm7_vector(uint32_t vectorAddr)
{
IOMUXC_LPSR_GPR->GPR26 = IOMUXC_LPSR_GPR_GPR26_CM7_INIT_VTOR(vectorAddr);
}
2.4 激活从核
此时从核已经摩拳擦掌,等待来自主核的最后激活指令了。激活控制是在SRC->SCR寄存器里实现的,将BT_RELEASE_Mx位置1即可启动CMx从核。这里需要注意一点,如果是在调试,从核有可能已经被调试器的脚本激活过了,那么此时仅需要reset一下从核即可。

下面是激活从核启动的示例代码:
void launch_cm4_core(void)
{
/* If CM4 is already running (released by debugger), then reset the CM4.
If CM4 is not running, release it. */
if ((SRC->SCR & SRC_SCR_BT_RELEASE_M4_MASK) != 0)
{
SRC->CTRL_M4CORE |= SRC_SLICE_CTRL_SW_RESET_MASK;
while ((SRC->STAT_M4CORE & SRC_SLICE_STAT_UNDER_RST_MASK) != 0UL);
}
else
{
SRC->SCR |= SRC_SCR_BT_RELEASE_M4_MASK;
}
}
void launch_cm7_core(void)
{
/* If CM7 is already running (released by debugger), then reset the CM7.
If CM7 is not running, release it. */
if ((SRC->SCR & SRC_SCR_BT_RELEASE_M7_MASK) != 0)
{
SRC->CTRL_M7CORE |= SRC_SLICE_CTRL_SW_RESET_MASK;
while ((SRC->STAT_M7CORE & SRC_SLICE_STAT_UNDER_RST_MASK) != 0UL);
}
else
{
SRC->SCR |= SRC_SCR_BT_RELEASE_M7_MASK;
}
}
三、一个典型示例
最后给一个完整示例,主核是CM7,从核是CM4,从核App代码存储在0x60010000地址,App长度是32KB,从核APP是从ITCM起始地址(0x1FFE0000)开始链接的。CM7激活CM4完整代码如下:
#define CM4_BUF_START 0x60010000U
#define CM4_BUF_LEN 0x8000U
#define CM4_CPY_START 0x20200000U
#define CM4_APP_START 0x1FFE0000U
int main(void)
{
copy_app_image(CM4_BUF_START, CM4_BUF_LEN, CM4_CPY_START);
set_cm4_vector(CM4_APP_START);
launch_cm4_core();
while (1)
{
}
}
至此,恩智浦i.MXRT1170上Cortex-M7与Cortex-M4内核互相激活的方法痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:大话双核i.MXRT1170之Cortex-M7与Cortex-M4互相激活之道的更多相关文章
- 痞子衡嵌入式:聊聊i.MXRT1170双核下不同GPIO组的访问以及中断设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170双核下不同GPIO组的访问以及中断设计. 在双核 i.MXRT1170 下设计应用程序,有一个比较重要的考虑点就是外 ...
- 痞子衡嵌入式:揭秘i.MXRT1170 eFuse空间访问可靠性的保护策略(冗余与ECC)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRT1170的eFuse空间访问可靠性保护策略. 关于i.MXRT系列的eFuse/OTP,痞子衡之前在介绍Boot时写过 ...
- 痞子衡嵌入式:在i.MXRT1170上启动含DQS的Octal Flash可不严格设Dummy Cycle (以MT35XU512为例)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是Octal或Hyper Flash上DQS信号与Dummy Cycle联系. 关于在 i.MXRT 上启动 NOR Flash 时如何设 ...
- 痞子衡嵌入式:揭秘i.MXRT1170上用J-Link连接复位后PC总是停在0x223104的原因
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上安全调试策略实现对JLink调试的影响. 痞子衡之前写过一篇旧文 <i.MXRT600的ISP模式下用J-L ...
- 痞子衡嵌入式:揭秘i.MXRT1170上串行NOR Flash双程序可交替启动设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上串行NOR Flash双程序可交替启动设计. 在上一篇文章 <i.MXRT1060/1010上串行NOR F ...
- 痞子衡嵌入式:大话双核i.MXRT1170之单独在线调试从核工程的方法(IAR篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170下单独在线调试从核工程的方法(基于IAR). 两年前痞子衡写过一篇<双核i.MXRT1170之Cortex-M ...
- 痞子衡嵌入式:大话双核i.MXRT1170之在线联合调试双核工程的三种方法(IAR篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170下在线联合调试双核工程的方法(基于IAR). 前段时间痞子衡写过一篇<双核i.MXRT1170之单独在线调试从 ...
- 痞子衡嵌入式:简析i.MXRT1170 Cortex-M7 FlexRAM ECC功能特点、开启步骤、性能影响
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M7内核的FlexRAM ECC功能. ECC是"Error Correcting ...
- 痞子衡嵌入式:简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M4内核的L-MEM ECC功能. 本篇是 <简析i.MXRT1170 Cortex-M ...
随机推荐
- 访问修饰符public,private,protected,以及不写(默认)时的区别?
private: 1.在当前类开发中,main方法之外可以直接借助名字使用,当前类的main方法中可以使用对象打点的方式直接使用成员. 2.在当前类之外,使用对象(或是类名,针对静态的)打点调用都是被 ...
- SQL实战(二)
一. 获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'.结果第一列给出当前员工的emp_no,第二列给出其manager ...
- RbbitMQ详解
高性能消息队列RabbitMQ 1.为什么要使用mq 主要解决应用解耦,流量削峰,异步消息,实现高性能,可升缩,最终一致性的架构. 2.activeMq的通讯模式 基于队列(点对点)与发布订阅(有多个 ...
- ArrayList源码浅析
这里只理解主要的常用方法: 1 public class ArrayList<E> extends AbstractList<E> 2 implements List<E ...
- GO gRPC教程-环境安装(一)
前言 gRPC 是一个高性能.开源和通用的 RPC 框架,面向移动和 HTTP/2 设计,带来诸如双向流.流控.头部压缩.单 TCP 连接上的多复用请求等特.这些特性使得其在移动设备上表现更好,更省电 ...
- 一文教会你如何在 Spring 中进行集成测试,太赞了
不得不说,测试真的是太重要了!但并不是所有的开发者都这样认为,这种感觉在我回到洛阳后尤其强烈.竟然有团队成员不经测试就把代码提交到代码库,并且是会报错的那种,我天呐,遇到这种队友我也是醉了. 我之前是 ...
- 构建LNMP
构建LNMP 案例1:部署LNMP环境 案例2:构建L ...
- MTK Android ListPreference的用法
首先,我们明确,preference是和数据存储相关的. 其次,它能帮助我们方便的进行数据存储!为什么这个地方一定要强调下方便的这个词呢?原因是,我们可以根本就不使用,我们有另外的N种办法可以实现同样 ...
- 2017蓝桥杯九宫幻方(C++B组)
题目:九宫幻方 小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行.每一列和每一条对角线的和都是相同的. ...
- Array(数组)对象-->sort() 方法
1.定义和用法 sort() 方法用于对数组的元素进行排序. 默认排序顺序为按字母升序. 语法: array.sort(sortfunction) 参数: sortfunction:规定排序顺序.必须 ...