文章目录
前言
本人正在学习 Zephyr,一个可移植性较强,可以兼容多种开发板及物联网设备的操作系统,如果你感兴趣,可以点此查看我的 学习笔记总述 进行了解!
摘要
之前介绍了如何 创建并编译一个新的工程,可以正常的编译并烧录到开发板上进行运行了,但是对于具体怎么工作的,如何创建,构建和运行 Zephyr 应用程序,还是比较模糊的。
NCS 是以 Zephyr 为内核,如果想要熟练使用 NCS,那就应该对 Zephyr 有比较深入的了解,下面介绍下 Zephyr 的源码树结构。
1. 源树结构
zephyr
├── arch 包含和硬件体系结构相关的代码,每种平台占一个相应的目录
├── boards 板级代码及相关的配置文件,如 nRF9160_pca10090 等
├── cmake 构建 Zephyr 需要额外的构建脚本
├── doc 系统文档目录
├── drivers 设备驱动,每个不同的驱动占用一个子目录
├── dts devicetrree 源文件,用于描述特定板子的设备细节,如外设寄存器数量及寄存器地址
├── ext 其他功能的支持
├── include 包括所有公共 api 的文件,除了在 lib 下定义的部分
├── kernel 与架构无关的内核代码
├── lib 库代码,包括最小的标准 C 库
├── misc 不属于任何其他*目录的杂项代码
├── modules 提供特定芯片系列的一些外设配置选项
├── samples 演示使用 Zephyr 特性的示例应用程序
├── scripts 用于构建和测试 Zephyr 应用程序的各种程序和其他文件。
├── soc SoC 相关代码和配置文件,如 nRF9160 soc
├── subsys zephyr 子系统,包括 USB,网络,文件系统及蓝牙等
├── tests 测试 Zephyr 特性的代码
├── CMakeLists.txt CMake 构建系统的顶层文件,包含构建 Zephyr 所需的大量逻辑
├── Kconfig 顶层 Kconfig 文件,它引用 Kconfig.zephyr 文件。也可以在*目录中找到
├── west.yml West 清单,列出由 West 命令行工具管理的外部存储库
这里介绍下源码树各路径对应的功能,有一个直观的认识即可,要知道什么东西需要去哪里寻找。
例如要看 GPIO 设备如何控制,我们就知道要去 zephyr/driver/gpio
下面去查看相关的代码,结合路径下的CMakeLists
文件及 Kconfig
文件,就知道改如何配置外设参数及使用。
若要知道开发板的硬件配置,就要知道要到 zephyr/boards
目录下去看默认设置与相关的配置。
2. 配置设置
每一个 NCS 或者 Zephyr 项目都包含了非常多的配置项或选项,总数有可能达几千项之多,然而绝大多数配置项我们都不需要去管他们,只需要使用默认值即可,所以开发一个简单的 NCS 应用程序,有可能我们不需做任何配置,就可以跑起来。
NCS 或者 Zephyr 里面主要包含两种配置项:Kconfig 和 DeviceTree,Kconfig 主要负责软件的配置,DeviceTree 主要负责板子硬件的配置。两者最终都会生成一个 .h
文件,其中Kconfig 生成的头文件为:autoconf.h
,而 DeviceTree 生成的头文件为 devicetree_unfixed.h
,他们都在如下目录:
<build_dir>/zephyr/include/generated
其中 <build_dir> 为你编译生成的文件目录。
2.1 简介
开发过 nRF5 SDK 的话,一定记得里面有个:sdk_config.h
,在 ncs 上面没有 sdk_config.h
文件,替代的是的 autoconf.h
文件和 devicetree_unfixed.h
文件,从机理上,它们没有本质的区别,都是完成相同的功能。
autoconf.h
文件是负责 软件配置,而 devicetree_unfixed.h
文件是负责 硬件配置。ncs 把软硬件分离开来了,相当于有两个 sdk_config.h
的文件。
但是我们不能像 sdk_config.h
文件一样去直接修改 autoconf.h
文件和 devicetree_unfixed.h
文件,因为它们是在编译过程中通过 Python 脚本自动生成的。
下面介绍下这二者的生成过程以及我们如何来进行软硬件配置。
2.2 软件配置
autoconf.h
文件是在编译过程中由许许多多的 Kconfig
文件生成的,基本上每个模块都有自己的 Kconfig
文件。
生成 autoconf.h
文件的整体流程图如下:
看了这个图,可能会有疑问:不是说autoconf.h
文件是由 Kconfig
文件生成的吗?怎么又多出来 prj.conf
文件和 .config
文件呢?(图中的 .conf 文件实际应该是 .config)
前面说了,Kconfig
文件都是模块自带的,模块为每一个选项都设了一个默认值,如果你想修改这个默认值,怎么办?你需要跑到每个模块下面直接把 Kconfig
文件改了(这样不方便,而且也会影响到其他项目工程的运行)。
为此 NCS 或者 Zephyr 引入了 prj.conf
文件,prj.conf
文件是每个项目的配置文件,通过修改 prj.conf
文件来修改 Kconfig
文件。然后将所有的 Kconfig
文件与 prj.conf
文件结合,先生成一个 .config
文件,最后生成 autoconf.h
文件。
.config
文件是一个临时文件,编译系统默认会以它为基准来生成 autoconfig.h
,所以一旦你的 Kconfig
或者 prj.conf
更新了,记得一定要重新装载项目,以更新 .config
文件,从而生成新的 autoconfig.h
文件。
.config
文件是起一个中间桥梁的作用,和 autoconf.h
文件的内容一一对应,大部分的图形化配置系统都是通过调用 .config
文件来配置 Kconfig
文件的,所以这就是为什么使用图形化配置系统只能在当次编译的时候生效的原因。
所以 autoconf.h
文件实际上是由 Kconfig
文件和 prj.conf
文件一起来生成的,而我们只需要修改 prj.conf
文件就可以进行相应的软件配置了。
通过 prj.conf
,可以更改默认的 Kconfig
选项,而且这个更改是永久的,并只适用于本项目。
2.3 硬件配置
生成 devicetree_unfixed.h
文件的流程图为:
与生成 autoconf.h
文件的过程类似,<board>.dts
是不同类型开发板的默认硬件配置,可以在目录 zephyr/boards
下查看,而 <board>.overlay
是每个项目的硬件配置文件。
整个过程和上面的软件配置过程一样,这里就不多做介绍了,<board>.dts
类似于 Kconfig
文件,<board>.overlay
类似于 prj.conf
文件,
所以,通过 <board>.overlay
,就可以更改板子的默认配置,而且这个更改是永久的,并只适用于本项目。
与软件配置相比,图中多了个 <board>_common.dts
文件,但这个 <board>_common.dts
文件不是每个开发板都有的。
有时候会出现这种情况,有几个板子的大部分特性都是一样的,只有少数组件不一样,这个时候会把相同的地方拿出来,组成一个 <board>_common.dts
文件,然后几块板子再分别引用这个 <board>_common.dts
文件,
例如 nRF9160:有 nrf9160dk_nrf9160ns 和 nrf9160dk_nrf9160 这两块开发板内容基本上是一样的,所以在这里把相同的内容拎出来组成了一个:nrf9160dk_nrf9160_common.dts,然后 nrf9160dk_nrf9160ns.dts 和 nrf9160dk_nrf9160.dts 再引用 nrf9160dk_nrf9160_common.dts,这样拆分一下逻辑性更强,使系统更加灵活,扩展性更好。
3. 总结
软硬件配置生成的临时文件分别为 .config
和 zephyr.dts
,这两个文件存放路径为:<build_dir>/zephyr
;
生成的最终配置文件为 autoconf.h
和 devicetree_unfixed.h
,存放路径为:<build_dir>/zephyr/include/generated
。
当你觉得对自己的配置不放心,或者出现问题时,可以去查看这几个文件,以确认你的配置是否生效。
参考链接
源树结构: https://docs.zephyrproject.org/latest/application/index.html#source-tree-structure
构建和配置系统: https://docs.zephyrproject.org/latest/guides/build/index.html