这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【FRDM-MCXN947评测】kick Core1 点亮LED

共3条 1/1 1 跳转至

【FRDM-MCXN947评测】kick Core1 点亮LED

工程师
2024-11-08 21:40:46   被打赏 50 分(兑奖)     打赏

简介

      MCX Nx4x系列微控制器将两个Arm Cortex M33内核、一个CoolFlux BSP32、一个PowerQuad DSP协处理器、一个NPU,以及多个运行频率达150MHz的高速连接功能相结合。为了支持各种应用, MCX N系列配备了高级串行外设、定时器、高精度模拟和最先进的安全功能。所有的MCX Nx4x产品都包含双区闪存,支持在内部闪存进行边读边写的操作。 MCX Nx4x系列还支持大型外部串行存储器配置。MCX Nx4x 是 一 个 双 核 微 控 制 器 系 列 MCU CPU0 是 主 Cortex-M33 r0p4-00rel0 版 ) 处 理 器 , 支 持TrustZone-M、浮点单元( FPU)和内存保护单元( MPU)。MCX Nx4x芯片还包含第二个Cortex-M33实体CPU1CPU1作为一个副CM33,旨在从主处理器上分担部分工作,以支持特殊的专用应用。 此实体的配置不包括MPUFPUDSPETMTrustzone-M、安全属性单元( SAU及协处理器接口。两个内核均支持SYSTICKCortex-M33使用两个32位总线接口( 代码总线和系统总线), 改变了Harvard存储器架构。总线接口按地址范围激活, 且可以在一个特定的总线端口上同时进行指令获取和操作数数据引用。( 传统的哈佛架构严格地将指令获取和操作数数据引用分离,将它们分配到特定的总线端口,不考虑访问地址。 )代码总线通常用于指令获取PC相关数据的访问,而系统总线通常用于对片上和片外存储器的操作数数据的引用以及外设访问。 此总线结构完全支持指令获取和数据访问的并发执行,但Cortex-M33的实现可以在每个总线上都生成这两种类型的引用。

CORE1 启动相关寄存器

    启动CORE1 需要使用CPUCTRL 和  CPBOOT寄存器,CPUCTRL  用于控制CORE1的clock 和 reset 信号,CPBOOT 用于设置CORE1 的启动地址信息,对应寄存器说明如下。

image.png

image.png

image.png

image.png

           

CORE1 的启动按照下面的配置即可完成启动。

  1. 配置SYSCON->CPBOOT 为CORE1镜像的加载地址 

  2. 配置SYSCON->CPUCTRL[CPURSTEN] = 1 release CORE1 的reset 信号

  3. 配置SYSCON->CPUCTRL[CPUCLKEN] = 1 使能CORE1 的CLK  信号 完成CORE1 的启动。

NXP 的软件包示例程序中有muticore 运行的示例程序,我们参照 SDK“\boards\frdmmcxn947\multicore_examples\hello_world”中的示例程序使用上一篇适配的RT-thread  的基础上将CORE1 kick起来让core1 点亮LED验证core1是否被正常拉起。

参照上面的启动流程添加如下代码让core1运行。

void start_secondary_core(uint32_t sec_core_boot_addr)
{
    /* Boot source for Core 1 from flash */
    SYSCON->CPBOOT = (sec_core_boot_addr & SYSCON_CPBOOT_CPBOOT_MASK);

    int32_t temp = SYSCON->CPUCTRL;
    temp |= 0xc0c40000;
    SYSCON->CPUCTRL = temp | SYSCON_CPUCTRL_CPU1RSTEN_MASK | SYSCON_CPUCTRL_CPU1CLKEN_MASK;
    SYSCON->CPUCTRL = (temp | SYSCON_CPUCTRL_CPU1CLKEN_MASK) & (~SYSCON_CPUCTRL_CPU1RSTEN_MASK);
}

在RT-thread 中添加如下代码core0启动过程中拉起 core1

#include <rtthread.h>
#include "fsl_common.h"

#define CORE1_IMAGE_COPY_TO_RAM

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define PRIMARY_CORE_MAILBOX_CPU_ID   kMAILBOX_CM33_Core0
#define SECONDARY_CORE_MAILBOX_CPU_ID kMAILBOX_CM33_Core1

/* Address of RAM, where the image for core1 should be copied */
#define CORE1_BOOT_ADDRESS 0x2004E000

#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
extern uint32_t Image$$CORE1_REGION$$Base;
extern uint32_t Image$$CORE1_REGION$$Length;
#define CORE1_IMAGE_START &Image$$CORE1_REGION$$Base
#elif defined(__ICCARM__)
extern unsigned char core1_image_start[];
#define CORE1_IMAGE_START core1_image_start
#elif (defined(__GNUC__)) && (!defined(__MCUXPRESSO))
extern const char core1_image_start[];
extern const char *core1_image_end;
extern int core1_image_size;
#define CORE1_IMAGE_START ((void *)core1_image_start)
#define CORE1_IMAGE_SIZE  ((void *)core1_image_size)
#endif

#ifdef CORE1_IMAGE_COPY_TO_RAM
uint32_t get_core1_image_size(void);
#endif

void start_secondary_core(uint32_t sec_core_boot_addr);


#ifdef CORE1_IMAGE_COPY_TO_RAM
uint32_t get_core1_image_size(void)
{
    uint32_t image_size;
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
    image_size = (uint32_t)&Image$$CORE1_REGION$$Length;
#elif defined(__ICCARM__)
#pragma section = "__core1_image"
    image_size = (uint32_t)__section_end("__core1_image") - (uint32_t)&core1_image_start;
#elif defined(__GNUC__)
    image_size = (uint32_t)core1_image_size;
#endif
    return image_size;
}
#endif

void start_secondary_core(uint32_t sec_core_boot_addr)
{
    /* Boot source for Core 1 from flash */
    SYSCON->CPBOOT = (sec_core_boot_addr & SYSCON_CPBOOT_CPBOOT_MASK);

    int32_t temp = SYSCON->CPUCTRL;
    temp |= 0xc0c40000;
    SYSCON->CPUCTRL = temp | SYSCON_CPUCTRL_CPU1RSTEN_MASK | SYSCON_CPUCTRL_CPU1CLKEN_MASK;
    SYSCON->CPUCTRL = (temp | SYSCON_CPUCTRL_CPU1CLKEN_MASK) & (~SYSCON_CPUCTRL_CPU1RSTEN_MASK);
}

static int kick_core1(void)
{
    CLOCK_EnableClock(kCLOCK_Gpio0);
  
    GPIO_EnablePinControlNonSecure(BOARD_LED_RED_GPIO, (1 << BOARD_LED_RED_GPIO_PIN));
  
#ifdef CORE1_IMAGE_COPY_TO_RAM
    /* Calculate size of the image */
    uint32_t core1_image_size;
    core1_image_size = get_core1_image_size();
    rt_kprintf("Copy CORE1 image to address: 0x%x, size: %d\r\n", CORE1_BOOT_ADDRESS, core1_image_size);

    /* Copy application from FLASH to RAM */
    memcpy((void *)CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, core1_image_size);
#endif

    /* Start the secondary core */
    start_secondary_core(CORE1_BOOT_ADDRESS);
    
    return 0;
}

INIT_ENV_EXPORT(kick_core1);

修改后发现板子上的红色LED按照预期的闪烁了,说明core1已经运行起来。

CORE1 点灯代码如下周期闪烁:

/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016-2020 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "pin_mux.h"
#include "board.h"
#include "mcmgr.h"

#include "fsl_common.h"
#include "fsl_gpio.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define LED_INIT()   LED_RED_INIT(LOGIC_LED_ON)
#define LED_TOGGLE() LED_RED_TOGGLE()
/*******************************************************************************
 * Code
 ******************************************************************************/

/*!
 * @brief Application-specific implementation of the SystemInitHook() weak function.
 */
void SystemInitHook(void)
{
    /* Initialize MCMGR - low level multicore management library. Call this
       function as close to the reset entry as possible to allow CoreUp event
       triggering. The SystemInitHook() weak function overloading is used in this
       application. */
    (void)MCMGR_EarlyInit();
}


/*!
 * @brief Main function
 */
int main(void)
{
    uint32_t startupData, i;
    mcmgr_status_t status;

    /* Init board hardware.*/
    /* enable clock for GPIO */
    CLOCK_EnableClock(kCLOCK_Gpio0);
    BOARD_InitBootPins();

    /* Initialize MCMGR, install generic event handlers */
    (void)MCMGR_Init();

    /* Get the startup data */
    //do
    //{
    //    status = MCMGR_GetStartupData(&startupData);
    //} while (status != kStatus_MCMGR_Success);

    /* Make a noticable delay after the reset */
    /* Use startup parameter from the master core... */
    for (i = 0; i < startupData; i++)
    {
        SDK_DelayAtLeastUs(1000000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
    }

    /* Configure LED */
    LED_INIT();

    for (;;)
    {
        SDK_DelayAtLeastUs(500000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
        LED_TOGGLE();
    }

}

image.png

Core1 运行也可以正常运行。



专家
2024-11-09 04:51:42     打赏
2楼

看一下


助工
2024-11-09 14:52:32     打赏
3楼

好像没看到core1怎么点灯的


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]