肥仔教程网

SEO 优化与 Web 开发技术学习分享平台

i.MXRT1170双核CM7与CM4互相激活之道

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是恩智浦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 对应的是 OCRAM(M7)空间)。

下面是加载从核 App 示例代码,appBuffer 是从核 App Image 在外部 Flash 里存放的首地址,vectorAddr 是加载的目标 RAM 首地址。为了防止 Cache 干扰后续从核取复位向量执行,主核在加载 App 前后最好均要清一下 DCache。

 1void copy_app_image(uint8_t *appBuffer, uint32_t appLength, uint32_t vectorAddr)
 2{
 3#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
 4    SCB_CleanInvalidateDCache_by_Addr((void *)vectorAddr, appLength);
 5#endif
 6
 7    /* Copy app image to dest addrress. */
 8    memcpy((void *)vectorAddr, appBuffer, appLength);
 9
10#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
11    SCB_CleanInvalidateDCache_by_Addr((void *)vectorAddr, appLength);
12#endif
13}

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 里。

下面是设置从核启动初始中断向量表地址的示例代码:

 1void set_cm4_vector(uint32_t vectorAddr)
 2{
 3    IOMUXC_LPSR_GPR->GPR0 = IOMUXC_LPSR_GPR_GPR0_CM4_INIT_VTOR_LOW(vectorAddr);
 4    IOMUXC_LPSR_GPR->GPR1 = IOMUXC_LPSR_GPR_GPR1_CM4_INIT_VTOR_HIGH(vectorAddr >> 16);
 5}
 6
 7void set_cm7_vector(uint32_t vectorAddr)
 8{
 9    IOMUXC_LPSR_GPR->GPR26 = IOMUXC_LPSR_GPR_GPR26_CM7_INIT_VTOR(vectorAddr);
10}

2.4 激活从核

此时从核已经摩拳擦掌,等待来自主核的最后激活指令了。激活控制是在 SRC->SCR 寄存器里实现的,将 BT_RELEASE_Mx 位置 1 即可启动 CMx 从核。这里需要注意一点,如果是在调试,从核有可能已经被调试器的脚本激活过了,那么此时仅需要 reset 一下从核即可。

下面是激活从核启动的示例代码:

 1void launch_cm4_core(void)
 2{
 3    /* If CM4 is already running (released by debugger), then reset the CM4.
 4       If CM4 is not running, release it. */
 5    if ((SRC->SCR & SRC_SCR_BT_RELEASE_M4_MASK) != 0)
 6    {
 7        SRC->CTRL_M4CORE |= SRC_SLICE_CTRL_SW_RESET_MASK;
 8        while ((SRC->STAT_M4CORE & SRC_SLICE_STAT_UNDER_RST_MASK) != 0UL);
 9    }
10    else
11    {
12        SRC->SCR |= SRC_SCR_BT_RELEASE_M4_MASK;
13    }
14}
15
16void launch_cm7_core(void)
17{
18    /* If CM7 is already running (released by debugger), then reset the CM7.
19       If CM7 is not running, release it. */
20    if ((SRC->SCR & SRC_SCR_BT_RELEASE_M7_MASK) != 0)
21    {
22        SRC->CTRL_M7CORE |= SRC_SLICE_CTRL_SW_RESET_MASK;
23        while ((SRC->STAT_M7CORE & SRC_SLICE_STAT_UNDER_RST_MASK) != 0UL);
24    }
25    else
26    {
27        SRC->SCR |= SRC_SCR_BT_RELEASE_M7_MASK;
28    }
29}

三、一个典型示例

最后给一个完整示例,主核是 CM7,从核是 CM4,从核 App 代码存储在 0x60010000 地址,App 长度是 32KB,从核 APP 是从 ITCM 起始地址(0x1FFE0000)开始链接的。CM7 激活 CM4 完整代码如下:

 1#define CM4_BUF_START 0x60010000U
 2#define CM4_BUF_LEN   0x8000U
 3#define CM4_CPY_START 0x20200000U
 4#define CM4_APP_START 0x1FFE0000U
 5
 6int main(void)
 7{
 8    copy_app_image(CM4_BUF_START, CM4_BUF_LEN, CM4_CPY_START);
 9    set_cm4_vector(CM4_APP_START);
10    launch_cm4_core;
11
12    while (1)
13    {
14    }
15}

至此,恩智浦 i.MXRT1170 上 Cortex-M7 与 Cortex-M4 内核互相激活的方法痞子衡便介绍完毕了,掌声在哪里~~~

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言