为 Zephyr 适配自己的开发板
为了入门 Zephyr,首先就需要有一块官方适配的开发板,但是大多数人没有,或者与列表上的有所不同。
手上的开发板有挺多,就用RTThread的Art-Pi来做演示吧,这是一块基于STM32H750XBH6的开发板,板上有一些比较常见的外设组件,如SDRAM、QSPI和SPI FLASH、WIFI等,足够入门了。
在这摆上 Art-Pi 的原理图
在开始之前先细说一下咱们的文件夹结构,首先是可以按照官方推荐,把咱们适配的board直接扔到 zephyr/boards/*
目录下,但我觉得这样太丑了,还有些污染目录,我们这次创建一个新项目,并单独创建 boards
文件夹。
# ~/zephyrproject/applications/artpi
.
├── boards
│ └── arm
│ └── artpi
│ ├── artpi_defconfig
│ ├── artpi.dts
│ ├── board.cmake
│ ├── Kconfig.board
│ ├── Kconfig.defconfig
│ └── support
│ └── openocd.cfg
├── CMakeLists.txt
└── src
└── main.c
Devicetree
Devicetree
是一种描述硬件的结构语言,Zephyr使用 Devicetree
来适配硬件驱动与进行硬件初始化设置。在这就不细说Devicetree的语法了。
// artpi.dts
/dts-v1/;
#include <st/h7/stm32h750Xb.dtsi>
#include <st/h7/stm32h750xbhx-pinctrl.dtsi>
/ {
model = "RTThread Art-Pi";
compatible = "rtt,art-pi";
chosen {
zephyr,console = &uart4;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
};
};
&clk_hse {
clock-frequency = <DT_FREQ_M(25)>;
status = "okay";
};
&clk_lse {
lse-bypass;
status = "okay";
}
&pll {
clocks = <&clk_hse>;
div-m = <5>;
mul-n = <192>;
div-p = <2>;
div-q = <2>;
div-r = <2>;
status = "okay";
};
&rcc {
clocks = <&pll>;
clock-frequency = <DT_FREQ_M(480)>;
d1cpre = <1>;
hpre = <2>;
d1ppre = <2>;
d2ppre1 = <2>;
d2ppre2 = <2>;
d3ppre = <2>;
status = "okay";
};
&uart4 {
pinctrl-0 = <&uart4_tx_pa0 &uart4_rx_pi9>;
pinctrl-names = "default";
current-speed = <115200>;
status = "okay";
}
这是一个最简单的配置,首先配置时钟树 clk_hse
clk_lse
pll
rcc
,参考了一下CubeMX的相关配置, SysTick
为 480M。接下来配置 uart4
的引脚和速率。
先写一个简陋的版本来测试能否正常工作。
Kconfig
在上面的文件结构中的Kconfig有 Kconfig.board
Kconfig.defconfig
artpi_defconfig
# Kconfig.board
config BOARD_ARTPI
bool "ArtPi board"
depends on SOC_STM32H750XX
# Kconfig.defconfig
if BOARD_ARTPI
config BOARD
default "ArtPi"
endif
# artpi_defconfig
CONFIG_SOC_SERIES_STM32H7X=y
CONFIG_SOC_STM32H750XX=y
# Enable MPU
CONFIG_ARM_MPU=y
# Enable HW stack protection
CONFIG_HW_STACK_PROTECTION=y
CONFIG_SERIAL=y
# console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
# Enable GPIO
CONFIG_GPIO=y
# Enable Clocks
CONFIG_CLOCK_CONTROL=y
# Enable pin controller
CONFIG_PINCTRL=y
Test
到此为止,我们完成了一个简单的移植(指只移植了时钟树和串口),可以用来进行简单的测试。
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
set(BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
set(BOARD artpi)
find_package(Zephyr REQUIRED)
project(artpi)
target_sources(app PRIVATE src/main.c)
// src/main.c
#include <zephyr/kernel.h>
void main()
{
printk("Hello Zephyr! %s\n", CONFIG_BOARD);
}

LED & Button
在完成以上内容后,我们来适配一些其他的简单外设,LED和Button。

GPIO_LED_B
<->PI8
GPIO_LED_R
<->PC15
GPIO_USER_KEY1
<->PH4
在 artpi.dts
中添加LED与Button的定义。
/ {
model = "RTThread Art-Pi";
compatible = "rtt,art-pi";
chosen {
zephyr,console = &uart4;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
};
leds {
compatible = "gpio-leds";
blue_led: led_1 {
gpios = <&gpioi 8 GPIO_ACTIVE_LOW>;
label = "User LD1";
};
red_led: led_2 {
gpios = <&gpioc 15 GPIO_ACTIVE_LOW>;
label = "User LD2";
};
};
keys {
compatible = "gpio-keys";
user_button: key_1 {
gpios = <&gpioh 4 GPIO_ACTIVE_LOW>;
label = "User Btn";
};
};
};