查看: 4723|回复: 0

[原创] 【LPC54114双核任务二】理解双核(一)

[复制链接]

该用户从未签到

3

主题

4

帖子

0

高级会员

Rank: 4

积分
695
最后登录
2019-12-4
发表于 2017-6-28 17:33:33 | 显示全部楼层 |阅读模式
作为一名接触arm一年的新人,不得不说从来没接触过双核,所以在学习这个事后也就遇到了很多简单却又根本的问题。所以我从原理开始求索,尝试慢慢理解双核的机制和通信方式。相信肯定有人会跟我一样第一次接触双核,希望我的学习过程能够帮到大家。 lpc54110_03.gif



开发环境:IAR
首先在硬件上,肯定只有一个最初的启动地址,官网例程将m0和m4的代码分成两份,首先编译烧录m0,然后烧录m4,从m4处启动和关闭m0.
这是m4工程下的代码:
  1. #define CORE1_BOOT_ADDRESS (void *)0x20010000                          //定义了前面烧录的m0代码的地址core1是m0,代表slave

  2. #if defined(__CC_ARM)
  3. extern uint32_t Image$CORE1_REGION$Base;
  4. extern uint32_t Image$CORE1_REGION$Length;
  5. #define CORE1_IMAGE_START &Image$CORE1_REGION$Base
  6. #elif defined(__ICCARM__)
  7. extern unsigned char core1_image_start[];                                              //声明了一个数组,用来存储m0,使得m0的代码加载进内存
  8. #define CORE1_IMAGE_START core1_image_start
  9. #endif

  10. /*******************************************************************************
  11. * Prototypes
  12. ******************************************************************************/

  13. #ifdef CORE1_IMAGE_COPY_TO_RAM
  14. uint32_t get_core1_image_size(void);                                                  //得到m0程序的大小
  15. #endif
  16. void delay(void);

  17. /*******************************************************************************
  18. * Code
  19. ******************************************************************************/

  20. #ifdef CORE1_IMAGE_COPY_TO_RAM
  21. uint32_t get_core1_image_size()
  22. {
  23.     uint32_t core1_image_size;                                                            //通过地址计算出代码长度
  24. #if defined(__CC_ARM)
  25.     core1_image_size = (uint32_t)&Image$CORE1_REGION$Length;
  26. #elif defined(__ICCARM__)
  27. #pragma section = "__sec_core"                                                  
  28.     core1_image_size = (uint32_t)__section_end("__sec_core") - (uint32_t)&core1_image_start;
  29. #endif
  30.     return core1_image_size;
  31. }
  32. #endif
复制代码
现在基本上已经看出,是将m0的代码烧进flash的固定位置,这个位置在iar的icf中有定义。然后以m4的代码为入口,在m4代码中将m0的代码从存储中加载进一个数组,从而进入内存得以启动。接下来是main里面的代码:
  1. #ifdef CORE1_IMAGE_COPY_TO_RAM
  2.     /* Calculate size of the image  - not required on LPCExpresso. LPCExpresso copies image to RAM during startup
  3.      * automatically */
  4.     uint32_t core1_image_size;
  5.     core1_image_size = get_core1_image_size();                                                     //在此处得到了m0程序的大小
  6.     PRINTF("Copy Secondary core image to address: 0x%x, size: %d\n", CORE1_BOOT_ADDRESS, core1_image_size);//官方例程的提示;

  7.     /* Copy Secondary core application from FLASH to RAM. Primary core code is executed from FLASH, Secondary from RAM
  8.      * for maximal effectivity.*/
  9.     memcpy(CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, core1_image_size);  //复制进数组。
  10. #endif
复制代码
上面的所有过程完成了将m0加载进内存,使其可执行成为可能。
  1. MCMGR_Init();                                                                 //多核心管理初始化,里面其实只是初始化了mailbox时钟,mailbox是双核间通信用的,关于其使用的协议细节我还在学习中。

  2.     /* Boot Secondary core application */
  3.     PRINTF("Starting Secondary core.\n");
  4.     MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 1, kMCMGR_Start_Synchronous);   //把数组的地址传入,启动m0内核!!
复制代码
关于上面的最后一行代码,对核心进行启动,第一个参数kMCMGR_Core1是一个enum的代码编号,1是m0,0是m4,第二个参数是数组地址,第三个参数其实是在启动m0内核时传给m0的数据,m0可以接受到这个数据并进行一系列的操作。最后一个参数指定了核心的工作状态,同步还是异步,因为以前没有接触过,所以对这个不太了解,通过检索大概内容就是,同步是多个核心以相同频率同时运行,异步是可以以不同的频率运行然后轮换运行,我所说的不一定对,这个地方我觉得原理应该很有趣。说的不对要是有人指正就很棒了!
m4的代码先看到这,接下来看一下m0的代码:
捕获4.PNG
可以看到main函数之前并没有像m4一样做额外处理
  1. int main(void)
  2. {
  3.     uint32_t startupData, i;                                      //该变量用来接收上面传进来的那个1

  4.     /* Define the init structure for the output LED pin*/
  5.     gpio_pin_config_t led_config = {
  6.         kGPIO_DigitalOutput, 0,
  7.     };

  8.     /* Initialize MCMGR before calling its API */
  9.     MCMGR_Init();                                                    //同样要初始化mailbox时钟

  10.     /* Get the startup data */
  11.     MCMGR_GetStartupData(kMCMGR_Core1, &startupData);        //这就是得到启动时传入进来的数据,原理是什么?是他们共享的那部分数据,后面说

  12.     /* Make a noticable delay after the reset */
  13.     /* Use startup parameter from the master core... */
  14.     for (i = 0; i < startupData; i++)
  15.         delay();

  16.     /* Init board hardware.*/
  17.     /* enable clock for GPIO */
  18.     CLOCK_EnableClock(kCLOCK_Gpio0);
  19.     CLOCK_EnableClock(kCLOCK_Gpio1);
  20.     BOARD_InitPins_Core1();
  21.     /* Configure LED */
  22.     LED_INIT();

  23.     /* Signal the other core we are ready */
  24.     MCMGR_SignalReady(kMCMGR_Core1);        //更新准备信号

  25.     while (1)
  26.     {
  27.         delay();
  28.         LED_TOGGLE();
  29.     }
  30. }
复制代码
关于共享的数据:
lpc54114_cm4的头文件里有些内容,具体踪迹我还在找,因为我也是在摸索嘛,且摸且写。到最后无非是两个工程定位到同一个地址。

把这个工程看完吧,回到m4:
捕获5.PNG
定义了按键和关闭启动内核==。
整个工程就这样结束了,
MCMGR相关的所有函数其实到最后都指向mailbox,接下来就摸索一下mailbox!
任务二未完待续。分析代码来学习是我的习惯,若能帮像我一样的初学者稍微理清一下思路,那再好不过。


回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-8-31 06:38 , Processed in 0.077701 second(s), 19 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表