-
背景
在zephyr中支持的板子数量多大150+,但是难免会有没有涉及到板子,这时候怎么办呢,so轮到我上了,自己移植一个呗。 -
自定义板移植
2.1 需要添加的文件结构
boards/
soc/
CMakeLists.txt
prj.conf
README.rst
src/
其中boards目录下就是要构建的电路板:
.
├── boards
│ └── arm
│ └── my_custom_board
│ ├── doc
│ │ └── img
│ └── support
└── src
2.2 构建电路板
如上结构,boards目录下会有架构的支持,在相应的架构下添加我们自己的电路板。构建电路板要遵循zephyr的构建规则,并提供一下文件:
my_custom_board_defconfig
my_custom_board.dts
my_custom_board.yaml
board.cmake
board.h
CMakeLists.txt
doc/
dts_fixup.h
Kconfig.board
Kconfig.defconfig
pinmux.c
support/
其中.dts文件是设备树的描述文件,此文件用来配置电路板板载的功能。还有一个比较重要的文件是pinmux.c,内容是管脚功能配置,此文件在某些板子中必须有比如stm32系列,msp430的板子上就没有,这是因为不同的芯片厂商所作的芯片结构不同,SDK支持不同,自己看情况吧。
2.2.1 添加板载默认配置
- 添加板子的名称
if BOARD_NUCLEO_L431CB
config BOARD
default "nucleo_l431rc"
- 添加基本外设
if SPI
config SPI_1
default y
config SPI_STM32_INTERRUPT
default y
endif # SPI
- 添加没有驱动的外设
2.3 添加SOC支持
soc文件夹的结构同boards类似,结构如下:
soc
└── arm
│ └── st_stm32
│ ├── common
│ └── stm32l4
└── Kconfig
首先添加自定义的Kconfig文件:
# SPDX-License-Identifier: Apache-2.0
choice
prompt "SoC/CPU/Configuration Selection"
source "$(SOC_DIR)/$(ARCH)/*/Kconfig.soc"
endchoice
menu "Hardware Configuration"
osource "$(SOC_DIR)/$(ARCH)/Kconfig"
osource "$(SOC_DIR)/$(ARCH)/*/Kconfig"
module = SOC
module-str = SOC
source "subsys/logging/Kconfig.template.log_config"
endmenu
使用cmake添加对自定义平台的位置信息,来构建平台的应用程序:
cmake -B build -GNinja -DBOARD=<board name> -DSOC_ROOT=<path to soc> -DBOARD_ROOT=<path to boards> .
ninja -C build
2.4 添加设备树节点
需要添加一下目录下的文件哦:
dts/common/
dts/arm/
dts/
########### 分隔符 ##################
include/
dts/bindings/
这里之所以用分割符,是由于分割符下面的两个涉及到设备驱动的添加,在我的另一篇添加驱动里面讲过这里不在讲。
一般在添加设备书节点都会用到定义flash和SDRAM,一般都会包含头文件dts/common/mem.h来定义大小,查询数据手册来添加节点的入口地址。
dts/架构/soc系列会添加关于soc设备的节点,示例:
#include <st/l4/stm32l4.dtsi>
/ {
soc {
pinctrl: pin-controller@48000000 {
gpiod: gpio@48000c00 {
compatible = "st,stm32-gpio";
gpio-controller;
#gpio-cells = <2>;
reg = <0x48000c00 0x400>;
clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000008>;
label = "GPIOD";
};
gpioe: gpio@48001000 {
compatible = "st,stm32-gpio";
gpio-controller;
#gpio-cells = <2>;
reg = <0x48001000 0x400>;
clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000010>;
label = "GPIOE";
};
};
i2c2: i2c@40005800 {
compatible = "st,stm32-i2c-v2";
clock-frequency = <I2C_BITRATE_STANDARD>;
#address-cells = <1>;
#size-cells = <0>;
reg = <0x40005800 0x400>;
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00400000>;
interrupts = <33 0>, <34 0>;
interrupt-names = "event", "error";
status = "disabled";
label= "I2C_2";
};
spi2: spi@40003800 {
compatible = "st,stm32-spi-fifo";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x40003800 0x400>;
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>;
interrupts = <36 5>;
status = "disabled";
label = "SPI_2";
};
};
};
关于为什么这么定义,看设备树定义文档还有一篇是Linux下的设备树说明https://elinux.org/Device_Tree_Reference#Device_Tree_Usage
关于设备树的编译原理,稍后更新。