胤幻1988 发表于 2020-11-3 16:06:13

【NXP OKdo E1双核Cortex M33开发板】+LPC55S69双核通讯实验

今天我来做一下LPC55S69的双核通讯实验,我们通过上面的分析已知通讯的关键就在是要mailbox寄存器。
闲话不多说,我们在官方的hello_world_cm33_core0及其匹配的hello_world_cm33_core1.上面修改。
我们定义core1程序一直在运行一个闪烁灯,而core0程序控制一个按键,按下按键可以打开或者关闭core1,并空闲状态不停输出"Hello world"。
先在core0的main函数文件页面修改:
先添加1个变量
//按键的初始化
...
uint8_t      led_flg=0;


while函数里面。查询:
<blockquote><blockquote>if(0 == IS_BUTTON_PRESSED())core1c程序的修改:
main函数while:
LED_GREEN_TOGGLE();
delay();这里没有用到中断,仅简单看core0能否直观的控制core1.
编译下载调试:
串口输出(不知道怎么回事,调试双核时,虚拟串口无法正常输出,可能我哪边配置不对,仅调试台输出信息):
Hello world!
Hello world!
Hello world!
Hello world!
Starting Secondary core.//开启
The secondary core application has been started.
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Stopping Secondary core.//关闭
The secondary core application has been stopped.
Hello world!
Hello world!
Hello world!CORE1打开时LED闪烁,关闭时LED保保持最后的状态不变。
至少证明通讯成功,下面用core0程序里的按键进行控制core1程序里的LED亮灭,需要使用中断:
这里定义发送1为开灯,发送2为关灯,发送接收得到数据不能为0,不然会被忽略。
在core0 mian函数页面添加变量:
uint16_t Mail_DATA=0;//邮箱数据接收缓存
uint8_t g_flg=0;//邮箱中断标志
uint8_t      led_flg=0;//led状态while里面:
if(g_flg==1)
{
      g_flg=0;
      printf("Core0 receve data is : %d",Mail_DATA);

}
else
{
      //我们这添加控制核1打开的操作
      if(0 == IS_BUTTON_PRESSED())
      {
                while (0== IS_BUTTON_PRESSED())
                {
                }

                led_flg=1-led_flg;
                //printf("the led_flg is %d \r\n",led_flg);
                //发送数据不能为0,为0无效
                if(led_flg==1)
                {
                        MAILBOX_SetValueBits(MAILBOX, kMAILBOX_CM33_Core1, 1);
                }
                else
                {

                        MAILBOX_SetValueBits(MAILBOX, kMAILBOX_CM33_Core1, 2);
                }
      }

      LED_BLUE_TOGGLE();
      delay();
}mailbox的中断,例程已写好在mcmgr_internal_core_api_lpc55s69.c里面,
我们直接修改下:
添加外部变量引用:
extern uint16_t Mail_DATA;
extern uint8_t g_flg;在中断程序里面修改,没有破坏之前的结构(发送接收得到数据不能为0,不然会被忽略):
void MAILBOX_IRQHandler(void)
{
#if defined(FSL_FEATURE_MAILBOX_SIDE_A)
    mailbox_cpu_id_t cpu_id = kMAILBOX_CM33_Core0;
#else
    mailbox_cpu_id_t cpu_id = kMAILBOX_CM33_Core1;
#endif
    uint32_t data;
    uint16_t eventType;
    uint16_t eventData;

    data = MAILBOX_GetValue(MAILBOX, cpu_id);
<font color="#ff0000">    Mail_DATA=data;</font>
    // To be MISRA compliant, return value needs to be checked even it could not never be 0
    if (0U != data)
    {
<font color="#ff0000">            g_flg=1;</font>

      MAILBOX_ClearValueBits(MAILBOX, cpu_id, data);

      eventType = (uint16_t)(data >> 16u);
      eventData = (uint16_t)(data & 0x0000FFFFu);

      if (((mcmgr_event_type_t)eventType >= kMCMGR_RemoteCoreUpEvent) &&
            ((mcmgr_event_type_t)eventType < kMCMGR_EventTableLength))
      {
            if (MCMGR_eventTable[(mcmgr_event_type_t)eventType].callback != ((void *)0))
            {
                MCMGR_eventTable[(mcmgr_event_type_t)eventType].callback(
                  eventData, MCMGR_eventTable[(mcmgr_event_type_t)eventType].callbackData);
            }
      }
    }
}对core1函数进行修改:
main函数里面修改:
定义变量:
uint16_t Mailbox_data=0;
uint8_t g_flag=0,led_flag=0;if(g_flag==1)
            {
                  g_flag=0;
                  //printf("Core1 receiver data is : %d",Mailbox_data);
                  led_flag=Mailbox_data;

            }
            else
            {
                  if(led_flag==1)
                  {
                            LED_GREEN_ON();

                  }
                  else if(led_flag==2)
                        {
                            LED_GREEN_OFF();
                        }
            }中断函数里面修改:
