请选择 进入手机版 | 继续访问电脑版
查看: 850|回复: 5

[分享] MCXN947与Zephyr的跨界合作

[复制链接]
  • TA的每日心情
    开心
    2020-12-18 12:56
  • 签到天数: 55 天

    [LV.5]常住居民I

    85

    主题

    236

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    1767
    最后登录
    2024-10-14
    发表于 2024-5-28 23:11:58 | 显示全部楼层 |阅读模式
    MCX N947成功初步移植Zephyr,标志着嵌入式技术的新飞跃,为物联网应用注入更强动力与智能。
    简介
    ·搭建 Zephyr 环境
    参考Zephyr Getting Started。在这篇 Zephyr 的官方文档中详细介绍了环境的搭建过程, 同时 NXP 也提供了工具解决 Zephyr 安装过程所需的依赖。
    ·了解 Zephyr 架构
    为了移植 Zephyr ,首先需要了解 Zephyr 的架构,理解其如何工作。在此处仅对其简单介绍,便于理解后续内容。
    ·构建系统
    Zephyr 使用 CMake 作为其构建系统,使用 Kconfig 进行配置。首先 CMake 通过收集相应配置并执行对应脚本,生成对应的编译脚本。

    Configuration Overflow

     Configuration Overflow
      
    Configuration Overflow
    ·Devicetree
    设备树是一种描述硬件及其配置的树形数据结构,如果对 MPU 开发领域有所深入对它可能会有所了解。Zephyr 使用设备树选择合适的驱动及配置。


    使用设备树可以在编译阶段确定硬件的配置是否合理,定义同一外设的多种不同工作模式便于切换, 同时使用设备树也让整个系统的复杂度增加。


    设备树的相关语法可参考 Zephyr Devicetree Syntax。


    移植
    对于适配新 SoC , Zephyr 官方目前资料不多。Zephyr SoC Porting,在该链接中简述了移植 Zephyr 的要求 。
    虽然资料很少,但移植工作也并非毫无头绪。Zephyr Github Repo本身便是一个详细的参考内容。
    ·SoC
    首先为新SoC建立相应目录
    soc/arm/nxp_mcx/
    |-- CMakeLists.txt
    |-- Kconfig
    |-- Kconfig.defconfig
    |-- Kconfig.soc
    `-- mcxnx4x
        |-- CMakeLists.txt
        |-- Kconfig.defconfig.mcxn947_cpu0
        |-- Kconfig.defconfig.mcxn947_cpu1
        |-- Kconfig.defconfig.series
        |-- Kconfig.series
        |-- Kconfig.soc
        |-- linker.ld
        |-- soc.c
        `-- soc.h
    整个文件结构可以参考同目录下的其他文件夹。
    ·Device tree
    soc 目录中主要为 Kconfig ,其中主要定义了 SoC 中的各种属性, 比如芯片的架构( Cortex-M33 )、有无 FPU ( CPU_HAS_FPU )等。
    在完成 SoC 的移植后,我们需要定义 SoC 的相关外设,但在这个阶段, 我们只需要对 FLASH 与 SRAM 做出定义即可,相应的驱动支持在后期进行适配。mcx n947 是一颗 Cortex-M33 架构的 CPU , 芯片使用了 Cortex-M33 定义的 TrustZone 功能, 将外设分为 Secure 和 Non-Secure 两部分。因此,在定义设备树时,需要考虑安全外设与非安全外设的不同地址。
    // dts/arm/nxp/nxp_mcxn947_common.dtsi
    // 在该 dtsi ( device tree source include )文件中仅定义到目前为止移植所需要的外设
    // 包括 SRAM 地址与大小, FLASH 地址与大小,中断优先级 BIT 数等等。
    #include <mem.h>
    #include <arm/armv8-m.dtsi>
    / {
        cpus: cpus {
            #address-cells = <1>;
            #size-cells = <0>;
            cpu@0 {
                compatible = "arm,cortex-m33f";
                reg = <0>;
            };
            cpu@1 {
                compatible = "arm,cortex-m33";
                reg = <1>;
            };
        };
    };
    &sram {
        #address-cells = <1>;
        #size-cells = <1>;
        sramx: memory@4000000 {
            compatible = "mmio-sram";
            reg = <0x4000000 DT_SIZE_K(96)>;
        };
        srama: memory@20000000 {
            compatible = "mmio-sram";
            reg = <0x20000000 DT_SIZE_K(32)>;
        };
        sramb: memory@20008000 {
            compatible = "mmio-sram";
            reg = <0x20008000 DT_SIZE_K(32)>;
        };
        sramc: memory@20010000 {
            compatible = "mmio-sram";
            reg = <0x20010000 DT_SIZE_K(64)>;
        };
        sramd: memory@20020000 {
            compatible = "mmio-sram";
            reg = <0x20020000 DT_SIZE_K(64)>;
        };
        srame: memory@20030000 {
            compatible = "mmio-sram";
            reg = <0x20030000 DT_SIZE_K(64)>;
        };
        sramf: memory@20040000 {
            compatible = "mmio-sram";
            reg = <0x20040000 DT_SIZE_K(64)>;
        };
        sramg: memory@20050000 {
            compatible = "mmio-sram";
            reg = <0x20050000 DT_SIZE_K(64)>;
        };
        sramh: memory@20060000 {
            compatible = "mmio-sram";
            reg = <0x20060000 DT_SIZE_K(32)>;
        };
    };
    &peripheral {
        #address-cells = <1>;
        #size-cells = <1>;
        fmu: flash-controller@43000 {
            compatible = "flash-controller";
            reg = <0x43000 0x1000>;
            #address-cells = <1>;
            #size-cells = <1>;
            status = "disabled";
            flash0: flash@0 {
                compatible = "soc-nv-flash";
                reg = <0x0 DT_SIZE_M(2)>;
            };
        };
    };
    &nvic {
        arm,num-irq-priority-bits = <3>;
    };
    // dts/arm/nxp/nxp_mcxn947_ns.dtsi
    // 在 ns ( None-Secure )配置中定义外设与 SRAM 的基础地址
    / {
        soc {
            sram: sram@4000000 {
                ranges = <0x4000000 0x4000000 0x20000000>;
            };
            peripheral: peripheral@40000000 {
                ranges = <0x0 0x40000000 0x10000000>;
            };
        };
    };
    #include "nxp_mcxn947_common.dtsi"
    ·Soc.c
    以目前的进度, soc.c 与 soc.h 中需要定义的内容不多。其中 soc.c 中需要定义芯片启动后的流程,如时钟初始化等等,在此处直接调用 SystemInit 图个方便。nxp_mcxnx4x_init 中定义了芯片初始化行为, 以目前的进度,还不需要做什么特殊操作,暂时留空。
    #include <soc.h>
    #include <zephyr/kernel.h>
    #include <zephyr/init.h>
    #include <fsl_common.h>
    static int nxp_mcxnx4x_init(void)
    {
        return 0;
    }
    #ifdef CONFIG_PLATFORM_SPECIFIC_INIT
    void z_arm_platform_init(void)
    {
        SystemInit();
    }
    #endif /* CONFIG_PLATFORM_SPECIFIC_INIT */
    SYS_INIT(nxp_mcxnx4x_init, PRE_KERNEL_1, 0);
    #ifndef _SOC__H_
    #define _SOC__H_
    #endif /* _SOC__H_ */
    ·Misc
    在移植过程中,还需要使用 MCUX SDK , Zephyr 已经提供了一份,其位于 zephyrproject/modules/hal/nxp 中, 但该版本中并没有包括本次移植目标的相关驱动与配置文件,所以将我们下载好的 SDK 整理并入文件夹中。同时修改对应 CMake 文件,使项目能够自动包含相关驱动文件。
    ·Board
    接下来定义 board ,只有定义 board 才能进行编译测试。该过程以手上的 mcxn947-evk 为例。
    最终创建的目录结构如下,在这仅仅创建了全部必须的配置文件,包括相应的配置与设备树, 为了方便测试,添加了 board.cmake ,该文件用来定义支持的下载方式与参数。
    boards/arm/mcxn947_evk/
    |-- Kconfig.board
    |-- Kconfig.defconfig
    |-- board.cmake
    |-- mcxn947_evk_ns.dts
    `-- mcxn947_evk_ns_defconfig
    # Kconfig.board
    config BOARD_MCXN947_EVK_CPU0
        bool "NXP MCXN947-EVK [CPU0]"
        depends on SOC_SERIES_MCXNX4X
        select SOC_PART_NUMBER_MCXN947VDF
    # Kconfig.defconfig
    if BOARD_MCXN947_EVK_CPU0
    config BOARD
        default "mcxn947_evk_cpu0" if BOARD_MCXN947_EVK_CPU0
    endif # BOARD_MCXN947_EVK_CPU0
    # mcxn947_evk_ns_defconfig
    CONFIG_SOC_SERIES_MCXNX4X=y
    CONFIG_SOC_MCXN947_CPU0=y
    CONFIG_BOARD_MCXN947_EVK_CPU0=y
    CONFIG_UART_CONSOLE=n
    CONFIG_CONSOLE=y
    CONFIG_RTT_CONSOLE=y
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000u
    /dts-v1/;
    #include <nxp/nxp_mcxn947_ns.dtsi>
    / {
        model = "NXP MCX N947 EVK";
        compatible = "nxp,mcxn947";
        cpus {
            /delete-node/ cpu@1;
        };
        chosen {
            zephyr,sram = &srama;
            zephyr,flash = &flash0;
        };
    };
    &flash0 {
        partitions {
            compatible = "fixed-partitions";
            #address-cells = <1>;
            #size-cells = <1>;
            boot_partition: partition@0 {
                label = "mcuboot";
                reg = <0x0 0x00008000>;
            };
            slot0_partition: partition@8000 {
                label = "image-0";
                reg = <0x00008000 0x00010000>;
            };
        };
    };
    # board.cmake
    board_runner_args(jlink "--device=MCXN947")
    include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
    到目前为止,我们仍未对时钟、引脚、串口等驱动进行适配,所以无法通过串口输出日志与 kprintf 。所以使用 RTT 进行输出, RTT 通过向特定内存区域buffer读写,结合调试器达成数据传输, 在目前无法驱动串口(后续工作)的情况下很有用,相关配置在 mcxn947_evk_ns_defconfig 中体现。默认情况下, CPU 时钟速度为 48MHz ,同样在 Kconfig 中定义。


    结论
    在全部移植完成后,使用 samples/hello_world 例子进行测试。执行指令 west build -b mcxn947_evk_ns samples/hello_world 进行编译。如果出现问题那就需要进行一些小修小改。
    最终编译结果如下:
    [133/133] Linking C executable zephyr\zephyr.elf
    Memory region         Used Size  Region Size  %age Used
               FLASH:       10844 B         2 MB      0.52%
                 RAM:        4944 B        32 KB     15.09%
            IDT_LIST:          0 GB         2 KB      0.00%
    因为在之前步骤中定义了下载方式,所以将硬件连接后直接执行指令 west flash 即可完成下载。
    最后打开 J-Link RTT Viewer 观察 RTT 内容。

    RTT Output

    RTT Output
    RTT Output
    至此, Zephyr 的初步移植工作已经结束,后续将会对常用外设进行移植。

    签到
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 13:01
  • 签到天数: 194 天

    [LV.7]常住居民III

    6

    主题

    510

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1015
    最后登录
    2024-11-10
    发表于 2024-5-29 00:05:23 | 显示全部楼层
    Zephyr 的设备树不错
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    8 小时前
  • 签到天数: 300 天

    [LV.8]以坛为家I

    18

    主题

    531

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1434
    最后登录
    2024-11-11
    发表于 2024-5-29 07:30:19 | 显示全部楼层
    zephyr非常值得学习。
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    6 小时前
  • 签到天数: 186 天

    [LV.7]常住居民III

    56

    主题

    783

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1856
    最后登录
    2024-11-11
    发表于 2024-5-29 09:11:30 | 显示全部楼层
    zephyr很少见,这个操作系统有什么优势吗?大佬能讲解一下吗
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2024-8-29 10:59
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    7

    主题

    1286

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2736
    最后登录
    2024-11-11
    发表于 2024-5-29 13:00:19 | 显示全部楼层
    zephyr可以支持多核?类似于linux的多核调度?
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 13:01
  • 签到天数: 194 天

    [LV.7]常住居民III

    6

    主题

    510

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1015
    最后登录
    2024-11-10
    发表于 2024-5-29 21:15:25 | 显示全部楼层
    oxlm 发表于 2024-5-29 13:00
    zephyr可以支持多核?类似于linux的多核调度?

    SMP不知道支持了吗
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-11-11 15:54 , Processed in 0.139644 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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