Zephyr应用的代码结构--自定义驱动(转自Half Coder)

本作品采用知识共享署名(https://lgl88911.gitee.io,转载过程中有修改原文)

本文说明如何将新增的驱动纳入到Zephyr应用的目录下进行管理。

本篇是<<Zephyr应用的代码结构>>系列的终篇和下面两篇文章一起可以构建出一个有app独立管理的zephyr项目
Zephyr个人项目的代码结构–West提货单: zephyr和zephyr外部项目纳入到应用代码目录管理
Zephyr应用的代码结构–自定义开发板: 将自定义board纳入到应用代码目录管理
除了上面两个场景外,我们的硬件可能也有新的驱动需求,而该驱动不被Zephyr支持,如果不想将驱动放入Zephyr中,就需要将驱动纳入到应用代码目录。

Zephyr驱动的添加可以分为3个级别:

  1. 有驱动API抽象,有设备树绑定: 只用添加驱动代码
  2. 有驱动API抽象,无设备树绑定:添加设备树绑定文件和驱动代码
  3. 无驱动API抽象,无设备树绑定: 添加抽象API头文件,添加设备树绑定文件,添加驱动代码

驱动代码目录

驱动代码目录添加

在app/目录下添加drivers目录,如下

app
├── drivers
│   └── zephyr
│       ├── CMakeLists.txt
│       ├── Kconfig
│       └── sensor
│           ├── CMakeLists.txt
│           ├── Kconfig
│           └── rotary_encoder
                ├── CMakeLists.txt
                ├── Kconfig
                ├── rotary_encoder.c
                └── rotary_encoder.h

在drivers/zephyr下的将要添加的驱动类型分类,例如我需要添加传感器类型的驱动,就增加一个sensor文件夹
zephyr/CMakeLists.txt中指定该文件夹, 如果有其它驱动类型的文件夹也加入到该文件中

add_subdirectory(sensor)

zephyr/Kconfig包含各个驱动类型文件夹的Kconfig

rsource "sensor/Kconfig"

zephyr/sensor/CMakeLists.txt中指定要使用的驱动文件夹,例如这里要指定选择编码器

add_subdirectory_ifdef(CONFIG_ROTARY_ENCODER rotary_encoder)

zephyr/sensor/Kconfig包含该类型下各个驱动的Kconfig

rsource "rotary_encoder/Kconfig"

zephyr/sensor/rotary_encoder/CMakeLists.txt指定驱动的源代码

zephyr_include_directories(.)
zephyr_library()
zephyr_library_sources(rotary_encoder.c)

zephyr/sensor/rotary_encoder/Kconfig则是该驱动代码rotary_encoder.c要使用的配置选项

menuconfig ROTARY_ENCODER
        bool "Rotary Encoder Sensor"
        depends on GPIO
        help
          Enable driver for Rotary encoder sensors.

if ROTARY_ENCODER

config ROTARY_ENCODER_THREAD_PRIORITY
        int "Thread priority"
        default 10
        help
          Priority of thread used by the driver to handle interrupts.

config ROTARY_ENCODER_THREAD_STACK_SIZE
        int "Thread stack size"
        default 1024
        help
          Stack size of thread used by the driver to handle interrupts.

驱动代码由rotary_encoder.c和rotary_encoder.h组成,不是本文说明重点,如何实现驱动可以参考Zephyr驱动模型实现方式

指定使用驱动目录

Zephyr建议将外部目录的驱动作为module添加,在app/CMakeLists.txt中添加下面内容,构建时就会编译app/drivers

list(APPEND ZEPHYR_EXTRA_MODULES
  ${CMAKE_CURRENT_SOURCE_DIR}/drivers
)

设备树绑定文件目录

为了硬件上的灵活性,Zephyr引入了设备树,通过设备树绑定的方式将设备树转换为C宏来使用。Zephyr的设备树绑定文件可能不包含我们要用的硬件设备,这就需要我们自己添加。同样设备树绑定文件也可以纳入app的目录进行管理,在app目录下添加dts目录,里面放置设备树绑定文件

app
├── dts
│   └── bindings
│       └── sensor
│           └── rotary-encoder.yaml

rotary-encoder.yaml的编写和使用方法不是本文重点,详细可以参考Zephyr添加旋转编码器驱动
在app/CMakeLists.txt中添加下面内容,构建时编译设备树会查找到app/dts目录

list(APPEND DTS_ROOT ${CMAKE_SOURCE_DIR})

设备驱动API头文件目录

对于个人项目开发来说,设备驱动API一般是项目内使用,API抽象的普遍覆盖性并不一定要非常全,此外使用的人员也不需要大范围讨论,根据需求进行自定义就可以, 所形成的头文件放到对应的驱动目录即可,例如zephyr/sensor/rotary_encoder/rotary_encoder.h, 为了方便应用直接使用,可以在app/CMakeLists中添加

add_subdirectory(drivers)

之后应用代码中就可以直接”#include “rotary_encoder.h”

结束语

到此为止我们通过三篇文章可以将Zephyr代码, Zephyr外部项目,自定义board, 驱动都纳入到一个app的仓库进行管理,通过一个独立的app仓库可以驱动编译所必须的代码,既方便管理,又十分精简。
如果你使用的SOC都还未被Zephyr支持,也可以将soc的移植纳入到应用目录下进行管理,这部分目前我并没有使用过无法做实例解释可以参考https://docs.zephyrproject.org/latest/application/index.html#soc-definitions进行操作。

参考

https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/application_development/out_of_tree_driver
https://docs.zephyrproject.org/latest/samples/application_development/out_of_tree_driver/README.html