查看: 6405|回复: 6

[原创] 【LPC54114双核任务二】――B、LPC54114双核调试方法

[复制链接]
  • TA的每日心情
    擦汗
    2021-7-5 15:45
  • 签到天数: 664 天

    连续签到: 1 天

    [LV.9]以坛为家II

    42

    主题

    1594

    帖子

    19

    金牌会员

    Rank: 6Rank: 6

    积分
    5636
    最后登录
    2021-12-22
    发表于 2017-7-2 13:00:46 | 显示全部楼层 |阅读模式
    本帖最后由 okwh 于 2017-7-3 20:29 编辑

    LPC54114双核任务二】――BLPC54114双核调试方法

    一、       LPC54114双核基本知识:
      两个核的用途:一切其实都是在时间和空间上排列操作序列和数据分配,两个核有助于完成一些复杂任务,双核编程就像安排两个人协作完成任务一样,但要简单些,其关键就是依据任务的紧迫程度、响应快慢需求、各自的擅长等进行规划。比如如果你有两个任务要同时完成、或者依序完成时不满意、或者事情教复杂分给两个核以方便管理。最基本的特点就是双核方便更灵活安排事情的时序。
      多核工作原理上类似软件中的进程间通讯。其核心思想是1)建立一共享内存区(或其他共享机制)以便两个或多个进程都有权存取; 2) 有某种标志用于共享区的可用状态以保持共享区不能被同时写、可同时读但不能正在读时被写。 通常这样的共享区和标志由操作系统的SDK提供,有操作系统协助(在标志变化时通知、中断各方)完成。
      LPC54114的双核与之类似,可看做两个线程间如何通讯。显然两个核在一个芯片上,当然最方便的方法就是共享内存+标志
        *  共享内存可直接指定(如果事先知道要传递多少),也可动态分配、运行时传递(核间共享记录内存地址的变量),通常由编程自行实现。
        *  标志是用于协调哪个核有权去使用、正在使用共享内存。
        *  协调权限方法:其实就是谁给谁发个信号(通常就是送标志),最常用的方法就是查询、中断,当然管脚状态也是用查询、中断的方法,这是最基本的方法,其他其实都是在此基础上发展丰富、分层分级、特化专门化出来的。或者说事实上就是同一内存(地址或地址区)如何分时使用的问题。

           LPC54114双核都可存取所有资源,并为双核间通讯准备了7个寄存器以方便邮箱式通讯(在地址0x 4008 B000))
        *  两个可读写中断寄存器:  IRQ0(M0响应)IRQ1(M4响应),为324字节。
        *  两对清除/设置只写操作:IR0CLR/IRQ0SET IR1CLR/IRQ1SET,分别用于IRQ0IRQ2的清零复位和置1.  (当然直接对IRQ0IRQ1赋值01也是同样效果,但通常这两种之一。)
        *  一个可读写互斥标志:MUTEX,谁读到1谁有权去使用、正在使用共享内存 (若读到0就不而能使用或去等待), 使用完后,写任何值就失去权限。注意 两个核必须是每核一次的交替使用模式。

        注: 也可以使用查询不用中断,也可以使用自定义的标志变量替代互斥标志寄存器的功能。
        换句话说,双核能存取有关资源(内存、外设和管脚)是最基本支持,专用中断提供了可选的及时通讯能力,互斥标志提供了可选的协调授权的方便。
        两个核对芯片所有资源都可使用,但注意M0+只通过其Sys总线使用资源,M4则有多种总线途径,这些总线的优先级是可设置的。(AHBMATPRIO, 在地址0x 4000 0004)
        注: IRQ0SET 和 对 IRQ0直接用1赋值效果相同,但IRQ0必须写入非0值才行。IRQ1同样。所以这IRQ有两种通常用法,1) 直接传递最多32位的数据,;  2) 把这32位做为数据地址传送,或把32位做数据的16位地址和16位长度传送…, 接收方再去相应地址处理数据。
    (NXP的设计师很喜欢除直接寄存器读写之外,还同时提供CLR/SET这样的基于地址用于功能的操作寄存器,却是提供了多样化的方法,不知道是否浪费资源)

    二、       厂家驱动和例程
           NXP在驱动mailbox_5411x.h中提供了邮箱数据结构和相关函数供使用。
    早期AN11609.zipLPC54102的例程。早期资料仍可在http://www.lpcware.com/下载。相比现在已经封装的更好的SDK,早期资料能看到更多的细节。
        在KeilpackNXP自己原来的LPCXpresso下提供有厂家驱动和LPCOPEN3的简单例库LPC54102LPC54114
        随MCUXpresso的新体系中关于双核包括了lightweightimplementation of the RPMsg protocolEmbeded Remote ProcedureCalleRPC)、Multicore Manager (MCMGR)Low_Power低功耗管理的库、中间件和例程,支持IAR embeddedWorkbench 7.80.4Keil MDK 5.21aMCUXpresso。双核支持得到了很好的加强。邮箱支持在fsl_mailbox.h。新SDK还在发展中,有关资料参考http://mcuxpresso.nxp.com/api_doc/dev/174/index.html

    三、       LPC54114双核编程调试
        通常开发系统原来并不支持多核调试,目前的多核调试还不是很完善。通常使用三种开发系统:KeilIARMCUXpresso(LPCXpresso),仿真器使用LPC-Link2 Jlink ULlNK2 ULlNKPro,支持CMSISDAP等,LPC54系列目前只使用SWD接口进行双核调试,而SWD有时不太稳定(特别是仿真器质量不好或电气环境不佳时)。不知道能不能同时使用两个仿真器调试,目前是通过一个仿真器,运行两个keil进行调试,MCUXpresso是一个开发环境中打开两个调试窗口会话(session或者说场景secene)

    这里介绍下keil下的调试方法
    1)    Kei lV5以上软件,需要为每个核建立工程(可以在一个workplace),调试时要运行两个keill分别对应把工程选作当前工程运行调试各核。
    2)   对于双核,M4的工程是芯片的主项目,或者说缺省首先开始运行,其调试和单核独立项目相同,如果你只需要单核,只开发M4就可以(SDK中的单核例程都是m4)。需设置调试对话框(仿真调试器对话框)中的参数AP0x00,并选中 “Reset afterConnect" 选项(它的意思大概是点击调试按钮后自动到达第一句代码处或者到达main位置), 需要同时项目设置对话框的debuguse仿真调试器选项下的”loadapplication at Startup””Run to main()”, 不选”Run to main()”可调试在main前执行的s文件中的启动引导初始代码。这和单核是相同的,只是单核只有一个AP无需设置,双核才需要设置主核项目的调试用AP0x00APAccess Point存取点,就想象成虚拟的插座吧)。做为主核,它的IROM1起始地址0x00
    3)   M0+工程是次项目,需设置调试对话框中的参数AP0x01不要选中 “Reset afterConnect" 选项。,不要选”loadapplication at Startup””Run to main()”(干脆”Run to main()”变灰就不让选了,我还不知道如何变灰的,可能在项目工程文件中或是devicepack中就已经指明了吧)
    Xb1.png Xb2.png

    4)   做为次核,它的代码放哪里?从哪里开始运行呢?当然肯定放在在flash中,但似乎NXP目前没有提供子和的flash算法,所以从项目无法直接下载到flash(可能需要额外工具通过Utilitiues设置使用,或者使用nxp独立的烧写工具)NXP的例程提供是通过编译后设置在处理,在userafter Build设置Run #1, fromelf.exe外部程序把编译后的文件转为bin格式($K\ARM\ARMCC\bin\fromelf.exe--bincombined --bincombined_base=0x20010000 --output=$Lcore1_image.bin !L  这转换参数表明 这个bin文件的内容将设计为在0x20010000地址运行),这个bin文件被被M4工程当做数据文件,和m4自己的一起写入flash
    5)  做为次核,它的代码从哪里开始运行呢?虽然理论上代码可放在任何地址并从那里执行,当然实际产品是要进行地址分配的。通常代码可在两个地方运行:flash或者RAM或者二者配合(特殊情况下在一定支持下可从一些端口接口运行如特殊的启动过程)。目前NXP的例程提供M0代码可从flash运行也可以从RAM执行。若m0工作很简单,代码很少,可以复制到RAMRAM执行,这种情况下,前面的bin文件下入flash后, M4main函数中把对应的代码从flash复制RAM地址0x20010000,然后用Chip_CPU_CM0Boot(jumpAddr,stackAddr); 或新的MCMGR_StartCore(kMCMGR_Core1,CORE1_BOOT_ADDRESS, 1, kMCMGR_Start_Synchronous);M0核开始工作。分析s文件,可看到,对于次核,判定CPU_id后立即进入休眠的,s文件还有 cpu_id               EQU              0xE000ED00  /// cpu_ctrl         EQU              0x40000300  ///  coproc_boot  EQU              0x40000304  ///  coproc_stack  EQU              0x40000308 这样的信息。有关多核管理的库函数是固化在芯片里的,有兴趣者可在调试状态分析一下其汇编代码。下图说明了双核的启动过程:
    Xb0.png


    6)   那么怎么调试呢: 1)  只调试M4,此时M4和通常单核一样,如果不需要调试m0,只运行M4工程即可。         2)  核都调试,先运行m4工程进入调试main并且在Chip_CPU_CM0Boot或新的MCMGR_StartCoreM0核开始工作后!!!再在新打开的keil执行m0工程(那些项目设置保证无需下载,直接试图通过同一个仿真器连接m0核,),运行等待连接上,就可以设置断点可以调试了。         3) 只调试M0, 用M4工程下载代码到flash, 重启电路板处于运行状态,然后在新打开的keil执行m0工程,等待连接上,就可以设置断点可以调试了。
    7)   总之,把双核想象成两个人配合工作,只是有主次之分,m4要负责触发m0开始,开始后就可以连山软件进行调试了。目前,NXPm0设计似乎是不允许它独立不允许它优先,m0调试的核心是Connect withdebugger to m0+ without reset of chip and withoutcode-download!!

    所以关键就是 m0调试就是  调试器是在 单片机已经在运行时 挂接的 !!!   这几乎就是和 PC机上调试动态链接库DLL的方式 一样!

    进一步学习: 有兴趣的可进一步分析s文件,特别是分析linker设置中对应M4m0Scatter文件.scf。我不是专业人员,分析到这里已经足够使用了。

            我猜测,似乎NXP有倾向把嵌入系统发展为我们熟悉的PC那样,程序exe存在什么地方或盘上,需要时装入内存即可,这样的运行方式已经并正在向嵌入系统渗透,不仅是安卓系统、嵌入Linux那样的已经是这样实现,甚至这只有几十数百k字节内存的单片机上也开始有这种迹象。从最初很少次可擦写的各种ROM到今天数十万次可擦写的flash,如果这支持eXecute In Place(XIP)flash再提速扩容缩体强大些,也许单片机级别的功能动态重组重载就不远了,实现了,小机器也都快成半个生命了。
     
    四、调试实践:
    基于例子lpc54114\SDK_2.2.1_LPCXpresso54114\boards\lpcxpresso54114\multicore_examples\hello_world
    步骤:
    1)   编m0hello_world_cm0plus.uvmpwhello_world_cm0plus.uvprojx生成core1_image.bin
    2)  编译m4hello_world_cm4.uvmpwhello_world_cm4.uvprojx;里面通过incbin.s包含了core1_image.bin

    incbin.s内容:典型的只读数据汇编表达
    1. AREA M0CODE, DATA, READONLY, PREINIT_ARRAY, ALIGN=3
    2.         EXPORT m0_image_start
    3.         EXPORT m0_image_end
    复制代码
    M4项目main中如何启动M0的代码:
    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();
    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

    11.     /* Initialize MCMGR before calling its API */
    12.     MCMGR_Init();

    13.     /* Boot Secondary core application */
    14.     PRINTF("Starting Secondary core.\n");
    15.     MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 1, kMCMGR_Start_Synchronous);
    复制代码
    在这之后就m0的调试就可以挂接上了

    m4代码修改增加:
    1. GPIO_PinInit(BOARD_SW1_GPIO, 1, 8, &sw_config);//万利按键PB2
    2. GPIO_PinInit(BOARD_SW2_GPIO, 1, 9, &sw_config); //万利按键PB3
    3. ………………………..

    4.   while (1)
    5.     {
    6.         /* Stop secondary core execution. */
    7.       //  if (!GPIO_ReadPinInput(BOARD_SW1_GPIO, BOARD_SW1_GPIO_PORT, BOARD_SW1_GPIO_PIN))
    8.                                 if (!GPIO_ReadPinInput(BOARD_SW1_GPIO, 1, 8))
    9.         {
    10.             MCMGR_StopCore(kMCMGR_Core1);
    11.             PRINTF("Stopped Secondary core.\n");
    12.             delay();
    13.         }
    14.         /* Start core from reset vector */
    15.    //     if (!GPIO_ReadPinInput(BOARD_SW2_GPIO, BOARD_SW2_GPIO_PORT, BOARD_SW2_GPIO_PIN))
    16.                                 if (!GPIO_ReadPinInput(BOARD_SW2_GPIO, 1, 9))
    17.         {
    18.             MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 5, kMCMGR_Start_Synchronous);
    19.             PRINTF("Started Secondary core.\n");
    20.             delay();
    21.         }
    22. }
    复制代码

    m0代码修改增加:
    1. //  LED_INIT();
    2.     GPIO_PinInit(GPIO, 0, 15, &led_config);  //D11
    3.                 GPIO_PinInit(GPIO, 0, 19, &led_config);  //D10
    4.                 GPIO_PinInit(GPIO, 0, 21, &led_config);  //D9
    5.                 GPIO_PinInit(GPIO, 0, 22, &led_config);  //D8
    6.                
    7.                 GPIO_PinInit(GPIO, 0, 25, &led_config);  //D7
    8.                 GPIO_PinInit(GPIO, 0, 26, &led_config);  //D6
    9.                 GPIO_PinInit(GPIO, 0, 29, &led_config);  //D5
    10.                 GPIO_PinInit(GPIO, 0, 30, &led_config);  // D4
    11.                
    12.         gpio_pin_config_t sw_config = {kGPIO_DigitalInput, 0};
    13.         GPIO_PinInit(BOARD_SW1_GPIO, 1, 10, &sw_config); //万利按键PB4
    14.         GPIO_PinInit(BOARD_SW2_GPIO, 1, 11, &sw_config); //万利按键PB5
    15. ……………
    16.    while (1)
    17.     {
    18.  delay();
    19.  GPIO_TogglePinsOutput(GPIO, 0, 1u << 15);   //D11
    20.  GPIO_TogglePinsOutput(GPIO, 0, 1u << 19);    //D10
    21.  GPIO_TogglePinsOutput(GPIO, 0, 1u << 25);  //D7
    22.  GPIO_TogglePinsOutput(GPIO, 0, 1u << 26);                //D6        
    23.                         //  LED_TOGGLE();
    复制代码
    1. //  LED_TOGGLE();
    2.                         if (!GPIO_ReadPinInput(BOARD_SW1_GPIO, 1, 10))
    3.                         {

    4.                         GPIO_TogglePinsOutput(GPIO, 0, 1u << 21);
    5.                         GPIO_TogglePinsOutput(GPIO, 0, 1u << 22);
    6.                         }
    7.                         if (!GPIO_ReadPinInput(BOARD_SW1_GPIO, 1, 11))
    8.                         {

    9.                         GPIO_TogglePinsOutput(GPIO, 0, 1u << 29);
    10.                         GPIO_TogglePinsOutput(GPIO, 0, 1u << 30);
    11.                         }
    12.     }
    复制代码


    试验功能:
    按键2/3M4接收实现起停M0,对应M0翻转闪动绿D6/D7和红D10/D11
    按键4/5M0接收实现亮灭M0,  对应按键4翻转亮灭红D8/D9, 按键5翻转亮灭红D4/D5.

    源代码文件: hello_world.rar (280.59 KB, 下载次数: 52)
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2018-3-27 15:23
  • 签到天数: 49 天

    连续签到: 1 天

    [LV.5]常住居民I

    0

    主题

    109

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    333
    最后登录
    2018-6-28
    发表于 2017-7-2 13:27:12 | 显示全部楼层
    这么多 字  看着头晕,这排版
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2021-7-5 15:45
  • 签到天数: 664 天

    连续签到: 1 天

    [LV.9]以坛为家II

    42

    主题

    1594

    帖子

    19

    金牌会员

    Rank: 6Rank: 6

    积分
    5636
    最后登录
    2021-12-22
     楼主| 发表于 2017-7-2 15:19:11 | 显示全部楼层
    nxp_helloworld 发表于 2017-7-2 13:27
    这么多 字  看着头晕,这排版

    没办法,看漫画的就请了。 福袋.txt (10 Bytes, 下载次数: 60)
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-11-20 11:31
  • 签到天数: 123 天

    连续签到: 1 天

    [LV.7]常住居民III

    1

    主题

    313

    帖子

    0

    高级会员

    Rank: 4

    积分
    893
    最后登录
    2018-7-13
    发表于 2017-7-2 15:36:57 | 显示全部楼层
    okwh 发表于 2017-7-2 15:19
    没办法,看漫画的就请了。

    可以直接上附件么?
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2017-12-29 14:09
  • 签到天数: 144 天

    连续签到: 1 天

    [LV.7]常住居民III

    9

    主题

    534

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1856
    最后登录
    2025-7-22
    发表于 2017-7-3 14:55:03 | 显示全部楼层
    多谢分享
    签到!!!
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2021-7-5 15:45
  • 签到天数: 664 天

    连续签到: 1 天

    [LV.9]以坛为家II

    42

    主题

    1594

    帖子

    19

    金牌会员

    Rank: 6Rank: 6

    积分
    5636
    最后登录
    2021-12-22
     楼主| 发表于 2017-7-3 14:56:38 | 显示全部楼层
    本帖最后由 okwh 于 2017-7-3 20:30 编辑

    奇怪,代码怎么少了?


    已修改 并附上工程代码
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    11

    帖子

    0

    新手上路

    Rank: 1

    积分
    21
    最后登录
    2019-4-3
    发表于 2019-4-3 14:59:48 | 显示全部楼层
    学习,学习,楼主威武,多谢分享
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-8-29 06:23 , Processed in 0.090837 second(s), 26 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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