Zephyr 快速入门

DTS 快速入门

DTS 详细介绍请参考 DTS 介绍

DTS 语法和使用简介

快速入门请参考 DTS 基本语法一个实际硬件的例子

修改 DTS 配置

Zephyr 中 DTS 是分散在多个文件中的,详见 Zephyr 中 DTS 组织,修改 DTS 时修改哪个文件要视情况而定

修改某个 test/sample 的 DTS 配置:
  1. 到对应 test/sample 源码目录下(test 通常是 zephyr/tests/*/boards,sample 通常是 zephyr/samples/*/boards)新增对应 board 的 overlay 文件(如果尚不存在)并进行修改

  2. 如下 overlay 例子是增加一个 led 节点,设置相关 gpio 口,并为该节点取别名 led0

/ {
  aliases {
    led0 = &led_0;
  };

  gpio-led {
    compatible = "gpio-leds";
    led_0: led_0 {
      gpios = <&gpioa 25 0>;
    };
  };
};
  1. 如下例子是修改已有 DTS 中的配置(将 status 改为 okay

&gpioa {
  status = "okay";
};

如何确认 DTS 最终配置是否正确

Zephyr DTS 因为涉及多个文件,同一个配置项可能会被多处设置或重置,所以直接看某个文件不能反映最终的结果,需要:

  1. 检查修改(overlay)是否生效

  2. 检查某个设备的状态(okaydisabled)或属性设置是否符合预期

此时可以查看 build/zephyr/zephyr.dts 文件,它是最终生成的 DTS 文件

如何查看某个设备的 binding 文件

binding 文件介绍请参考 DTS binding

方法 1:
  1. 到定义设备的 dts 中找到其 compatible 字段,如:compatible = "realtek,ameba-rcc";

  2. 查找名为 realtek,ameba-rcc.yaml 文件,确认其中 compatible 值为 "realtek,ameba-rcc",则该文件为对应 binding 文件

注意

只有当 binding 文件的命名遵循了与 compatible 字段相同的规则时,才能使用该方法;但此规则在 Zephyr 中并非强制,若命名不一致,需要通过方法 2

在代码中如何访问 DTS

访问 DTS 通常是为了获取某个节点的属性或者驱动,可以参照如下步骤:

  1. 假如有 DTS 内容如下:

/ {
    soc {
        serial0: serial@40002000 {
            reg = <0x40002000 0x100>;
            status = "okay";
            current-speed = <115200>;
            /* ... */
        };
    };

    aliases {
        my-serial = &serial0;
    };

    chosen {
        zephyr,console = &serial0;
    };
};
  1. 首先获取某个节点标识符。DTS 中有多种方法标识一个节点,所以也对应多种方法获取节点标识符:

/* Option 1: by node label */
#define MY_SERIAL DT_NODELABEL(serial0)

/* Option 2: by alias */
#define MY_SERIAL DT_ALIAS(my_serial)

/* Option 3: by chosen node */
#define MY_SERIAL DT_CHOSEN(zephyr_console)

/* Option 4: by path */
#define MY_SERIAL DT_PATH(soc, serial_40002000)
  1. 上述代码中宏 MY_SERIAL 即表示节点标识符,利用它可以进一步得到节点属性或驱动

获取属性:
/* Demo 1: conditional compilation based on node status */
#if DT_NODE_HAS_STATUS(MY_SERIAL, okay)
//Desired code when node is okay(enabled)
#endif

/* Demo 2: get normal property */
uint32_t speed = DT_PROP(MY_SERIAL, current_speed);  //=115200

/* NOTE: some properties have an exclusive macro */
/* Demo 3: get reg info */
uint32_t addr = DT_REG_ADDR(MY_SERIAL);  //=0x40002000
uint32_t size = DT_REG_SIZE(MY_SERIAL);  //=0x100
  1. 更多进阶用法参考 扩展阅读

在 Kconfig 中如何访问 DTS

参考:Kconfig 快速入门

在 CMake 中如何访问 DTS

参考:CMake 快速入门

如何定位 undefined reference 的 DTS 符号问题

  • DTS 中定义的节点会在驱动代码中被定义为某个符号,其标识符是按照某些编码规范生成,如 __device_dts_ord_22

  • 实际使用中可能会遇到类似如下的编译错误:

    /opt/rtk-toolchain/asdk-12.3.1-4431/linux/newlib/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld.bfd: app/libapp.a(test_counter.c.obj):(.rodata.devices+0x0): undefined reference to `__device_dts_ord_22'
    
  • 出现该问题的原因通常是驱动层之上的代码引用了一个符号(驱动实例),但链接时没有找到该驱动实例的符号定义(代码实现)

  • 这里无法直接通过名字 __device_dts_ord_22 定位到相关的代码区域,下面给出一个针对上述错误的排查流程

  1. 首先定位出问题的 DTS 节点:通过 test_counter.c.obj 可以确定引用该符号的源文件是 test_counter.c,此时可以选择直接查看该文件,分如下两种情况:

    1. 如果只有一个驱动实例引用,就可以通过代码确定对应的 DTS 节点信息(节点名称,label 等),例如可能有如下代码:

      #define I2C_DEV_NODE DT_ALIAS(i2c_0)
      const struct device *const i2c_dev = DEVICE_DT_GET(I2C_DEV_NODE);
      

      此时可以很容易判断是 i2c_0 这个 DTS 节点对应设备的驱动定义有问题

    2. 如果代码复杂,有多个驱动实例引用或复杂的预处理逻辑,则可以通过生成预处理文件直接精确定位 DTS 节点,步骤如下

      1. 在文件 build/compile_commands.json 中查找 test_counter.c.obj,可以定位到如下一个位置(其中 xxx 表示被省略的部分内容):

        {
          "directory": "/xxx/build",
          "command": "/xxx/arm-none-eabi-gcc xxx -o CMakeFiles/app.dir/src/test_counter.c.obj -c /xxx/zephyr/tests/drivers/counter/counter_basic_api/src/test_counter.c",
          "file": "/xxx/zephyr/tests/drivers/counter/counter_basic_api/src/test_counter.c",
          "output": "CMakeFiles/app.dir/src/test_counter.c.obj"
        },
        
      2. 其中 command 字段是编译 test_counter.c 的完整命令,需要对完整的该命令稍作修改:-o 后的输出路径改为新文件名(如 test_counter.i),-c 改为 -E ,然后在终端执行:

        /xxx/arm-none-eabi-gcc xxx -o test_counter.i -E /xxx/zephyr/tests/drivers/counter/counter_basic_api/src/test_counter.c",
        
      3. 此时会在执行目录生成一个文件 test_counter.i,打开该文件搜索未定义符号 __device_dts_ord_22 可以找到如下内容:

        static const struct device *const devices[] = {
        # 63 "/xxx/zephyr/tests/drivers/counter/counter_basic_api/src/test_counter.c"
        
        # 124 "/xxx/zephyr/tests/drivers/counter/counter_basic_api/src/test_counter.c"
        (&__device_dts_ord_22), (&__device_dts_ord_23), (&__device_dts_ord_24), (&__device_dts_ord_25),
        # 144 "/xxx/zephyr/tests/drivers/counter/counter_basic_api/src/test_counter.c"
        };
        
      4. 通过上述第 4,5 行可知 __device_dts_ord_22 是在源文件 124 行引用的,定位到该行代码如下:

        #ifdef CONFIG_COUNTER_TMR_AMEBA
          DEVS_FOR_DT_COMPAT(realtek_ameba_counter)
        #endif
        
      5. 由此可知是 compatiblerealtek,ameba-counter 的 DTS 节点对应设备的驱动定义有问题

  2. 排查 DTS 节点对应的驱动定义问题,可以参考以下思路:

    • DTS 节点不存在或未使能(status 未设置为 okay),可以参考 如何确认 DTS 最终配置是否正确

    • DTS 节点对应驱动代码未加入编译,这里要检查相关驱动的 CMakeLists.txt 或 Kconfig 配置

    • DTS 节点驱动代码中编码问题,例如 DT_DRV_COMPAT 宏定义是否正确等

Kconfig 快速入门

在 Kconfig 中获取 DTS 信息

Zephyr 提供了一系列接口,用于在 Kconfig 中访问 DTS 信息,更多内容请参考 Devicetree-related Functions

使用示例如下:

config AMEBA_PSRAM
  def_bool y if $(dt_nodelabel_enabled,psram)  # init bool value by node state

config AMEBA_PSRAM_SIZE
  hex
  depends on AMEBA_PSRAM
  default $(dt_nodelabel_reg_size_hex,psram)  # init hex value by node reg's size cell

对应的 DTS 配置如下:

psram: memory@60000000 {
  compatible = "zephyr,memory-region";
  device_type = "memory";
  reg = <0x60000000 DT_SIZE_M(4)>;   /* dt_nodelabel_reg_size_hex reads size from here */
  zephyr,memory-region = "PSRAM";
  status = "disabled";               /* dt_nodelabel_enabled reads status from here */
};

CMake 快速入门

在 CMake 中获取 DTS 信息

Zephyr 提供了一系列接口,用于在 CMake 中访问 DTS 信息,具体实现可参考 zephyr/cmake/modules/extensions.cmake

常用 API 说明如下:

API

Description

dt_nodelabel()

Function for retrieving the node path for the node having nodelabel

dt_alias()

Get a node path for an /aliases node property

dt_node_exists()

Tests whether a node with path <path> exists in the devicetree

dt_node_has_status()

Tests whether <path> refers to a node which exists in the devicetree, and has a status property matching the <status> argument

dt_prop()

Get a devicetree property value. The value will be returned in the <var> parameter

dt_comp_path()

Get a list of paths for the nodes with the given compatible. The value will be returned in the <var> parameter

dt_num_regs()

Get the number of register blocks in the node's reg property

dt_reg_addr()

Get the base address of the register block at index <idx>, or with name <name>

dt_reg_size()

Get the size of the register block at index <idx>, or with name <name>

dt_has_chosen()

Test if the devicetree's /chosen node has a given property <prop> which contains the path to a node

dt_chosen()

Get a node path for a /chosen node property

NVIC 快速入门

NVIC 详细介绍请参考 NVIC 介绍

Zephyr 中断使用说明

在 Zephyr 中开发驱动使用中断需要完成几个关键步骤,即可正常响应中断。

下面将给出一个使用示例,并列举其中的关键步骤。

代码示例

DTS 配置:

中断设备树配置示例
 1nvic: interrupt-controller@e000e100 {
 2   #address-cells = < 0x1 >;
 3   compatible = "arm,v8.1m-nvic";
 4   reg = < 0xe000e100 0xc00 >;
 5   interrupt-controller;
 6   #interrupt-cells = < 0x2 >;
 7   arm,num-irq-priority-bits = < 0x3 >;
 8   phandle = < 0x1 >;
 9};
10timer0: counter@40819000 {
11   compatible = "realtek,ameba-counter";
12   reg = <0x40819000 0x30>;
13   clocks = <&rcc AMEBA_LTIM0_CLK>;
14   interrupts = <7 0>;
15   clock-frequency = <32768>;
16   status = "disabled";
17};

C 代码实现:

中断驱动代码实现示例
 1#define DT_DRV_COMPAT realtek_ameba_counter
 2...
 3
 4void counter_ameba_isr(const struct device *dev)
 5{
 6}
 7
 8#define TIMER_IRQ_CONFIG(n)                                                                        \
 9   static void irq_config_##n(const struct device *dev)                                       \
10   {                                                                                          \
11      IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), counter_ameba_isr,          \
12            DEVICE_DT_INST_GET(n), 0);                                             \
13      irq_enable(DT_INST_IRQN(n));                                                       \
14   }
15
16#define AMEBA_COUNTER_INIT(n)                                                                      \
17   TIMER_IRQ_CONFIG(n)                                                                        \
18   ...
19
20DT_INST_FOREACH_STATUS_OKAY(AMEBA_COUNTER_INIT);

关键步骤

  1. 确认硬件支持, DTS 中配置中断信息。

    如上 中断设备树配置示例 中高亮行 14 行所示设置驱动的中断属性, interrupts 有两个入参,第一个是中断号,第二个是中断优先级。

  2. 驱动代码中实现中断服务函数,注册中断时需要用到,如上 中断驱动代码实现示例 4-6 行。

  3. 驱动代码中从 DTS 获取中断优先级等属性,注册中断时需要用到,如上 中断驱动代码实现示例 11 行。 详细介绍请参考 获取中断属性

    /*获取中断号*/
    DT_INST_IRQN(n);
    /*获取中断优先级*/
    DT_INST_IRQ(n, priority);
    
  4. 驱动代码中注册中断,如上 中断驱动代码实现示例 11 行。 详细介绍请参考 中断注册

  5. 驱动代码中启用中断,如上 中断驱动代码实现示例 13 行。 详细介绍请参考 启用/关闭中断

文件系统 快速入门

文件系统详细介绍请参考 文件系统介绍

LittleFS on FLASH

示例路径: zephyr/samples/subsys/fs/littlefs/

使用以下命令编译 LittleFS on FLASH 示例(将 <BOARD> 替换为实际开发板名称):

./nuwa.py build zephyr/samples/subsys/fs/littlefs -b <BOARD>

如需自定义 DTS,请参考 LittleFS on FLASH 示例 进行配置。

可通过最终生成的 DTS 文件 build/zephyr/zephyr.dts 验证 DTS 配置是否正确:

  • spic 的 status = "okay"

  • LittleFS 使用的 partition 起始地址和大小符合预期

遇到链接错误时,通常是某些 Kconfig 选项未启用。 可通过 build/zephyr/include/generated/zephyr/autoconf.h 检查当前的 Kconfig 配置。

LittleFS on FLASH 需要在 prj.conf 中启用以下配置:

CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y

FatFS on SD

示例路径: zephyr/samples/subsys/fs/fs_sample/

使用以下命令编译 FatFS on SD 示例(将 <BOARD> 替换为实际开发板名称):

./nuwa.py build zephyr/samples/subsys/fs/fs_sample -b <BOARD>

遇到链接错误时,通常是某些 Kconfig 选项未启用。 可通过 build/zephyr/include/generated/zephyr/autoconf.h 检查当前的 Kconfig 配置。

FatFS on SD 需要在 prj.conf 中启用以下配置:

CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVERS=y

Settings 快速入门

Settings 详细介绍请参考 Settings 介绍

示例路径: zephyr/samples/subsys/settings/

使用以下命令编译 Settings 示例:

./nuwa.py build zephyr/samples/subsys/settings -b <BOARD>

可参考 Settings 配置 配置 DTS。

Debug 快速入门

Debug 详细介绍请参考 Debug 介绍

Debug 简介

Debug 包括两部分:

  • 离线调试:不直接连接正在运行的目标。通过采集日志、coredump、跟踪数据、性能采样文件等离线数据,在本地或分析工具中复盘问题。

  • 在线调试:调试工具直接连接到正在运行的目标系统(例如通过 JTAG/SWD、GDB 远程、网络/串口),在真实环境中进行断点、单步、变量查看与修改、寄存器/内存访问等操作。

离线调试

下面介绍一种分析 coredump 日志的离线调试方法。

配置

配置详细介绍可查看 coredump 配置

配置示例:

CONFIG_DEBUG_COREDUMP=y                 #启用 coredump 模块
CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y #使用日志模块获取 coredump 输出
CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y #仅转储异常线程的堆栈、其线程结构以及一些其他最基本的必要数据

获取 coredump

转储内容详细介绍可查看 转储格式

根据已启用的后端,从设备获取 coredump 信息。比如启用的日志后端,可以通过日志工具保存打印的日志,获取日志文件 coredump.log。

解析

解析详细介绍可查看 解析步骤

使用日志后端解析 coredump 步骤如下:

  1. 运行 coredump 串行日志转换器,提取 coredump.log 中 coredump 部分数据,生成 coredump.bin :

    ./zephyr/scripts/coredump/coredump_serial_log_parser.py coredump.log coredump.bin
    
  2. 启动自定义 GDB 服务器,解析 zephyr.elf 和 coredump.bin,获取符号表和异常堆栈等信息,以供 gdb 调试器查询:

    ./zephyr/scripts/coredump/coredump_gdbserver.py build/zephyr/zephyr.elf coredump.bin
    
  3. 启动 GDB 调试器:

    arm-none-eabi-gdb build/zephyr/zephyr.elf
    
  4. 在 GDB 内部,通过端口 1234 连接到 GDB 服务器:

    (gdb) target remote localhost:1234
    

也可以从 GDB 内部启动 GDB 服务器:

  1. 启动 GDB :

    arm-none-eabi-gdb  build/zephyr/zephyr.elf
    
  2. 在 GDB 内部,使用以下选项启动 GDB 服务器 --pipe

    (gdb) target remote |
    ./scripts/coredump/coredump_gdbserver.py --pipe build/zephyr/zephyr.elf coredump.bin
    

然后就可以使用 gdb 命令查看异常信息,比如:

  • 检查 CPU 寄存器: info registers

  • 查看回溯信息: bt

在线调试

在线调试详细介绍可查看 在线调试

下面介绍使用 gdb 进行在线调试的方法,需要使用 Jlink 连接开发板和电脑,介绍三种典型场景。

使用 gdb 命令行调试的方式:

备注

  • PA18、PA19 不能被占用。

  1. 代码在 windows 电脑,开发板通过 jlink 与 windows 电脑连接,使用 west debug 调试。直接在 windows 上使用 west debug 命令:

    west debug
    

    输出如下:

    PS D:\code\nuwa> west debug
    -- west debug: rebuilding
    ninja: no work to do.
    -- west debug: using runner jlink
    -- runners.jlink: reset after flashing requested
    -- runners.jlink: JLink version: 8.40
    -- runners.jlink: J-Link GDB server running on port 2335; no thread info available
    GNU gdb (Realtek ASDK-12.3.1 Build 4431) 12.1.90.20221114-git
    Copyright (C) 2022 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    Type "show copying" and "show warranty" for details.
    This GDB was configured as "--host=x86_64-w64-mingw32 --target=arm-none-eabi".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <https://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
        <http://www.gnu.org/software/gdb/documentation/>.
    
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from D:\code\nuwa\build\zephyr\zephyr.elf...
    Remote debugging using :2335
    __enable_irq () at D:/code/nuwa/modules/hal/cmsis_6/CMSIS/Core/Include/cmsis_gcc.h:800
    800       __ASM volatile ("cpsie i" : : : "memory");
    Resetting target
    (gdb)
    
  2. 代码在 linux 服务器,开发板通过 jlink 与 windows 电脑连接,使用 gdb 命令行工具调试。

    1. 在 windows 手动启动 JLinkGDBServer 连接开发板;

      可以使用 sdk/amebagreen2_gcc_project/utils/jlink_script/ap_jlinkGDBSever.bat 启动 JLinkGDBServer,脚本中已经有一些配置,可以直接连接 AP 核,双击脚本即可启动。

      备注

      ap_jlinkGDBSever.bat 脚本默认使用 -device Cortex-M33。由于 rtl8721f 使用 Cortex-M55 核,运行脚本前需要将其改为 -device Cortex-M55,或者直接使用 west debug 命令(它会通过 board.cmake 自动使用正确的 CPU 型号)。

    2. 在 linux 服务器启动 gdb 调试器连接 JLinkGDBServer。

      ~/code/nuwa$ arm-none-eabi-gdb build/zephyr/zephyr.elf
      (gdb) target remote <windows-ip>:2335
      
  3. 代码在 linux 服务器,开发板通过 jlink 与 windows 电脑连接,使用 west debug 命令行调试。

    1. 首先在 windows 上启动 JLinkRemoteServer;

      直接双击 JLinkRemoteServer 软件启动,需要选择一个 port,用于监听 linux 服务器上 JLinkGDBServer 的连接。

      ../../_images/zephyr_debug_JLinkRemoteServer_port.png
    2. 在 linux 服务器上使用 west debug 命令。需要添加一个 -i ip:port 参数用于连接 windows 上的 JLinkRemoteServer。port 需要与步骤 A 中设置的相同。

      west debug -i ip:port
      

MCUboot 快速入门

MCUboot 详细介绍请参考 MCUboot 介绍

编译 MCUboot 示例

本节以 zephyr/samples/sysbuild/with_mcuboot 为例,它是启用 MCUboot 的最小工程,仅包含必要的配置。

RTL8721Dx:
  1. 编译,执行命令:

./nuwa.py build -b rtl872xda_evb//mcuboot zephyr/samples/sysbuild/with_mcuboot --sysbuild
  1. 固件位于 SDK 根目录的 images/ 目录下,烧录方法参考 固件下载

  2. 通过 Trace Tool 查看串口日志,看到如下日志即表示 km0km4 两个 CPU 都成功运行:

    [MAIN-I] KM0 OS START
    *** Booting Zephyr OS build f998faa02fe0 ***
    Hello sysbuild with mcuboot! rtl872xda_evb
    

备注

通过 ImageTool 下载固件时,每个固件的 Start AddrEnd Addr 必须与 DTS 中 flash layout 配置一致,地址计算方式见 Flash Layout

创建自己的应用

将上面的示例目录整体拷贝到自定义位置(记为 <APP_DIR>),按需修改后编译,编译命令中的工程路径替换为该 <APP_DIR> 即可。

sysbuild 编译时可通过两个配置文件调整 MCUboot 相关配置:

  • <APP_DIR>/sysbuild.conf:sysbuild(整机)层级配置,用于设置 SB_CONFIG_* 选项。例如选择 OTA 升级模式(不指定时顶层默认 swap_using_move,也可指定 swap_using_offset 等其它模式):

    SB_CONFIG_MCUBOOT_MODE_SWAP_USING_OFFSET=y
    
  • <APP_DIR>/sysbuild/mcuboot.conf:仅作用于 MCUboot bootloader 固件的 Kconfig 片段,合并在板级配置(zephyr/boards/realtek/<board>/<board>_mcuboot_defconfig 等)之后,可覆盖其默认值。

固件签名

MCUboot 在启动 app 前会校验其签名,校验不通过则拒绝启动。签名以 TLV 形式附加在 固件尾部,bootloader 内置对应公钥用于校验。Ameba 平台支持两种签名密钥来源。

使用 MCUboot 自带密钥签名

Zephyr/MCUboot 的默认方式,通过 sysbuild 配置选择签名算法与密钥文件:

  • 签名算法:SB_CONFIG_BOOT_SIGNATURE_TYPE_RSA / SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 / SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519(默认 RSA)。

  • 密钥文件:SB_CONFIG_BOOT_SIGNATURE_KEY_FILE 指定签名私钥(PEM)。不指定时使用 MCUboot 自带的示例密钥(如 root-ec-p256.pem),仅供开发调试,量产须替换为自己的密钥。

使用 manifest.json5 中的密钥签名

Ameba ROM 使用 manifest.json5 中的密钥对 bootloader 进行签名(secure boot)。为便于维护,app 的 MCUboot 签名可复用同一套密钥(仅支持 ECDSA_P256ED25519)。步骤如下:

  1. <APP_DIR>/sysbuild/mcuboot.conf 中添加:CONFIG_AMEBA_USING_MANIFEST_KEY=y

  2. <APP_DIR>/sysbuild.conf 中添加:SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="\${APP_DIR}/my.key"

  3. manifest.json5 中更新你的密钥

  4. 执行编译。cmake 会自动把 manifest.json5 中 app(image2)的密钥按所选算法转换为 MCUboot 所需的 PEM 格式,输出到上面指定的 $APP_DIR/my.key 供签名使用

固件加密

Ameba 平台支持两种相互独立的固件加密方式。

使用 MCUboot 自带加密

即 MCUboot 的 encrypted images 特性,主要用于加密 OTA 升级固件:固件体以 AES-CTR 加密,AES 密钥再用非对称算法(ECIES-P256、ECIES-X25519、RSA-OAEP、AES-KW 之一)封装后随固件下发,设备在搬运/升级时解密。仅适用于 swap、overwrite-only 等需要搬运固件的升级模式(不支持 direct-XIP)。

  • 通过 SB_CONFIG_BOOT_ENCRYPTION 启用,SB_CONFIG_BOOT_ENCRYPTION_KEY_FILE 指定加密密钥(PEM),SB_CONFIG_BOOT_ENCRYPTION_ALG_AES_128 / SB_CONFIG_BOOT_ENCRYPTION_ALG_AES_256 选择 AES 密钥长度。

  • 启用后编译会额外输出加密固件 zephyr.signed.encrypted.bin

使用 RSIP 加密

RSIP 是 Ameba 的硬件 flash 加密:固件以密文烧录到 flash,运行时由硬件在总线上实时解密,XIP 场景无需先解密到 RAM。详细介绍和配置步骤可参考 安全固件保护(RSIP) 。相关配置位于 manifest.json5`(:file:`modules/hal/realtek/ameba/<SOC_NAME>/manifest.json5),在其中设置 rsip_enable、加密模式(XTS/CTR)与密钥等;编译时其 IV 会以自定义 TLV 附加到固件上。

Twister 快速入门

Twister 详细介绍请参考 Twister 介绍

运行 Twister 的基本步骤如下:

  1. 参考 Twister 环境搭建 完成环境准备。

  2. 确保开发板能进入烧录状态,以便 Twister 在每轮测试之间自动烧录固件:

    • 对于支持硬件进入烧录状态的板子,无需额外配置。

    • 其它板子需要预先烧录一个支持 reboot uartburn 命令(配置 CONFIG_SHELL=y)的固件,Twister 通过该命令让板子进入烧录状态。

    可先在 tracetool 上手动输入 reboot uartburn 验证该命令是否生效,期望看到以下回显:

    uart:~$ reboot uartburn
    [BOOT-I] ROM:[V1.0]
    [BOOT-I] FLASH RATE:1, Pinmux:0
    [BOOT-I] BOOT FROM NOR
    Flash Download Start
    
  3. 在 nuwa 工作区根目录下跑一个基础的 kernel 测试套件,验证 Twister 编译、烧录流程是否正确。例如:

    Linux (Ubuntu):
    ./nuwa.py twister --device-testing \
      --flash-before --west-flash="--port=/dev/ttyUSB0" --device-serial /dev/ttyUSB0 --device-serial-baud 1500000 \
      --platform rtl8721f_evb \
      -T zephyr/tests/kernel/threads/dynamic_thread_stack/ \
      --test kernel.threads.dynamic_thread.stack.no_pool.no_alloc.no_user
    

    备注

    根据实际情况,替换上述命令中 --west-flash--device-serial 指定的串口,以及 --platform 指定的平台。

    在输出界面上,期望看到以下的 passed 信息:

    INFO    - Total complete:    1/   1  100%  built (not run):    0, filtered:    0, failed:    0, error:    0
    INFO    - 1 test scenarios (1 configurations) selected, 0 configurations filtered (0 by static filter, 0 at runtime).
    INFO    - 1 of 1 executed test configurations passed (100.00%), 0 built (not run), 0 failed, 0 errored, with no warnings in 394.83 seconds.
    INFO    - 1 of 1 executed test cases passed (100.00%) on 1 out of total 1118 platforms (0.09%).
    INFO    - 3 selected test cases not executed: 3 skipped.
    INFO    - 1 test configurations executed on platforms, 0 test configurations were only built.
    
    Hardware distribution summary:
    
    | Board                 | ID   |   Counter |   Failures |
    |-----------------------|------|-----------|------------|
    | rtl8721f_evb/rtl8721f |      |         1 |          0 |
    INFO    - Saving reports...
    ......
    

    如果遇到错误,可以参考 Twister 测试失败定位

  4. 上述步骤通过后,可认为 Twister 的基本流程已经打通。接下来可以进一步运行指定的测试用例。

    如何通过命令行参数选择测试用例范围,详见 Twister 使用方法

    如何批量运行自定义测试集,详见 自定义批量测试集