news 2026/4/17 14:05:18

基于SF32创建Zephyr 应用工程并获取设备树节点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于SF32创建Zephyr 应用工程并获取设备树节点

一、创建自己的 Zephyr 应用工程

除去以下方法,也可以参考官网提供的办法:zephyr官方文档

想要快速创建一个属于自己的 Zephyr 应用工程,最直接的方法是复制并修改现有的示例工程。下面以helloworld为例,介绍具体步骤:

1. 复制工程
在 Zephyr 项目目录中(例如zephyrproject/zephyr),找到samples/hello_world文件夹。将其复制到你希望存放自定义项目的目录中,并可以重命名(例如my_app)。

2. 配置环境(推荐)
在终端中激活 Zephyr 开发环境,执行以下命令。在编译后将会生成compile_commands.json文件。该文件能帮助 VS Code 实现精确的代码跳转和智能提示。

west config build.cmake-args -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

3. 编译工程
切换到你的应用工程目录(例如my_app),执行编译命令。这里以sf32lb52_devkit_lcd开发板为例。(切换到工程目录下编译是为了在当前工程目录下生成build文件夹,方便代码转跳和提示以及查看生成的文件)

west build -p always -b sf32lb52_devkit_lcd

编译成功后,会在build目录下生成zephyr.elfzephyr.bin等固件文件,同时也会生成compile_commands.json文件,从而启用代码跳转功能。


二、设备树(Devicetree)简介

如果想更详细的了解请参考 Zephyr 官方文档:zephyr官方文档-设备树

1. 设备树简介

设备树是一种描述硬件资源的层次化数据结构。在 Zephyr 中,它用于将硬件配置信息从驱动代码中分离出来,提高代码的可移植性。

设备树的处理流程主要涉及两种输入文件:

  • 设备树源文件(.dts / .dtsi):描述具体板级或 SoC 的硬件构成。
  • 设备树绑定文件(.yaml):定义节点属性的格式、约束和含义,用于验证.dts文件。

构建系统(如 CMake)会根据这些文件生成一个 C 头文件(devicetree_generated.h),供应用程序和驱动程序通过统一的 API 访问硬件信息。

2. 节点(Node)

设备树由节点组成,以树形结构组织,根节点为/

2.1 节点层级与路径
  • 根节点:整个设备树的起点,路径为/
  • 父子关系:子节点必须定义在父节点内部,这反映了硬件的物理连接或逻辑归属关系。例如,一个 I2C 传感器节点必须定义在其所属的 I2C 控制器节点之下。
    // 示例:I2C总线及其设备 / { // 根节点 soc { // 片上系统节点 i2c0: i2c@40003000 { // I2C控制器节点 compatible = "nordic,nrf-twim"; reg = <0x40003000 0x1000>; apds9960@39 { // I2C传感器(子节点) compatible = "avago,apds9960"; reg = <0x39>; // I2C从地址 }; }; }; };
  • 节点路径:通过从根节点到目标节点的所有名称连接而成,类似文件系统路径。例如,上述传感器的路径是/soc/i2c@40003000/apds9960@39
2.2 节点标识

