MCX N947成功初步移植Zephyr,標(biāo)志著嵌入式技術(shù)的新飛躍,為物聯(lián)網(wǎng)應(yīng)用注入更強(qiáng)動(dòng)力與智能。
簡(jiǎn)介
搭建 Zephyr 環(huán)境
參考Zephyr Getting Started。在這篇 Zephyr 的官方文檔中詳細(xì)介紹了環(huán)境的搭建過(guò)程, 同時(shí) NXP 也提供了工具解決 Zephyr 安裝過(guò)程所需的依賴(lài)。
了解 Zephyr 架構(gòu)
為了移植 Zephyr ,首先需要了解 Zephyr 的架構(gòu),理解其如何工作。在此處僅對(duì)其簡(jiǎn)單介紹,便于理解后續(xù)內(nèi)容。
構(gòu)建系統(tǒng)
Zephyr 使用 CMake 作為其構(gòu)建系統(tǒng),使用 Kconfig 進(jìn)行配置。首先 CMake 通過(guò)收集相應(yīng)配置并執(zhí)行對(duì)應(yīng)腳本,生成對(duì)應(yīng)的編譯腳本。
? ? ? ? ? ? ? ? ? ?Configuration Overflow
Devicetree
設(shè)備樹(shù)是一種描述硬件及其配置的樹(shù)形數(shù)據(jù)結(jié)構(gòu),如果對(duì) MPU 開(kāi)發(fā)領(lǐng)域有所深入對(duì)它可能會(huì)有所了解。Zephyr 使用設(shè)備樹(shù)選擇合適的驅(qū)動(dòng)及配置。
使用設(shè)備樹(shù)可以在編譯階段確定硬件的配置是否合理,定義同一外設(shè)的多種不同工作模式便于切換, 同時(shí)使用設(shè)備樹(shù)也讓整個(gè)系統(tǒng)的復(fù)雜度增加。
設(shè)備樹(shù)的相關(guān)語(yǔ)法可參考 Zephyr Devicetree Syntax。
移植
對(duì)于適配新 SoC , Zephyr 官方目前資料不多。Zephyr ?SoC Porting,在該鏈接中簡(jiǎn)述了移植 Zephyr 的要求 。
雖然資料很少,但移植工作也并非毫無(wú)頭緒。ZephyrGithub Repo本身便是一個(gè)詳細(xì)的參考內(nèi)容。
SoC
首先為新SoC建立相應(yīng)目錄
?
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
?
整個(gè)文件結(jié)構(gòu)可以參考同目錄下的其他文件夾。
Devicetree
soc 目錄中主要為 Kconfig ,其中主要定義了 SoC 中的各種屬性, 比如芯片的架構(gòu)( Cortex-M33 )、有無(wú) FPU ( CPU_HAS_FPU )等。
在完成 SoC 的移植后,我們需要定義 SoC 的相關(guān)外設(shè),但在這個(gè)階段, 我們只需要對(duì) FLASH 與 SRAM 做出定義即可,相應(yīng)的驅(qū)動(dòng)支持在后期進(jìn)行適配。mcx n947 是一顆 Cortex-M33 架構(gòu)的 CPU , 芯片使用了 Cortex-M33 定義的 TrustZone 功能, 將外設(shè)分為 Secure 和 Non-Secure 兩部分。因此,在定義設(shè)備樹(shù)時(shí),需要考慮安全外設(shè)與非安全外設(shè)的不同地址。
?
// dts/arm/nxp/nxp_mcxn947_common.dtsi
?
// 在該 dtsi ( device tree source include )文件中僅定義到目前為止移植所需要的外設(shè)
// 包括 SRAM 地址與大小, FLASH 地址與大小,中斷優(yōu)先級(jí) BIT 數(shù)等等。
?
#include#include / { 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 )配置中定義外設(shè)與 SRAM 的基礎(chǔ)地址 / { soc { sram: sram@4000000 { ranges = <0x4000000 0x4000000 0x20000000>; }; peripheral: peripheral@40000000 { ranges = <0x0 0x40000000 0x10000000>; }; }; }; #include "nxp_mcxn947_common.dtsi"
?
Soc.c
以目前的進(jìn)度, soc.c 與 soc.h 中需要定義的內(nèi)容不多。其中 soc.c 中需要定義芯片啟動(dòng)后的流程,如時(shí)鐘初始化等等,在此處直接調(diào)用 SystemInit 圖個(gè)方便。nxp_mcxnx4x_init 中定義了芯片初始化行為, 以目前的進(jìn)度,還不需要做什么特殊操作,暫時(shí)留空。
?
#include#include #include #include 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
在移植過(guò)程中,還需要使用 MCUX SDK , Zephyr 已經(jīng)提供了一份,其位于 zephyrproject/modules/hal/nxp 中, 但該版本中并沒(méi)有包括本次移植目標(biāo)的相關(guān)驅(qū)動(dòng)與配置文件,所以將我們下載好的 SDK 整理并入文件夾中。同時(shí)修改對(duì)應(yīng) CMake 文件,使項(xiàng)目能夠自動(dòng)包含相關(guān)驅(qū)動(dòng)文件。
Board
接下來(lái)定義 board ,只有定義 board 才能進(jìn)行編譯測(cè)試。該過(guò)程以手上的 mcxn947-evk 為例。
最終創(chuàng)建的目錄結(jié)構(gòu)如下,在這僅僅創(chuàng)建了全部必須的配置文件,包括相應(yīng)的配置與設(shè)備樹(shù), 為了方便測(cè)試,添加了 board.cmake ,該文件用來(lái)定義支持的下載方式與參數(shù)。
?
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/ { 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)
?
到目前為止,我們?nèi)晕磳?duì)時(shí)鐘、引腳、串口等驅(qū)動(dòng)進(jìn)行適配,所以無(wú)法通過(guò)串口輸出日志與 kprintf 。所以使用 RTT 進(jìn)行輸出, RTT 通過(guò)向特定內(nèi)存區(qū)域buffer讀寫(xiě),結(jié)合調(diào)試器達(dá)成數(shù)據(jù)傳輸, 在目前無(wú)法驅(qū)動(dòng)串口(后續(xù)工作)的情況下很有用,相關(guān)配置在 mcxn947_evk_ns_defconfig 中體現(xiàn)。默認(rèn)情況下, CPU 時(shí)鐘速度為 48MHz ,同樣在 Kconfig 中定義。
結(jié)論
在全部移植完成后,使用 samples/hello_world 例子進(jìn)行測(cè)試。執(zhí)行指令 west build -b mcxn947_evk_nssamples/hello_world 進(jìn)行編譯。如果出現(xiàn)問(wèn)題那就需要進(jìn)行一些小修小改。
最終編譯結(jié)果如下:
?
[133/133] Linking C executable zephyrzephyr.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%
?
因?yàn)樵谥安襟E中定義了下載方式,所以將硬件連接后直接執(zhí)行指令 west flash 即可完成下載。
最后打開(kāi) J-Link RTT Viewer 觀察 RTT 內(nèi)容。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?RTT Output
至此, Zephyr 的初步移植工作已經(jīng)結(jié)束,后續(xù)將會(huì)對(duì)常用外設(shè)進(jìn)行移植。
評(píng)論
查看更多