在实际项目的应用场景中,开发者往往需要基于CSK6接入新的硬件外设,例如摄像头、显示屏、触摸屏等,需要添加自定义驱动。csk6 sdk支持开发者在app应用目录下增加自定义驱动,本章节以增加型号为 BF30A2 摄像头驱动为例,展示如何在app应用项目下完成自定义驱动的添加。
在Zephyr应用程序目录下建立驱动目录drivers,并添加 BF30A2 摄像头驱动的.c文件,具体如下:
app
├── drivers
| ├── video
| | ├── CMakeLists.txt
| | ├── Kconfig.bf30a2
| | └── bf30a2.c
| ├── CMakeLists.txt
| └── Kconfig.drivers
└── dts
└──bindings
└──video
├── vendor-prefixes.txt
└── byd,bf30a2.yaml
drivers
目录与zephyr/drivers
目录结构相对应# SPDX-License-Identifier: Apache-2.0
zephyr_library_sources_ifdef(CONFIG_VIDEO_BF30A2 bf30a2.c)
CONFIG_VIDEO_BF30A2 为自定添加驱动的配置名称,bf30a2.c为自定义驱动的.c文件。
add_subdirectory_ifdef(CONFIG_VIDEO_BF30A2 video)
Kconfig.bf30a2是摄像头驱动代码bf30a2.c中要使用的配置选项,具体可参考csk6sdk/driver目录下对应类型驱动的Kconfig文件来完成修改,以下是BF30A2的Kconfig内容:
# BF30A2 driver
# Copyright (c) 2022 listenai
# SPDX-License-Identifier: Apache-2.0
config VIDEO_BF30A2
bool "1/15 inch QVGA CMOS Image Sensor BF30A2"
help
Enable driver for BF30A2 CMOS digital image sensor device.
config VIDEO_BF30A2_RECEIVE_BUF_NUM
int "Must be greater than or equal to 2"
default 2
help
Config the number of buffers that the bf30a2 driver receives raw data.
config VIDEO_BF30A2_RECEIVE_THREAD_PRIORITY
int "the priority of thread"
default -15
help
Config the priority of thread.
config VIDEO_BF30A2_TIMER_TIMEOUT
int "timeout of ms"
default 5
help
Config the timeout value for timer.
config VIDEO_BF30A2_INIT_PRIORITY
int "Init priority"
default 80
help
BF30A2 driver initialization priority.
rsource "video/Kconfig.bf30a2"
为了硬件上的灵活性,Zephyr引入了设备树,通过设备树绑定的方式将设备树转换为C宏来使用。Zephyr的设备树绑定文件可能不包含我们要用的硬件设备,这就需要我们自己添加。同样设备树绑定文件也可以纳入app的目录进行管理,在app目录下添加dts目录,里面放置设备树绑定文件。
.yaml
文件可参考csk6sdk/dts/bindings/video/
目录下对应类型驱动的.yaml文件来完成修改,以下是byd,bf30a2.yaml
文件内容:
# Copyright (c) 2022, listenai
# SPDX-License-Identifier: Apache-2.0
description: 1/15 inch QVGA CMOS Image Sensor
compatible: "byd,bf30a2"
properties:
pd-gpios:
type: phandle-array
required: false
description: pd-gpios
pwr-gpios:
type: phandle-array
required: false
description: power-gpios
product-id:
type: int
required: false
description: product-id
csk6-spec:
type: boolean
required: false
description: csk6-spec
label:
type: string
required: true
description: label
reg :
type: array
required: true
description: reg
spi:
type: phandle
required: false
description: spi-bus
pwms:
type: phandle-array
required: false
description: pwm output to xclk
xclk-freq:
type: int
required: false
description: xclk-freq
xclk-gpios:
type: phandle-array
required: false
description: xclk-gpios
include: i2c-device.yaml
vendor-prefixes.txt为供应商前缀注册,具体内容如下:
newvision NEWVISION Microelectronics Co., Ltd.
在app项目根目录下的CMakeLists.txt文件中通过add_subdirectory(drivers)
来指定使用自定义的驱动(drivers):
app
└── CMakeLists.txt
CMakeLists修改后的内容:
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(hello_world)
target_sources(app PRIVATE src/main.c)
# 引用自定义驱动
add_subdirectory(drivers)
在应用根目录/boards/csk6011a_nano.overlay
添加摄像头I2C和SPI引脚对应的设备树配置:
&csk6011a_nano_pinctrl{
pinctrl_i2c0_scl_default: i2c0_scl_default{
pinctrls = <&pinmuxb 2 8>;
};
pinctrl_i2c0_sda_default: i2c0_sda_default{
pinctrls = <&pinmuxb 3 8>;
};
pinctrl_spi1_sclk_default: spi1_sclk_default {
pinctrls = < &pinmuxb 0 7 >;
};
pinctrl_spi1_mosi_default: spi1_mosi_default {
pinctrls = < &pinmuxb 1 7 >;
};
pinctrl_spi1_cs_default: spi1_cs_default {
pinctrls = < &pinmuxa 9 7 >;
};
};
&gpt0 {
status = "okay";
};
&spi0 {
status = "disabled";
};
&spi1 {
status = "okay";
spi-max-frequency = <100000000>;
pinctrl-0 = <&pinctrl_spi1_sclk_default &pinctrl_spi1_mosi_default &pinctrl_spi1_cs_default>;
pinctrl-names = "default";
};
&i2c0 {
status = "okay";
pinctrl-0 = <&pinctrl_i2c0_scl_default &pinctrl_i2c0_sda_default>;
pinctrl-names = "default";
bf30a2: bf30a2@6e {
compatible = "byd,bf30a2";
status = "okay";
label = "VIDEO";
reg = <0x6e>;
product-id = <0x3b02>;
spi = <&spi1>;
xclk-gpios = <&gpioa 11 0>;
};
};
在应用跟目录下prj.conf
组件配置文件里增加video配置:
# video
CONFIG_SPI=y
CONFIG_I2C=y
CONFIG_DMA=y
CONFIG_PWM=y
CONFIG_VIDEO=y
CONFIG_VIDEO_BF30A2=y
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=25600
CONFIG_SCHED_MULTIQ=y
上述配置完成了自定义驱动所需要的操作,开发者即可在应用代码中使用自定义驱动,使用的方式和sdk默认支持的设备驱动方式一样,这里不展开说明,以下是BF30A2使用示例:
#define VIDEO_DEV DT_LABEL(DT_INST(0, byd_bf30a2))
const struct device *video = device_get_binding(VIDEO_DEV);
if (!device_is_ready(video)) {
LISA_LOGE(TAG, "ipm device is null.\n");
return;
}
本章节仅以BF30A2自定义驱动为例说明,开发者在实际项目开发过程中可能还会遇到显示屏、触摸屏等外设驱动的自定义开发,可参考本章节自定义驱动的说明,以及sdk默认驱动示例完成自定义驱动的添加。
sdk默认支持的显示屏驱动(sdk/driver/display):
sdk默认支持的触摸屏驱动(sdk/driver/kscan):
sdk默认支持的摄像头驱动(sdk/driver/video):
本示例基于CSK6-NanoKit开发板来实现,需要做如下准备工作:
CSK6 SDK
提供了bf30a2 camera
自定义驱动集成的示例,可以通过以下指令获取示例:
lisa zep create
boards→ csk6 → drivers → vidoe → bf30a2 → sample
bf30a2 sample创建成功。
在sample根目录下通过以下指令完成编译:
lisa zep build -b csk6011a_nano
csk6011a_nano
通过USB连接PC,通过烧录指令烧录:
lisa zep flash --runner pyocd