二、双核应用开发 · 初识
1. 双核简介
结合芯片手册以及芯片白皮书,我们在MCXN94x的框图中可以看到,MCXN94x采用的双Cortex-M33核,分为主核和辅助核,主核具备如下特性:
• TrustZone技术
• 内存保护单元
• SIMD功能
• 安全仲裁单元(SAU)
• 协处理器接口
• 单精度浮点运算单元
• Arm V8指令,包括DSP指令
从核是基础型,功耗优化的处理单元,适合执行不涉及信息安全或高速计算功能的简单处理任务,它不支持主核的TrustZone、 MPU、 FPU、 SIMD、 ETM、 SAU、协处理器接口及扩展DSP指令。
由于我之前并没有接触过双核MCU的开发,首先还是从官方例程中简单了解一下双核之间交互
2. 双核Helloworld Demo
在前面点灯时我们下载的SDK中,找到如下路径的双核Demo工程:
这是一个双核MCU打印helloworld+点灯的例程,可以看到分为了两个核的工程,首先我们打开“cm33_core0”的工程文件,路径“.\SDK_2_16_100_MCXN947\boards\mcxn9xxevk\multicore_examples\hello_world\cm33_core0”
打开工程后,打开“source/hello_world_core0.c”文件:
在main.c中可以看到主核和从核的一些操作以及串口打印等,内容我们待会分析,现在先编译一下,会发现如下问题:
编译提示找不到“core1_image.bin”,既然我们编译的时core0的工程,提示找不到core1的镜像,不如我们打开cm33_core1的工程编译一下:
编译之后我们可以看到输出文件里已经出现了刚才在core0中编译提示的缺失文件“core1_image.bin”:
接下来我们回到core0工程,重新编译,发现已经编译成功,接下来配置一下Linker并勾选自动复位运行,然后烧录程序:
下载完成后可以在1-2s后看到红灯闪烁(首次下载完成后似乎勾选的自动复位运行并不起效果,需要手动按下中间的复位按键进行复位或重新上电,留坑待查),至于我们如何查看串口收发引脚,我们在开发板原理图中可能找到明显标识,需要打开Data Sheet,找到Pin的说明部分:
另外在代码中配置串口初始化的部分也可以找到:
上述可以确定打印串口采用的为FLEXCOMM4,而FLEXCOMM4引脚配置为P1_9为TX,P1_8为RX;在连接上串口之后,重新运行程序,可以看到如下日志信息,并且LED灯开始闪烁:
接下来结合现象去分析源码部分
3. 源码分析
1)主核源码
在这个双核例程中,主核工程的main函数分为三部分,分别是初始化部分、拷贝辅助核Core1镜像到RAM中,然后启动Core1并等待启动完成,最后进入for死循环,期间插入了一些打印函数:
可以看到最后调用MCMGR_StartCore函数开启辅助核(次核):
(void)MCMGR_StartCore(kMCMGR_Core1, (void *)(char *)CORE1_BOOT_ADDRESS, 2, kMCMGR_Start_Synchronous);
进入这个MCMGR_StartCore函数可以看到系统会一直等待直到次核开始运行:
从mcmgr_start_core_internal函数可以看到启动方式是控制CPUCTRL寄存器,配置为SYSCON_CPUCTRL_CPU1RSTEN_MASK(Reset使能)以及SYSCON_CPUCTRL_CPU1CLKEN_MASK(时钟使能)
这两个寄存器在Reference Manual中可以看到说明:
2)辅助核源码
辅助核系统初始化后,进行多核管理器的相关初始化,载入启动数据启动完成后,执行应用功能部分(LED灯光闪烁):
这里比较关键的是多核管理器MCMGR初始化部分,我们进入MCMGR_Init函数,可以看到首先注册一些Event(注册回调函数),然后执行mcmgr_late_init_internal函数:
进入mcmgr_late_init_internal函数内,可以看到执行了一些中断打开动作,然后通过一个邮箱通知主核:
这一点的在核间通信手册中也可以看到邮箱在双核之间通信的示例,手册还有使用互斥锁+邮箱等进行通信的示例,这里不一一列举,大家自行查看:
然后系统的双核就分别各自启动运行了,Demo例程中主核启动后进入for死循环,辅助核执行LED Blink,对于多核管理器MCMGR,我也只是通过代码以及片面的手册简单理解,我们可以在官网查找相关资料了解更详细的启动过程以及实现方法,或者参考其他大神使用其他芯片时对于MCMGR源码的讲解。