本帖最后由 andeyqi 于 2020-12-2 21:35 编辑
之前的开箱帖子已经在逐飞的板子上CORE0运行起来RTT系统了,基于开箱帖子的基础上能否在CORE1上跑起来系统,很庆幸的是逐飞的开源库已经开放了双系统的demo,使用逐飞开源库的demo还是很容易运行起来双系统的。我们直接运行逐飞例程中的如下路径的demo程序。**\LPC55S69_Library\example_project\coreboard_multicore_example
该目录下包含了core0 和 core1 两个MDK工程,编译两个工程时需要注意先编译core1的工程,之后编译core0工程下载运行即可,我们先看下运行起来的效果。
系统运行起来后会输出当前运行的core ID,并开始运行time_run的task输出系统运行时间,从输出的log可以发现core1 的 计数是小于core0的计数,从而从侧面印证了之前的描述core1是通过core0来启动的说法,在core0的main函数内调用MCMGR_StartCore 接口启动core1,从而启动core1对应的程序,在调用该函数之前需要对MCMGR 组件进行初始化,core0的初始化操作在rt_hw_board_init 函数中对其进行了初始化操作。
- int main(void)
- {
- rt_kprintf("core0 running.\r\n");
- zf_gpio_default_init(PIO1, PIN12, PIN_DIR_OUT);
- (void)MCMGR_StartCore(kMCMGR_Core1, (void *)(char *)CORE1_BOOT_ADDRESS, 2, kMCMGR_Start_Synchronous);
- rt_thread_t tid;
- tid = rt_thread_create("runtime_print", print_runtime, RT_NULL, 1024, 12, 28);
- RT_ASSERT(tid != RT_NULL);
- rt_thread_startup(tid);
- while (1)
- {
- zf_gpio_output_not(PIO1, PIN12);
- delay_ms(2000);
- }
- }
复制代码
MCMGR_StartCore 接口是NXP LPCS55S69 SDK提供的接口,根据接口API描述可知cor0启动core1,CORE1的镜像地址为#define CORE1_BOOT_ADDRESS 0x00072000,根据CORE1工程的链接脚本(.\LPC55S69_cm33_core1_flash.scf)可以发现该地址对应core1代码段的中断向量表的首地址。
- /*!
- * @brief Start a selected core
- *
- * This function causes a selected core to initialize and start the code execution.
- * If the secondary core application boots from RAM, then there is a need to call the function,
- * which copies this app. Image to RAM prior this function.
- *
- * @param[in] coreNum Enum of the core to be started.
- * @param[in] bootAddress Boot address of the core to be started application.
- * @param[in] startupData Data which can be get by the other core on startup.
- * @param[in] mode Start mode, use kMCMGR_Start_Synchronous for synchronous mode (wait until the
- * core is started), kMCMGR_Start_Asynchronous for asynchronous mode (do not wait).
- *
- * @return kStatus_MCMGR_Success on success or kStatus_MCMGR_Error on failure.
- */
- mcmgr_status_t MCMGR_StartCore(mcmgr_core_t coreNum, void *bootAddress, uint32_t startupData, mcmgr_start_mode_t mode);
复制代码
我们下载的时候只是下载了core0工程的bin文件,并没有下载core1的镜像文件,core1是如何被加载的呢,实际上core0的代码中将core1生成的可执行文件core1_image.bin 作为代码段包含进工程中,所以我们只是更新了core0程序发现core1也正常的运行了,这个也是开头说的编译的时候要先编译core1工程的原因。
通过上述LPCSS55S69 SDK提供的MCMGR组件的api文件可以发现,其不除了提供核间启动/停止的功能外,还提供了核间event通信方式。
首先我们先介绍下核间通信方式1(Multicore Manager (MCMGR))--- EVENT
如下为MCMGR 双核之间交互流程:
根据mcmgr.h说明可以如下API可以发送和接受event.对于这个api的实现方式暂时还没有研究,先不管那么多先用起来看看好不好用再说,实践才是检验真理的唯一标准,先跑起来之后再研究实现原理。
- /*!
- * @brief Register event handler
- *
- * This function registers an event handler.
- * for remote processor events handling.
- *
- * @param[in] type Type of the event.
- * @param[in] callback User callback.
- * @param[in] callbackData Data/context for user callback.
- *
- * @return kStatus_MCMGR_Success on success or kStatus_MCMGR_Error on failure.
- */
- mcmgr_status_t MCMGR_RegisterEvent(mcmgr_event_type_t type, mcmgr_event_callback_t callback, void *callbackData);
- /*!
- * @brief Trigger event handler
- *
- * This function triggers an event handler
- * on the remote core.
- *
- * @param[in] type Type of the event.
- * @param[in] eventData Data to send to remote core.
- *
- * @return kStatus_MCMGR_Success on success or kStatus_MCMGR_Error on failure.
- */
- mcmgr_status_t MCMGR_TriggerEvent(mcmgr_event_type_t type, uint16_t eventData);
复制代码 使用上述API,我们在core0的工程里注册事件,对应的回调函数内打印出事件的data,在core1的工程中发送事件,简单添加下代码如下。
core0中注册接收事件函数:- void recv_core0_event(uint16_t data,void * contex)
- {
- rt_kprintf("recv CORE1 event %d\n",data);
- }
- int main(void)
- {
- rt_kprintf("core0 running.\r\n");
- (void)MCMGR_StartCore(kMCMGR_Core1, (void *)(char *)CORE1_BOOT_ADDRESS, 2, kMCMGR_Start_Synchronous);
-
- if(kStatus_MCMGR_Success != MCMGR_RegisterEvent(kMCMGR_RemoteRPMsgEvent,recv_core0_event,NULL))
- {
- rt_kprintf("reg event failed.\r\n");
- }
- else
- {
- rt_kprintf("reg event success.\r\n");
- }
- rt_thread_t tid;
- tid = rt_thread_create("runtime_print", print_runtime, RT_NULL, 1024, 12, 28);
- RT_ASSERT(tid != RT_NULL);
- rt_thread_startup(tid);
- while (1)
- {
- zf_gpio_output_not(PIO1, PIN12);
- delay_ms(2000);
- }
- }
复制代码 core1中通过命令来发送事件代码如下:
- void send_event (int argc)
- {
- static int i = 1;
- MCMGR_TriggerEvent(kMCMGR_RemoteRPMsgEvent, i++);
- }
- MSH_CMD_EXPORT(send_event, clear runtime with no param);
复制代码 从如下的运行结果发现,core1发送的事件已经被core0接收和打印出来了,根据之前了解的资料核间的通讯方式还有其他的,现在已经有了工程模板了后续再此基础上在研究追加。
其他方式,待后续研究继续追加..........
--------------------------------------------资料分割线-------------------------------------------- |