在线时间428 小时
UID3006061
注册时间2015-3-23
NXP金币76
TA的每日心情 | 开心 2025-1-21 08:52 |
---|
签到天数: 861 天 连续签到: 1 天 [LV.10]以坛为家III
金牌会员
 
- 积分
- 5867
- 最后登录
- 2025-1-22
|
本帖最后由 leo121_3006061 于 2017-6-27 16:08 编辑
LPC54114双核(M4 /M0+),如何实现双核之间的通信,NXP官方提供Multicore Software Development Kit (MCSDK) ,双核的管理如下图所示
可以看出MCSDK由三个组件组成
1. Multicore Manager (MCMGR)
1). 维护系统里所有核的信息 2).为第二核加载代码(当代码在ram里时,此功能才可用)
3).第二或辅助核的开启和关闭
4).维护共享的内存区域的地址映射表
我们可以通过sdk自带的例程Hello world 来理解Multicore Manager,为了更好的运行例程,我稍加修改了一下。
大致上,分别创建两个独立的keil工程,分别是m0+核与m4核,然后首先编译m0+核工程,再编译m4并且附加m0+一并且下载到开发板。
第一步 ,在m0核的keil工程里实现6,7的LED闪烁,下边附上部分代码。
- int main(void)
- {
- uint32_t startupData, i;
- /* Initialize MCMGR before calling its API */
- MCMGR_Init();
- /* Get the startup data */
- MCMGR_GetStartupData(kMCMGR_Core1, &startupData);
- /* Make a noticable delay after the reset */
- /* Use startup parameter from the master core... */
- for (i = 0; i < startupData; i++)
- delay();
- /* Init board hardware.*/
- /* enable clock for GPIO */
- CLOCK_EnableClock(kCLOCK_Gpio0);
- CLOCK_EnableClock(kCLOCK_Gpio1);
- BOARD_InitPins_Core1();
- /* Configure LED */
- // LED_INIT();
- led_init();
- /* Signal the other core we are ready */
- MCMGR_SignalReady(kMCMGR_Core1);
- while (1)
- {
- delay();
- led_toggle(6); //
- led_toggle(7);
- }
复制代码 然后修改如下图所示--user, $K\ARM\ARMCC\bin\fromelf.exe --bincombined --bincombined_base=0x20010000 --output=$Lcore1_image.bin !L,然后编译,不要下载。
第二步 再创建m4核的工程,我也稍微做了修改,为了减少篇幅,请看部分代码,此部分是当key建按下时m0+核停止运行。
- /* Define the init structure for the switches*/
- gpio_pin_config_t sw_config = {kGPIO_DigitalInput, 0};
- /* Init board hardware.*/
- /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
- CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
- BOARD_InitPins_Core0();
- BOARD_BootClockFROHF48M();
- BOARD_InitDebugConsole();
- /* Init switches */
- GPIO_PinInit(BOARD_SW1_GPIO, BOARD_SW1_GPIO_PORT, BOARD_SW1_GPIO_PIN, &sw_config);
- GPIO_PinInit(BOARD_SW2_GPIO, BOARD_SW2_GPIO_PORT, BOARD_SW2_GPIO_PIN, &sw_config);
- #ifdef CORE1_IMAGE_COPY_TO_RAM
- /* Calculate size of the image - not required on LPCExpresso. LPCExpresso copies image to RAM during startup
- * automatically */
- uint32_t core1_image_size;
- core1_image_size = get_core1_image_size();
- PRINTF("Copy Secondary core image to address: 0x%x, size: %d\n", CORE1_BOOT_ADDRESS, core1_image_size);
- /* Copy Secondary core application from FLASH to RAM. Primary core code is executed from FLASH, Secondary from RAM
- * for maximal effectivity.*/
- memcpy(CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, core1_image_size);
- #endif
- key_init();
- /* Initialize MCMGR before calling its API */
- MCMGR_Init();
- /* Boot Secondary core application */
- PRINTF("Starting Secondary core.\n");
- MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 1, kMCMGR_Start_Synchronous);
- /* Print the initial banner from Primary core */
- PRINTF("\r\nHello World from the Primary Core!\r\n\n");
- PRINTF("Press the Key1 button to Stop Secondary core.\r\n");
- PRINTF("Press the Key2 button to Start Secondary core.\r\n");
- while (1)
- {
- if(key_value(0)==0)
- {
- MCMGR_StopCore(kMCMGR_Core1);
- PRINTF("Stopped Secondary core.\n");
- delay();
-
-
- }
- if(key_value(0)==1)
- {
- MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 5, kMCMGR_Start_Synchronous);
- PRINTF("Started Secondary core.\n");
- delay();
-
- }
- }
复制代码 第三步编译m4并附加m0+(此步骤是代码里有),一并下载到开发板,打开串口调试工具,显示如下图所示信息
通过上面的步骤,很容易了解利用M4控制M0+的起停。
2. Remote Processor Messaging - Lite (RPMsg-Lite)主要为异构多核之间通讯提供接口。
推荐资源 http://github.com/NXPmicro/rpmsg-lite和官方的sdk接下来通过简单的修改官方的sdk就可以实现本次任务的要求,附上代码
m0+核的代码(只有修改的部分)
- #define RPMSG_LITE_LINK_ID (RL_PLATFORM_LPC5411x_M4_M0_LINK_ID)
- #define MCMGR_USED
- #define LOCAL_EPT_ADDR (30)
- typedef struct the_message
- {
- uint32_t DATA;
- } THE_MESSAGE, *THE_MESSAGE_PTR;
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*******************************************************************************
- * Code
- ******************************************************************************/
- THE_MESSAGE volatile msg = {0};
- unsigned long remote_addr = 0;
- /* Internal functions */
- static int my_ept_read_cb(void *payload, int payload_len, unsigned long src, void *priv)
- {
- int *has_received = priv;
- if (payload_len <= sizeof(THE_MESSAGE))
- {
- memcpy((void *)&msg, payload, payload_len);
- remote_addr = src;
- *has_received = 1;
- PRINTF("The m0+ core received msg from m4 core\r\n");
- PRINTF("Message: Size=%x, DATA = %i\n\r", payload_len, msg.DATA);<font color="#ff0000">//接到m4内核传递的消息并且通过uart打印出来,m0+核相当于转发消息</font>
- }
- return RL_RELEASE;
- }
- /*!
- * @brief Main function
- */
- int main(void)
- {
- char ch=0;
- volatile int has_received = 0;
- struct rpmsg_lite_ept_static_context my_ept_context;
- struct rpmsg_lite_endpoint *my_ept;
- struct rpmsg_lite_instance rpmsg_ctxt;
- struct rpmsg_lite_instance *my_rpmsg;
- /* Initialize standard SDK demo application pins */
- BOARD_InitPins_Core1();
-
- /* Initialize standard SDK demo application pins */
- /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
- CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
- BOARD_InitDebugConsole();
- #ifdef MCMGR_USED
- uint32_t startupData;
- /* Initialize MCMGR before calling its API */
- MCMGR_Init();
- /* Get the startup data */
- MCMGR_GetStartupData(kMCMGR_Core1, &startupData);
- my_rpmsg = rpmsg_lite_remote_init((void *)startupData, RPMSG_LITE_LINK_ID, RL_NO_FLAGS, &rpmsg_ctxt);
- /* Signal the other core we are ready */
- MCMGR_SignalReady(kMCMGR_Core1);
- #else
- my_rpmsg = rpmsg_lite_remote_init((void *)RPMSG_LITE_SHMEM_BASE, RPMSG_LITE_LINK_ID, RL_NO_FLAGS, &rpmsg_ctxt);
- #endif /* MCMGR_USED */
- while (!rpmsg_lite_is_link_up(my_rpmsg))
- ;
- my_ept = rpmsg_lite_create_ept(my_rpmsg, LOCAL_EPT_ADDR, my_ept_read_cb, (void *)&has_received, &my_ept_context);
- #ifdef RPMSG_LITE_NS_USED
- rpmsg_ns_announce(my_rpmsg, my_ept, RPMSG_LITE_NS_ANNOUNCE_STRING, RL_NS_CREATE);
- #endif /*RPMSG_LITE_NS_USED*/
- has_received = 0;
- //msg.DATA=ch;
- while (1) //rx received data
- {
- ch= GETCHAR();
- msg.DATA=ch-49;
-
- if (msg.DATA)<font color="#ff0000">//从uart传递过来的值,转发给m4核</font>
- {
- has_received = 0;
- // msg.DATA++;
- rpmsg_lite_send(my_rpmsg, my_ept, remote_addr, (char *)&msg, sizeof(THE_MESSAGE), RL_DONT_BLOCK);
- }
- }
- rpmsg_lite_destroy_ept(my_rpmsg, my_ept);
- my_ept = NULL;
- rpmsg_lite_deinit(my_rpmsg);
- msg.DATA = 0;
- /* End of example */
- }
复制代码 m4核代码
- static int my_ept_read_cb(void *payload, int payload_len, unsigned long src, void *priv)
- {
- int *has_received = priv;
- if (payload_len <= sizeof(THE_MESSAGE))
- {
- memcpy((void *)&msg, payload, payload_len);
- *has_received = 1;
- }
- msg.DATA++; <font color="#ff0000">//接收从m0+核传递过来的数据;为了区别原始数据,进行++操作</font>
- // PRINTF("Primary core received a msg\n\r");
- // PRINTF("Message: Size=%x, DATA = %i\n\r", payload_len, msg.DATA);
- return RL_RELEASE;
- }
- /*!
- * @brief Main function
- */
- int main(void)
- {
- volatile int has_received;
- struct rpmsg_lite_ept_static_context my_ept_context;
- struct rpmsg_lite_endpoint *my_ept;
- struct rpmsg_lite_instance rpmsg_ctxt;
- struct rpmsg_lite_instance *my_rpmsg;
- /* Initialize standard SDK demo application pins */
- /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
- CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
- BOARD_InitPins_Core0();
- BOARD_BootClockFROHF48M();
- BOARD_InitDebugConsole();
- #ifdef CORE1_IMAGE_COPY_TO_RAM
- /* Calculate size of the image */
- uint32_t core1_image_size;
- core1_image_size = get_core1_image_size();
- //PRINTF("Copy CORE1 image to address: 0x%x, size: %d\n", CORE1_BOOT_ADDRESS, core1_image_size);
- /* Copy application from FLASH to RAM */
- memcpy(CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, core1_image_size);
- #endif
- /* Initialize MCMGR before calling its API */
- MCMGR_Init();
- /* Boot Secondary core application */
- MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, (uint32_t)rpmsg_lite_base, kMCMGR_Start_Synchronous);
- // Print the initial banner
- // PRINTF("\r\nRPMsg demo starts\n\n\r");
- my_rpmsg = rpmsg_lite_master_init(rpmsg_lite_base, SH_MEM_TOTAL_SIZE, RPMSG_LITE_LINK_ID, RL_NO_FLAGS, &rpmsg_ctxt);
- my_ept = rpmsg_lite_create_ept(my_rpmsg, LOCAL_EPT_ADDR, my_ept_read_cb, (void *)&has_received, &my_ept_context);
- has_received = 0;
- /* Send the first message to the remoteproc */
- msg.DATA = 10;<font color="#ff0000">//初次运行通过m0+核传递的数据</font>
- rpmsg_lite_send(my_rpmsg, my_ept, REMOTE_EPT_ADDR, (char *)&msg, sizeof(THE_MESSAGE), RL_DONT_BLOCK);
- while (msg.DATA <= 100)
- {
- if (has_received)
- {
- has_received = 0;
- msg.DATA++;
- rpmsg_lite_send(my_rpmsg, my_ept, 30, (char *)&msg, sizeof(THE_MESSAGE), RL_DONT_BLOCK);
- }
- }
- rpmsg_lite_destroy_ept(my_rpmsg, my_ept);
- my_ept = NULL;
- rpmsg_lite_deinit(my_rpmsg);
- // Print the ending banner
- //PRINTF("\r\nRPMsg demo ends\n\n\r");
-
复制代码 运行效果如下图所示
上述过程是利用共享内存,来实现消息传输的。
3. Embedded Remote Procedure Call (eRPC)
eRPC Getting Started User's Guide.pdf
(970.6 KB, 下载次数: 60)
|
|