为了便于引用节点,设备树提供了几种标识方法:

  • 节点标签(Label):在节点定义时,可以为其附加一个唯一的标签。之后可以通过&标签名来引用该节点,无需写出冗长的路径。
    led0: led { // 定义标签 `led0` label = "User LED"; gpios = <&gpioa 5 GPIO_ACTIVE_HIGH>; }; // 在其他地方使用标签引用 &led0 { status = "okay"; };
  • 单元地址(Unit Address):节点名中@符号后的部分,用于表示节点在父节点地址空间中的位置。其含义因硬件类型而异:
    硬件类型单元地址含义示例
    内存映射外设寄存器基地址uart@40001000
    I2C 设备I2C 从机地址eeprom@50
    SPI 设备片选(CS)线编号flash@0
    内存/Flash起始地址memory@80000000

3. Aliases 和 Chosen 节点

这两个特殊节点提供了全局引用特定节点的方式。

  • aliases节点:为节点定义简短别名,常用于为通用功能(如led0,i2c-1)指定具体硬件。
    aliases { my-uart = &uart0; // 为 `uart0` 节点定义别名 `my-uart` led0 = &green_led; };
  • chosen节点:由系统或引导程序指定全局选择,用于确定某些关键设备,如控制台、内存等。
    chosen { zephyr,console = &uart0; // 指定调试控制台为 uart0 zephyr,sram = &sram0; // 指定主内存 };

三、在应用程序中获取设备树节点

Zephyr 提供了一系列宏,用于在 C 代码中获取设备树节点信息。以下是几种常用方式:

方式说明
通过节点标签DT_NODELABEL(label_name)使用节点上定义的标签。
通过完整路径DT_PATH(node_level1, node_level2, ...)指定从根节点开始的完整路径。
通过别名DT_ALIAS(alias_name)使用aliases节点中定义的别名。
通过 chosen 节点DT_CHOSEN(chosen_property)使用chosen节点中指定的属性。
通过 compatible 属性DT_INST_GET_BY_COMPATIBLE(inst_num, compatible_str)根据兼容性字符串和实例号获取。

实践示例:点亮 LED

我们通过一个简单的 LED 闪烁程序来演示如何获取和使用设备树节点。在开发板的设备树文件sf32lb52_devkit_lcd.dts中 (该文件位于C:\Users\%USERPROFILE%\zephyrproject\zephyr\boards\sifli\sf32lb52_devkit_lcd),LED 定义如下:

// 设备树片段 leds { compatible = "gpio-leds"; led0: led0 { label = "LED0"; gpios = <&gpioa_00_31 26 GPIO_ACTIVE_LOW>; // GPIO 引脚定义 }; };

在应用程序中,我们可以通过多种方式获取led0节点,并控制其对应的 GPIO:

#include<zephyr/kernel.h>#include<zephyr/drivers/gpio.h>#include<zephyr/devicetree.h>// 必须包含此头文件/* 方法1:使用节点标签(最直接) */#defineLED0_NODEDT_NODELABEL(led0)/* 方法2:使用别名(如果aliases中有定义) */// #define LED0_NODE DT_ALIAS(led0)/* 方法3:使用完整路径 */// #define LED0_NODE DT_PATH(leds, led0)// 获取LED的设备树规范(包括GPIO控制器、引脚号、标志)staticconststructgpio_dt_specled=GPIO_DT_SPEC_GET(LED0_NODE,gpios);voidmain(void){intret;// 1. 检查GPIO设备是否就绪if(!gpio_is_ready_dt(&led)){printk("Error: LED device (%s) is not ready\n",led.port->name);return;}// 2. 将引脚配置为输出模式ret=gpio_pin_configure_dt(&led,GPIO_OUTPUT_ACTIVE);if(ret<0){printk("Error %d: failed to configure LED pin\n",ret);return;}printk("Blinking LED on %s pin %d\n",led.port->name,led.pin);// 3. 主循环中闪烁LEDwhile(1){gpio_pin_toggle_dt(&led);// 翻转引脚状态k_sleep(K_MSEC(1000));// 延时1秒}}

补充说明:查看生成的设备树

编译后,可以在工程目录的build\zephyr\include\generated\zephyr目录下找到devicetree_generated.h文件。查看此文件可以帮助你理解设备树节点最终如何被转换为宏定义,并验证你的节点标识符是否正确。

小结

掌握设备树是进行 Zephyr 开发的关键。通过理解节点、标签、路径以及aliases/chosen的用法,你可以在代码中灵活、准确地获取硬件资源。从简单的 GPIO 控制到复杂的传感器、通信总线驱动,这一套机制是统一的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 5:38:26

掌握这7种R语言采样方法,轻松应对复杂环境监测任务

第一章&#xff1a;环境监测中R语言采样设计的核心价值在现代环境监测实践中&#xff0c;科学合理的采样设计是确保数据代表性与分析可靠性的关键前提。R语言凭借其强大的统计计算能力与灵活的空间分析扩展包&#xff0c;成为构建高效采样方案的理想工具。通过整合地理信息、历…

作者头像 李华
网站建设 2026/4/18 5:41:51

【云原生Agent实战指南】:Docker网络配置的5大核心技巧与避坑手册

第一章&#xff1a;云原生Agent与Docker网络概述在现代云原生架构中&#xff0c;Agent 通常指运行在宿主机或容器中的轻量级服务进程&#xff0c;用于采集监控数据、执行调度指令或管理应用生命周期。这些 Agent 需要与 Docker 容器网络进行高效通信&#xff0c;以实现对容器化…

作者头像 李华
网站建设 2026/4/18 7:37:05

搭建Appium工具环境

1、安装Java Development Kit&#xff08;JDK&#xff09; 前往Oracle官网下载JDK。 在https://www.oracle.com/java/technologies/javase-jdk11-downloads.html 找到最新版本的JDK。根据操作系统选择适合的版本&#xff0c;并根据指示下载安装程序。 安装JDK。运行下载的安…

作者头像 李华
网站建设 2026/4/18 8:07:42

为什么你的Agent工具在Dify中无法被调用?元数据定义缺失的6大征兆

第一章&#xff1a;Agent 工具注册的 Dify 元数据定义在构建基于 Dify 的智能 Agent 应用时&#xff0c;工具注册是实现功能扩展的核心环节。每个注册工具需附带一组结构化元数据&#xff0c;用于描述其能力、输入输出格式及调用方式。这些元数据不仅影响 Agent 对工具的理解与…

作者头像 李华
网站建设 2026/4/18 3:58:41

期末文献评述:核心内容、撰写要点与常见问题解析

科研新人做综述时最痛苦&#xff1a;一搜就是几十页论文&#xff0c;重复、无关、没用。下面三款工具让我效率翻倍。 ① WisPaper&#xff08;智能学术搜索 文献管理&#xff09; 官网&#xff1a;https://www.wispaper.ai WisPaper 能通过关键词和语义搜索快速找到相关文献&…

作者头像 李华
网站建设 2026/4/18 4:03:29

文献学案例分析期末复习指南:关键知识点与解题技巧解析

科研新人做综述时最痛苦&#xff1a;一搜就是几十页论文&#xff0c;重复、无关、没用。下面三款工具让我效率翻倍。 ① WisPaper&#xff08;智能学术搜索 文献管理&#xff09; 官网&#xff1a;https://www.wispaper.ai WisPaper 能通过关键词和语义搜索快速找到相关文献&…

作者头像 李华