<font color="#ff0000">extern uint16_t Mailbox_data;
extern uint8_t g_flag;</font>

void MAILBOX_IRQHandler(void)
{
#if defined(FSL_FEATURE_MAILBOX_SIDE_A)
    mailbox_cpu_id_t cpu_id = kMAILBOX_CM33_Core0;
#else
    mailbox_cpu_id_t cpu_id = kMAILBOX_CM33_Core1;
#endif
    uint32_t data;
    uint16_t eventType;
    uint16_t eventData;

    data = MAILBOX_GetValue(MAILBOX, cpu_id);
<font color="#ff0000">    Mailbox_data=data;</font>
//发送接收得到数据不能为0,不然会被忽略
   //To be MISRA compliant, return value needs to be checked even it could not never be 0
    if (0U != data)
    {
<font color="#ff0000">            g_flag=1;</font>

      MAILBOX_ClearValueBits(MAILBOX, cpu_id, data);

      eventType = (uint16_t)(data >> 16u);
      eventData = (uint16_t)(data & 0x0000FFFFu);

      if (((mcmgr_event_type_t)eventType >= kMCMGR_RemoteCoreUpEvent) &&
            ((mcmgr_event_type_t)eventType < kMCMGR_EventTableLength))
      {
            if (MCMGR_eventTable[(mcmgr_event_type_t)eventType].callback != ((void *)0))
            {
                MCMGR_eventTable[(mcmgr_event_type_t)eventType].callback(
                  eventData, MCMGR_eventTable[(mcmgr_event_type_t)eventType].callbackData);
            }
      }
    }
}
编译下载,现象如下:

例程比较简单,但是逻辑确实通用的,我们可以在这上面添加更多的外设控制。好了,双核通讯就到这了。
这里说个题外话,就是这个函数 就是core0里面的MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 5, kMCMGR_Start_Synchronous);
其中还是很有意思的,kMCMGR_Start_Synchronous等待2个函数同步后再运行。展开MCMGR_StartCore函数:
mcmgr_status_t MCMGR_StartCore(mcmgr_core_t coreNum, void *bootAddress, uint32_t startupData, mcmgr_start_mode_t mode)
{
    mcmgr_status_t ret;

    if ((uint32_t)coreNum < g_mcmgrSystem.coreCount)
    {
      /* Pass the startupData - LSB first */
      s_mcmgrCoresContext.startupData = startupData;
      /* the startup data is sent asynchronously */
      ret = mcmgr_start_core_internal(coreNum, bootAddress);

      if (ret == kStatus_MCMGR_Success)
      {
            if (mode == kMCMGR_Start_Synchronous)
            {
                /* Wait until the second core reads and confirms the startup data */

上面那个函数一直在等待core1准备好的状态。而core1里面:
do
    {
      status = MCMGR_GetStartupData(&startupData);
    } <font color="#ff0000">while (status != kStatus_MCMGR_Success);</font>
在不停的查询当前状态,并刷新。我一开始想完全撇开mcmgr,但发现牵连还挺多就放弃了。哪位大佬能详细讲述一下mcmgr,包括新注册的建中断任务等。小弟感激不尽!



页: [1]
查看完整版本: 【NXP OKdo E1双核Cortex M33开发板】+LPC55S69双核通讯实验

Baidu
map