一、如何新建工程
这里,依然参考官网。主要是翻译一遍,给自己留下印象。
引用:Application Development — Zephyr Project Documentation
******************基本上是翻译官网内容,不感兴趣可跳过,直接上手第二章****************
从引用可知:
***引用的文档约定如下:1、app文件目录存放在zephyrproject/<app>。2、构建输出目录放在<app>/build。
***将应用放在工作区,也就是zephyrproject内部,使用weist相关命令更方便。但是,只要环境变量(ZEPHYR_BASE)配置正确,应用可以放在电脑上任意位置。
***Zephyr基于cmake。
***应用目录里的文件负责把Zephyr、各类模块和写的应用关联起来。这个目录存放所有应用专属文件,比如应用独立配置文件、业务源码。
举例app文件夹的结构:
这些文件的作用如下:
- CMakeLists.txt:该文件告诉构建系统去哪里查找其他应用文件,并把应用目录接入 Zephyr 的 CMake 构建体系。通过这个关联,就可以使用 Zephyr 构建系统提供的能力,例如板级专属配置文件、在真实硬件或模拟器上运行和调试编译出的固件等。
- app.overlay:这是设备树覆写文件,用来针对你编译的任意开发板,在基础设备树之上追加应用专属的修改。设备树覆写一般用来配置应用用到的硬件资源。 构建系统默认会读取
app.overlay;你也可以添加更多设备树覆写文件,系统还会自动查找其他默认名称的配置文件。 更多设备树相关内容,请参见「Devicetree」文档。 - prj.conf:这是一份Kconfig 片段,用于为一个或多个 Kconfig 选项设置应用专属的值。这些应用配置会和其他配置合并,生成最终生效的配置。Kconfig 片段一般用来开启、配置应用需要用到的软件功能。 构建系统默认读取
prj.conf;你也可以添加更多 Kconfig 配置片段,系统还会自动查找其他默认名称的配置文件。 更多内容见下文「Kconfig Configuration」。 - VERSION:文本文件,里面包含若干版本信息字段。借助这些字段,可以管理应用的生命周期,并且在固件镜像签名时自动填充应用版本号。 关于该文件的用法,详见「Application version management」。
- main.c:源码文件。应用代码一般使用 C、C++ 或者汇编语言编写。Zephyr 的规范约定:源码统一放在
<app>下名为src的子目录中。
应用创建完成之后,需要使用cmake生成构建目录(build?)。该目录存放编译应用与Zephyr内核后的各类文件,之后将它们链接合并,生成可在开发板上运行的最终二进制固件。最简便的构建方式是使用west build,当然你也可以直接调用cmake。
应用编译的产物永远都在build中,Zephyr不支持源码内构建。
应用类型
我们根据<app>所在的位置,把Zephyr应用分为三种基础类型:
| 应用类型 | <app>的存放位置 |
|---|---|
| repository(仓库内应用) | zephyr 源码仓库内部 |
| workspace(工作区应用) | 安装了 Zephyr 的 west 工作区内 |
| freestanding(独立应用) | 其他任意位置 |
下面展开说明这三种类型:
Zephyr仓库内应用
参考下图文件夹中的应用(注意看目录):
Zephyr工作区应用
存放在 west 工作区内、但不在 zephyr 源码仓库内部的应用,称为 Zephyr 工作区应用。参考下图:
Zephyr独立应用
存放在Zephyr工作区之外的Zephyr程序。如下所示:
创建应用程序
在Zephyr中,既可以使用一个参考工作区的应用,或者手动创建应用。这里我选择前者,从历程中拷贝一个例程。
使用参考工作区的应用
example-application这个 Git 仓库包含了一个参考工作区应用。推荐在创建自己的应用时以它作为参考,后续章节会进行说明。
参考链接:GitHub - zephyrproject-rtos/example-application: Example out-of-tree application that is also a module · GitHub
该example-application仓库演示了多项常用功能的使用方法,例如:
- 自定义板级移植
- 自定义设备树绑定
- 自定义设备驱动
- 持续集成(CI)配置,包含 twister 工具的使用
- 自定义 west 扩展命令
example-application 的基础用法
在已有的Zephyr工作区中使用example-application 仓库,最简便的方式是执行以下步骤:
cd <home>/zephyrproject git clone https://github.com/zephyrproject-rtos/example-application my-app这个目录名my-app可以自定义,按需求修改即可。之后就可以进入这个目录,修改里面的内容来满足自身需求。因为是在已有 Zephyr 工作区内使用,你可以通过west build或者其他 west 命令来完成编译、烧录与调试。
example-application 高级用法
这里内容是搭建基于Zephyr的自定义软件发行包。我移植例程貌似用不到,用到再看吧。详细内容参见引用链接。
手动创建应用程序
可以按照以下步骤从零开始创建基础应用目录。不过,以example-application仓库或者 Zephyr 的示例与演示工程作为起点,通常会更加简单。
1、创建应用目录
不支持在路径包含空格的目录下编译 Zephyr 或者创建应用。 所以 Windows 路径C:\Users\YourName\app可以正常使用,但C:\Users\Your Name\app不行。
2、创建源代码文件
建议将所有应用源码放在名为src的子目录中,便于区分工程配置文件和源码文件。
承接上一步示例,执行:
3、将应用源码放到src子目录。本示例假设新建了src/main.c文件。
4、在app目录下新建CMakeLists.txt,内容如下:
备注:
cmake_minimum_required()是 CMake 的必需调用。下一行的 Zephyr 包也会调用它。如果 CMake 版本低于CMakeLists.txt中指定的版本,或是低于 Zephyr 包要求的版本,CMake 就会报错。find_package(Zephyr)会引入 Zephyr 构建系统,并创建一个名为app的 CMake 目标(参见 Zephyr CMake 包文档)。向该目标添加源码文件,就是把文件纳入编译。Zephyr 包会将Zephyr-Kernel定义为 CMake 工程,并启用 C、CXX(C++)、ASM(汇编)语言支持。project(my_zephyr_app)用于定义你的应用对应的 CMake 工程。必须写在find_package(Zephyr)之后,避免和 Zephyr 的project(Zephyr-Kernel)产生冲突。target_sources(app PRIVATE src/main.c)的作用是把源码文件添加到app目标中。这一句必须放在定义该目标的find_package(Zephyr)之后。你可以多次使用target_sources()添加任意多的源码文件。
5、至少为你的应用创建一个 Kconfig 片段文件(通常命名为prj.conf),在里面设置应用所需的 Kconfig 选项值,详见 Kconfig 配置文档。如果不需要设置任何 Kconfig 选项,创建一个空文件即可。
6、配置应用所需的设备树覆盖文件,通常使用app.overlay,详见设置设备树覆盖文档。
7、根据需要准备其他文件,例如 twister 测试配置文件、持续集成配置文件、文档等。
重要的构建系统变量
可以通过大量变量控制Zephyr构建系统。下面是开发者都需要了解的核心变量。
BOARD,CONF_FILE, andDTC_OVERLAY_FILE这三个变量,有三种方式传给构建系统(优先级从高到低):
1、在执行west build或者cmake命令时,通过-D参数传入。如果需要多个设备树叠加文件(overlay),要用引号包裹:"file1.overlay;file2.overlay"
2、设置为环境变量
3、在CMakeLists.txt里用set(<变量名> <值>)语句定义
- ZEPHYR_BASE:构建系统使用的Zephyr根目录变量
find_package(Zephyr)会自动把它设置为 CMake 缓存变量。也可以将ZEPHYR_BASE设置成环境变量,强制 CMake 使用指定路径下的 Zephyr 源码。 - BOARD:选择应用编译时使用的开发板,作为默认配置。 内置开发板信息参见【支持的开发板与扩展板】;新增板级移植请查阅【开发板移植指南】。
- CONF_FILE:指定一个或多个 Kconfig 配置片段文件。 多个文件名可以用空格或者分号分隔。文件内的 Kconfig 配置项会覆盖默认配置。 更多细节见【初始配置】章节。
- EXTRA_CONF_FILE:附加 Kconfig 配置片段文件。 多个文件名可用空格 / 分号分隔。适合保留
CONF_FILE默认值的同时,追加一部分额外配置选项。 - DTC_OVERLAY_FILE:指定一个或多个要加载的设备树叠加文件。多个文件使用分号隔开。示例参考【配置设备树叠加文件】,设备树基础概念见【设备树简介】。
- EXTRA_DTC_OVERLAY_FILE:额外追加的设备树叠加文件。多个文件使用分号隔开。适合保留
DTC_OVERLAY_FILE默认值的前提下,混入新增的 overlay 文件。 - SHIELD:参见【扩展板(Shields)】文档。Shields — Zephyr Project Documentation
- ZEPHYR_MODULES:CMake 列表,存放附加目录的绝对路径;这些目录内包含源码、Kconfig 等资源,参与应用编译。详情见【模块(外部工程)】。 重点:一旦手动设置该变量,它就是一份完整模块清单,构建系统不会再自动加载 west 管理的模块。
- EXTRA_ZEPHYR_MODULES:作用类似
ZEPHYR_MODULES,区别是:它追加到 west 自动搜索得到的模块列表尾部,而不是替换整个列表。 - FILE_SUFFIX:可选文件名后缀,用于 Kconfig 配置片段、设备树 overlay 文件。构建时优先查找带此后缀的文件;如果找不到,就回退到不带后缀的原始文件名。详情见【文件后缀机制】。
- KCONFIG_WARNING_AS_ERROR:将所有 Kconfig 警告升级为编译错误(包含默认仅打印提示的警告)。详情见【Kconfig 警告当作错误处理】
注意:你可以使用Zephyr Build Configuration CMake 包,在多个工程间共享这些变量的通用配置。
应用CMakeLists.txt
每个应用工程都必须有CMakeLists.txt文件,它是构建系统的入口(顶层文件)。最终的zephyr.elf镜像同时包含应用代码与内核库。
下面介绍可以在CmakeLists.txt里实现的部分功能,务必按照如下顺序。
首先,如果只需要给一块板子编译固件,可以另起一行,在工程里设置目标板的名称。示例:
更多板子可用信息参考:Supported Boards and Shields — Zephyr Project Documentation
Zephyr 构建系统会按下面顺序查找 BOARD 的值,一旦找到就停止继续查找:
1,CMake 缓存里已经存在的值,优先级最高。这样可以保证后续编译不会使用和配置阶段不一样的 BOARD。
2,CMake 命令行传入的值(直接传,或者通过west build间接传入),也就是-DBOARD=YOUR_BOARD。
3,如果设置了环境变量BOARD,则使用环境变量的值。
4,最后,才会使用应用CMakeLists.txt里面通过set(BOARD ...)设置的值。
其次,如果你的应用不使用默认的prj.conf,而是使用其他配置文件,需要添加代码设置CONF_FILE变量,指向这些配置文件。多个文件名之间用单个空格或者分号分隔。 如果你不想在一处一次性写死全部配置文件,可以用 CMake list 的方式模块化拼接配置片段文件。
Setting Kconfig configuration values — Zephyr Project Documentation
如果你的应用用到设备树叠加文件,可能需要设置DTC_OVERLAY_FILE。Devicetree HOWTOs — Zephyr Project Documentation
如果你的应用需要自定义内核配置项,在应用的CMakeLists.txt同级目录新建Kconfig文件。Configuration System (Kconfig) — Zephyr Project Documentation
这属于比较少见的高级用法:适合应用需要新增专属配置选项,并且在不同编译配置下取不同值的场景。 如果你仅仅是想给 Zephyr 已有的配置项设置自定义值,直接用上面讲的CONF_FILE就够了。
Kconfig文件模板写法:
在完成上面所有步骤后,另起一行声明本应用依赖Zephyr
注意:find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})用于强制使用环境变量ZEPHYR_BASE指定的 Zephyr 源码版本。Zephyr 的所有官方示例都支持ZEPHYR_BASE环境变量。
接下来,把应用源码添加到app目标库中,一个文件一行,写法如下:
下面是一份简单的cmakelist.txt:
CMake 属性HEX_FILES_TO_MERGE可以结合 Kconfig、CMake 的工程配置,把外部独立编译出来的 hex 文件,和 Zephyr 应用编译生成的 hex 文件合并在一起。示例:
CMakeCache.txt
CMake 使用CMakeCache.txt文件作为持久化的键值字符串存储,用于在多次编译之间缓存参数,包含编译选项、构建选项以及库依赖路径。 当在空的构建目录里第一次运行 CMake 时,就会生成这个缓存文件。
关于CMakeCache.txt的更多细节,请查阅 CMake 官方的 Cache 文档。
CMake Cache — Mastering CMake
应用配置
应用配置目录
Zephyr会从应用配置目录读取配置文件;但前面提到的参数(CONF_FILE、EXTRA_CONF_FILE、DTC_OVERLAY_FILE、EXTRA_DTC_OVERLAY_FILE)如果填写绝对路径,不受该目录约束。应用配置目录由变量APPLICATION_CONFIG_DIR控制。
APPLICATION_CONFIG_DIR的取值优先级(靠前更高):
用户通过-DAPPLICATION_CONFIG_DIR=<path>命令行传入,或者在find_package(Zephyr)之前在 CMake 脚本里设置,则使用该路径作为应用配置目录。
默认值:应用源码根目录。
Kconfig配置
应用的配置项一般在应用目录下的prj.conf中设置。例如,启用 C++ 支持可以这样写:
Samples and Demos — Zephyr Project Documentation
Setting Kconfig configuration values — Zephyr Project Documentation
Setting Kconfig configuration values — Zephyr Project Documentation
Hardening Tool — Zephyr Project Documentation
Configuration System (Kconfig) — Zephyr Project Documentation
一、实验性特征
暂时不研究了。
设备树叠加层Devicetree HOWTOs — Zephyr Project Documentation
File Suffixes 文件后缀机制
很多 Zephyr 项目希望一套源码,多套配置,用来适配不同产品版本、不同编译变体,它们需要不同的 Kconfig 和设备树配置。 Zephyr 提供FILE_SUFFIX参数,会自动给配置文件名追加后缀;这个机制同时作用于 Kconfig 片段、板级 overlay 文件。并且有降级逻辑:带后缀的文件找不到时,自动回退加载不带后缀的基础文件。
示例工程目录结构:
应用专属代码
应用源码默认放在src目录下。如果文件很多,可以在src下自行建立多层子目录分组。
应用代码不要使用内核预留的符号前缀,详细见命名规范(Naming Conventions)文档。
第三方代码库
库代码可以放在src目录之外参与编译,但有一个重点:应用和第三方库必须使用相同的 ABI(应用二进制接口)。 多数架构靠编译选项控制 ABI,所以库和应用的编译标志必须保持一致;适配胶水代码一般也需要能包含 Zephyr 内核头文件。
为方便集成第三方组件,Zephyr 构建系统提供了一组 CMake 函数,让应用脚本拿到 Zephyr 的编译参数。 函数定义在cmake/modules/extensions.cmake,命名格式:zephyr_get_<type>_<format>。
第三方构建系统通常需要传入这些变量:
CMAKE_C_COMPILER、CMAKE_ARARCH、BOARD,以及标识 Zephyr 内核版本的相关变量
示例工程:samples/application_development/external_lib,演示了第三方库集成用法。
https://github.com/zephyrproject-rtos/zephyr/blob/main/samples/application_development/external_lib
————————————————————
编译应用
Zephyr 构建系统会编译、链接应用所有组件,最终生成单一镜像文件,可以跑在仿真硬件或者真实板子上。
和其他基于CMake的系统应用,编译分为两个阶段:
1、生成构建文件阶段:用cmake+ 指定 generator,生成构建规则;generator 决定第二阶段用什么底层构建工具。
2、实际编译阶段:调用底层构建工具,编译源码、链接生成镜像。
Zephyr默认使用原工具west,west在内部自动调用cmake + 底层构建工具(ninja /make)。你也可以直接手动调用 cmake。
Basic基础用法
1、进入应用目录<app>。
2、执行下面命令,为指定板子编译,输出zephyr.elf。
west方式
west build -b <board>如果你想使用另一份.conf配置文件,可以用CONF_FILE参数。这份配置会覆盖应用原来的.config或默认prj.conf:
west build -b <board> -- -DCONF_FILE=prj.alternate.conf可以持久化指定板子和配置:
导出环境变量BOARD、CONF_FILE
或者在CMakeLists.txt里用set()设置 另外 west 还支持设置默认板子。
Build Directory Contents 构建目录内容
使用 Ninja 生成器时,build 目录结构如下:
build目录里重点文件:
build.ninja:ninja 的构建规则文件,ninja 靠它编译程序。
zephyr子目录:构建系统的工作目录,绝大多数编译生成文件放在这里
执行完ninja编译后,产物放在build/zephyr下:
.config:本次编译用到的全部 Kconfig 配置
zephyr.elf:最终 ELF 可执行文件;同时还会输出.hex、.bin等固件格式
重新编译应用
开发时频繁修改、测试是最高效的方式。源码、CMakeLists.txt、配置改动后,建议重新编译测试,方便调试。
Zephyr 构建系统是增量编译:只重新编译受改动影响的文件,所以再次编译通常比首次快很多。
有时候构建系统判断出错,该重编的文件没有重编,这时需要强制全量清理重建:
1、进入<app>/build目录
2、清理命令二选一(保留.config配置文件,只删编译产物)
west build -t clean
west build -t pristine(不保留.config)
3、清理完成后,再用正常编译命令重新构建。
为指定版本板子编译
用到再看吧。
运行应用
Zephyr 支持的大多数板子,都可以用west flash把固件烧录到板子并启动。在真实硬件上烧录运行步骤:
- 先完成编译(前面 Building an Application 章节)
- 板子连接主机,一般是 USB 方式
- 在
<app>/build目录执行:(每次执行这个命令,都会先增量编译,再烧录)
west flashZephyr 构建系统会结合板级支持文件,调用对应硬件的烧录工具,下载固件并启动。
Linux 环境开发时,通常需要安装对应板子的 udev 规则,才能让普通用户访问 USB 调试器。烧录失败时优先检查这点。
自定义板子、设备树以及 SOC 定义
如果你开发的板子 / 平台还没有被 Zephyr 主线支持,可以直接在你的应用工程里添加板子、设备树、SOC 相关定义,不需要提交到 Zephyr 源码仓库内部(out-of-tree,树外开发)。
这套树外板子与 SOC 的目录组织方式,和 Zephyr 主线内部维护板子、SOC 的结构保持一致。这样做的好处:前期开发完成后,如果后续想把这套平台代码合入 Zephyr 主线,迁移、提交上游会轻松很多。
在你的应用工程(或者单独仓库)里,用下面这套目录结构存放自定义板子:
上面的boards目录中存放自定义的板子:
soc目录用来存放 SOC 相关代码;当然,你也可以直接使用 Zephyr 主线里已经支持的 SOC 来做自定义板子。
Boards 板子目录规范
boards下一级文件夹使用厂商名作为目录名:
如果后续打算提交到 Zephyr 主线,厂商名必须和dts/bindings/vendor-prefixes.txt里的厂商前缀保持一致
非厂商自研板,这里用others
doc/文档、support/支持文件是可选的;但如果要上游合入 Zephyr,就必须提供。
my_custom_board目录内文件需要遵循 Zephyr 板子规范,包含这些文件:
目录搭建完成后,编译时通过-DBOARD_ROOT参数告诉 CMake 去哪里找这套自定义板子:
west build -b <board name> -- -DBOARD_ROOT=<path to boards>这样编译就会加载你的自定义板子配置,固件生成在应用工程内。
也可以在应用的CMakeLists.txt里设置BOARD_ROOT,必须放在find_package(Zephyr …)之前。
注意:
在 CMakeLists.txt 里写BOARD_ROOT时,必须用绝对路径,示例:
list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/<extra-board-root>)命令行传-DBOARD_ROOT时,绝对路径、相对路径都可以;相对路径以应用目录为基准。
注意:
如果使用 sysbuild,BOARD_ROOT需要在模块或者 sysbuild 的 CMakeLists.txt 中定义。
SOC定义
和板级支持的方式类似,目录结构和 Zephyr 源码树里维护 SOC 的方式保持一致,示例:
soc/Kconfig文件会在 Kconfig 中生成顶层SoC/CPU/ 配置选择菜单。
可以借助 CMake 变量SOC_ROOT,将树外(out-of-tree)的 SOC 定义添加到这个菜单中。该变量是一个用分号分隔的目录列表,这些目录存放 SOC 支持相关文件。
遵循上面的目录结构,你可以添加下述文件,从而在菜单中加载更多 SOC:
上面这些 Kconfig 文件可以用来描述该 SOC,或是加载其他额外的 SOC Kconfig 文件。
下面是在这套目录结构里加载stm32l0专属 Kconfig 文件的示例:
只需要在st/stm32/Kconfig.soc写入下面内容即可实现:
SOC 目录结构准备好之后,你就可以给应用程序指定这个自定义平台进行编译构建:向 CMake 构建系统传入-DSOC_ROOT参数,指定自定义平台信息所在路径。
使用west构建
west build -b <开发板名> -- -DSOC_ROOT=<soc目录路径> -DBOARD_ROOT=<开发板目录路径>构建时会启用你的自定义平台配置,并把 Zephyr 固件生成到应用目录下。
你可以查阅【构建设置】文档,了解如何在模块的zephyr/module.yml文件中配置SOC_ROOT。
Modules (External projects) — Zephyr Project Documentation
也可以在应用的CMakeLists.txt中定义SOC_ROOT变量。
注意:必须在执行find_package(Zephyr ...)引入 Zephyr 基础脚本之前定义它。
如果在CMakeLists.txt里设置SOC_ROOT,必须使用绝对路径,示例写法:
list(APPEND SOC_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/<extra-soc-root>)如果是通过-DSOC_ROOT=<soc-root>参数传入,则绝对路径、相对路径都支持; 相对路径是以应用程序目录作为基准进行解析。
设备树定义
设备树目录默认会从APPLICATION_SOURCE_DIR(应用源码目录)、BOARD_DIR(开发板目录)以及ZEPHYR_BASE(Zephyr 根目录)中查找。你也可以自行新增设备树目录(也就是DTS_ROOT),需要创建如下目录结构:
其中arm需要替换成对应的芯片架构。上面所有目录都是可选的。bindings目录存放设备树绑定描述文件;其余目录存放可在设备树源码中被#include引入的文件。
目录结构搭建完成后,就可以通过 CMake 缓存变量DTS_ROOT指定这个目录路径来启用它:
使用west构建
west build -b <开发板名> -- -DDTS_ROOT=<dts根目录路径>你同样可以在应用的CMakeLists.txt文件里定义该变量。一定要放在find_package(Zephyr ...)(引入 Zephyr 基础构建脚本)之前。
如果在CMakeLists.txt内设置DTS_ROOT,必须填写绝对路径,示例:
list(APPEND DTS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/<extra-dts-root>)如果是通过参数-DDTS_ROOT=<dts-root>传入,绝对路径、相对路径都支持;相对路径是以应用程序目录作为基准解析。
设备树源码会经过 C 预处理器处理,因此你可以#include放在DTS_ROOT目录下的文件。按照惯例,设备树头文件后缀为.dtsi。
你还可以借助预处理器控制设备树文件内容,通过 CMake 缓存变量DTS_EXTRA_CPPFLAGS传递预处理指令:
使用west构建
west build -b <开发板名> -- -DDTS_EXTRA_CPPFLAGS=-DTEST_ENABLE_FEATURE**************************************************************************************************************
二、点灯
完成第十三章 跑马灯实验
我这里参考工作区应用模版创建工程。
首先打开自己的Zephyr工作区,也就是zephyrproject。(注意,首先要激活Python虚拟环境(venv),才可以使用west工具,参考下图,下面的指令查看工作区目录。
west topdir)
1、在工作区目录输入如下指令:
cd <home>/zephyrproject git clone https://github.com/zephyrproject-rtos/example-application my-app注意,my-app可以自定义,这里我换成lab_1,如下图所示:
2、使用VSCode打开这个文件夹
3、先让app能正常编译,经过一番试错
先修改prj.conf
删掉CONFIG_BLINK=y
再修改main.c
/* * Copyright (c) 2021 Nordic Semiconductor ASA * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/kernel.h> #include <zephyr/drivers/sensor.h> #include <zephyr/logging/log.h> #include <zephyr/app_version.h> LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL); int main(void) { while(1); return 0; }之后,进行编译:
结果如下:
4、实现跳转
我这里用的插件是clangd,如下图,
但是会出现上图的提示,在app目录新建.clangd文件,内容如下:
CompileFlags: Remove: - -fno-printf-return-value - -mfp16-format=ieee - -fno-reorder-functions之后再restart一下即可
5、修改板子的设备树
我想用开发Linux驱动的方式来写这份例程,要不然直接用gpio点灯也不能突出Zephyr的优势。根据Linux经验,需要找到对应的驱动,然后看说明文件。
我这里使用如下图驱动,同样的说明文档如下图所示
先来阅读右边的说明文档,文档内容略,主要是描述了这个驱动的功能和设备树示例。
开始参考右边重写左边led节点。
修改如下:
/dts-v1/; #include <st/f1/stm32f103Xe.dtsi> #include <st/f1/stm32f103z(c-d-e)tx-pinctrl.dtsi> #include <zephyr/dt-bindings/input/input-event-codes.h> / { model = "alientek jingying stm32f103ze board"; compatible = "alientek,stm32f103ze"; chosen { zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; }; aliases { led0 = &led_0; led1 = &led_1; }; // 格式:【标签:】节点名 { 属性 }; leds { compatible = "gpio-leds"; led_0: led_0 { gpios = <&gpiob 5 GPIO_ACTIVE_LOW>; label = "LED 0"; }; led_1: led_1 { gpios = <&gpioe 5 GPIO_ACTIVE_LOW>; label = "LED 1"; }; }; }; &clk_lsi { status = "okay"; }; &clk_hse { clock-frequency = <DT_FREQ_M(8)>; status = "okay"; }; &pll { mul = <9>; clocks = <&clk_hse>; status = "okay"; }; &rcc { clocks = <&pll>; clock-frequency = <DT_FREQ_M(72)>; ahb-prescaler = <1>; apb1-prescaler = <2>; apb2-prescaler = <1>; }; &usart1 { pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; pinctrl-names = "default"; current-speed = <115200>; status = "okay"; }; &usart2 { pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>; pinctrl-names = "default"; current-speed = <115200>; status = "okay"; }; &usart3 { pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>; pinctrl-names = "default"; current-speed = <115200>; }; &i2c1 { pinctrl-0 = <&i2c1_scl_remap1_pb8 &i2c1_sda_remap1_pb9>; pinctrl-names = "default"; status = "okay"; clock-frequency = <I2C_BITRATE_FAST>; }; &spi1 { pinctrl-0 = <&spi1_sck_master_pa5 &spi1_miso_master_pa6 &spi1_mosi_master_pa7>; pinctrl-names = "default"; cs-gpios = <&gpiob 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; status = "okay"; }; &spi2 { pinctrl-0 = <&spi2_nss_master_pb12 &spi2_sck_master_pb13 &spi2_miso_master_pb14 &spi2_mosi_master_pb15>; pinctrl-names = "default"; status = "okay"; }; &timers1 { st,prescaler = <10000>; status = "okay"; pwm1: pwm { status = "okay"; pinctrl-0 = <&tim1_ch1_pwm_out_pa8>; pinctrl-names = "default"; }; }; &timers2 { st,prescaler = <255>; status = "okay"; pwm2: pwm { status = "okay"; pinctrl-0 = <&tim2_ch2_pwm_in_pa1>; pinctrl-names = "default"; }; }; &iwdg { status = "okay"; }; &rtc { clocks = <&rcc STM32_CLOCK(APB1, 28)>, <&rcc STM32_SRC_LSI RTC_SEL(2)>; status = "okay"; }; &adc12_common { status = "okay"; }; &adc1 { pinctrl-0 = <&adc1_in0_pa0>; pinctrl-names = "default"; status = "okay"; }; &die_temp { status = "okay"; }; &dma1 { status = "okay"; };注意下图:因为c的宏定义不能有下划线,但是我这里命名了下划线,故需要写 标签:节点名。
这是参考的说明文档内容
6、修改如下文件
上图是应用配置文件,怎么写也可以参考官方例程。
调整配置
1、在工程目录执行
west build -t menuconfig改完不会写进prj.conf,会写进哪?
2、直接在下图所示路径找
zephyrproject/zephyr/drivers/led参考如下:
7、写main.c
这个led.h是起什么作用的,我明明用的驱动头文件也不这样啊?(我怀疑这个是上层)
引用:Zephyr API Documentation: LED G:\zephyrproject\zephyr\samples\basic里的例程Light-Emitting Diode (LED) — Zephyr Project Documentation
参考例程:
上图中的例程使用了两种点灯方式,第一种是纯gpio点灯,我觉得不能突出Zephyr类Linux的特点,所以用第二种驱动方式点灯。
#include <zephyr/kernel.h> #include <zephyr/drivers/led.h> // 从设备树别名led0获取LED规格 这里的宏里面不能写下划线 所以设备树要加aliases // const struct led_dt_spec led0 = LED_DT_SPEC_GET(DT_ALIAS(led_0)); const struct led_dt_spec led0 = LED_DT_SPEC_GET(DT_ALIAS(led0)); const struct led_dt_spec led1 = LED_DT_SPEC_GET(DT_ALIAS(led1)); int main(void) { // 检查LED驱动是否就绪 if (!led_is_ready_dt(&led0)) { return 0; } if (!led_is_ready_dt(&led1)) { return 0; } while (1) { led_on_dt(&led0); led_off_dt(&led1); k_msleep(500); led_on_dt(&led1); led_off_dt(&led0); k_msleep(500); } }8、编译烧录
west build -b jingying_f103ze . --pristine最后一个参数用来强制解析设备树。
如何省去输入开发板的名字?加入下图这一行即可。
之后输入下面命令即可
west build .9、烧录延时
west flash实验1演示
本文为个人学习总结,难免存在疏漏与错误,欢迎大家在评论区批评指正。
***********************************草稿************************************************************
系统构建变量放在哪?