当前文档版本为 v0.7.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

Zephyr Board 配置指南

1 概述

Zephyr 使用一个名为 Board 的概念将各个板级硬件区分开,于是我们可以使用不同的 “board” 来编译不同的 App 工程;这种特性为实际项目提供了某种灵活性:如果 App 代码架构规划合理,将有办法使其很容易在不同 board 甚至 SoC 之间进行移植,缩短后续的开发周期。

Zephyr 默认的 board 存放目录为zephyr\boards,而对于 PAN1080 来说,其支持的所有 boards 所在目录为zephyr\boards\arm。目前 SDK 中支持 4 种 PAN108x EVB Board,及 1 种 PAN108x Mesh Dongle Board:

  1. pan108xxa1_evb:子板主控型号为PAN108X-XA1(512KiB Flash Size、32 Pin)

  2. pan108xxa3_evb:子板主控型号为PAN108X-XA3(512KiB Flash Size、48 Pin)

  3. pan108xxb1_evb/pan108xxb1_mesh_dongle:子板主控型号为PAN108X-XB1(1MiB Flash Size、32 Pin)

  4. pan108xxb5_evb:子板主控型号为PAN108X-XB5(1MiB Flash Size、64 Pin)

2 PAN1080 Evaluation Board

下面以 pan108xxb5_evb board 为例,介绍相关文件含义。

pan108xxb5_evb目录树结构如下:

<home>/01_SDK/zephyr/boards/arm/pan108xxb5_evb
├─board.cmake
├─Kconfig.board
├─Kconfig.defconfig
├─pan108xxb5_evb.dts
├─pan108xxb5_evb.yaml
└─pan108xxb5_evb_defconfig

其中:

  • board.cmake:板级 CMake 配置;

  • Kconfig.board:板级 Kconfig 定义;

  • Kconfig.defconfig:板级 Kconfig 默认值,配置后在 Menuconfig 中可修改;

  • pan108xxb5_evb.dts:板级 Devicetree 定义;

  • pan108xxb5_evb.yaml:板级测试相关信息(用于 zephyr 自动化单元测试系统);

  • pan108xxb5_evb_defconfig:板级 Kconfig 默认值,配置后在 Menuconfig 中不可修改;

2.1 board.cmake

board.cmake文件用于描述当前板级的 cmake 信息,目前主要是配置了 Jlink 相关参数,供 JLink 烧录和调试的时候调用:

# SPDX-License-Identifier: Apache-2.0

board_runner_args(jlink "--device=PAN1080XB" "--speed=2000")

include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake)
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)

:此文件非必要请不要修改,唯一可考虑修改的参数为"--speed=2000",可以根据实际情况修改 JLink 通信速率。

2.2 Kconfig.board

Kconfig.board文件用于描述当前板级的 Kconfig 定义,目前主要定义了当前 EVB 板的名称为BOARD_PAN108XXB5_EVB,并通过一系列select关键字,使能了 PAN1080 HAL 层的各个底层 Driver:

# PAN108X-XB5-EVB MCU configuration

# Copyright (c) 2020-2022 Shanghai Panchip Microelectronics Co.,Ltd.
# SPDX-License-Identifier: Apache-2.0

config BOARD_PAN108XXB5_EVB
	bool "PAN108X-XB5 Evaluation Board"
	depends on SOC_PAN1080XB5
	select USE_PANPLAT_ACC
	select USE_PANPLAT_ADC
	select USE_PANPLAT_CLKTRIM
	select USE_PANPLAT_DMAC
	select USE_PANPLAT_FMC
	select USE_PANPLAT_GPIO
	select USE_PANPLAT_I2C
	select USE_PANPLAT_I2S
	select USE_PANPLAT_KSCAN
	select USE_PANPLAT_LOWPOWER
	select USE_PANPLAT_PWM
	select USE_PANPLAT_PRF
	select USE_PANPLAT_QDEC
	select USE_PANPLAT_SPI
	select USE_PANPLAT_TIMER
	select USE_PANPLAT_UART
	select USE_PANPLAT_USB
	select USE_PANPLAT_WDT
	select USE_PANPLAT_WWDT
	select USE_PANPLAT_EFUSE

:此文件非必要请不要修改,但如果希望新增一些板级 Kconfig 定义,则直接在文件结尾新增定义即可。

2.3 Kconfig.defconfig

Kconfig.defconfig文件用于描述当前板级的默认值,并且此处配置的默认值是非强制的;换句话说,即使在此处配置了默认值,后续仍然可以在 Menuconfig 中或者 App 工程目录的prj.conf文件中进行强制修改:

# PAN108X-XB5-EVB MCU configuration

# Copyright (c) 2020-2022 Shanghai Panchip Microelectronics Co.,Ltd.
# SPDX-License-Identifier: Apache-2.0

if BOARD_PAN108XXB5_EVB

config BOARD
	default "pan108xxb5_evb"

# BT_CTLR depends on BT. When BT is enabled we should default to also
# enabling the controller.
config BT_CTLR
	default y if BT

# Use Panchip BLE Link Layer instead of Zephyr's
choice BT_LL_CHOICE
	default BT_LL_PANCHIP if BT_CTLR
endchoice

if BT_LL_PANCHIP

config BT_HCI_TX_STACK_SIZE
	default 2048

endif # BT_LL_PANCHIP

# Change default Logging configurations
if LOG

config LOG_BUFFER_SIZE
	default 5120

config LOG_STRDUP_BUF_COUNT
	default 8

config LOG_DEFAULT_LEVEL
	default 3

endif # LOG

if USB_DEVICE_STACK

config USB_DEVICE_VID
	default 0x2FE4

config USB_DEVICE_PID
	default 0x0001

config USB_DEVICE_MANUFACTURER
	default "Panchip"

config USB_DEVICE_REMOTE_WAKEUP
	default n

endif # USB_DEVICE_STACK

# Increase ztest_thread_stack[] from default 1024 to 2048, since
# the default size is not enough, such as when test fcb_raw cases.
config ZTEST_STACKSIZE
	default 2048
	depends on ZTEST

endif # BOARD_PAN108XXB5_EVB

:此文件可以根据实际需要进行修改。

2.4 pan108xxb5_evb.dts

pan108xxb5_evb.dts文件用于描述当前板级的 Devicetree 定义:

/*
 * Copyright (c) 2020-2022 Shanghai Panchip Microelectronics Co.,Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/dts-v1/;
#include <mem.h>
#include <panchip/pan1080/pan1080xb5.dtsi>

/ {
	model = "Panchip PAN108X-XB5 Evaluation Board";
	compatible = "panchip,pan108xxb5-evb", "panchip,pan1080xb5";

	chosen {
		zephyr,console = &uart0;
		zephyr,shell-uart = &uart0;
		zephyr,bt-mon-uart = &uart0;
		zephyr,bt-c2h-uart = &uart0;
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
		zephyr,code-partition = &slot0_partition;
	};

	soc {
		pin-controller@40030000 {
			/* port, pin, pinmux_name, pinmux_sel [, flag1, ... ] */
			DT_PAN_PINS(p0, 1, uart0_rx, PAN1080_PIN_FUNC_P01_UART0_RX, input-enable);
			DT_PAN_PINS(p0, 7, uart1_rx, PAN1080_PIN_FUNC_P07_UART1_RX, input-enable);
			DT_PAN_PINS(p0, 4, qdec_x0, PAN1080_PIN_FUNC_P04_QDEC_X0, bias-pull-up, input-enable);
			DT_PAN_PINS(p0, 5, qdec_x1, PAN1080_PIN_FUNC_P05_QDEC_X1, bias-pull-up, input-enable);
			DT_PAN_PINS(p3, 1, spi0_miso, PAN1080_PIN_FUNC_P31_SPI0_MISO, input-enable);
		};
	};

	leds {
		compatible = "gpio-leds";
		led_blue: led_b {
			gpios = <&p1 6 GPIO_ACTIVE_HIGH>;
			label = "LED_BLUE";
		};
	};

	pwmleds {
		compatible = "pwm-leds";
		pwm_led_red: pwm_led_r {
			pwms = <&pwm0 4 PWM_POLARITY_NORMAL>;
			label = "RGB_LED_RED";
		};
		pwm_led_green: pwm_led_g {
			pwms = <&pwm0 5 PWM_POLARITY_NORMAL>;
			label = "RGB_LED_GREEN";
		};
		pwm_led_blue: pwm_led_b {
			pwms = <&pwm0 6 PWM_POLARITY_NORMAL>;
			label = "RGB_LED_BLUE";
		};
	};

	buttons {
		compatible = "gpio-keys";
		key1: k1 {
			label = "KEY_1";
			gpios = <&p0 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
		};
		key2: k2 {
			label = "KEY_2";
			gpios = <&p0 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
		};
	};

	aliases {
		led0 = &led_blue;
		sw0 = &key1;
		pwm-led0 = &pwm_led_red;
		pwm-led1 = &pwm_led_green;
		pwm-led2 = &pwm_led_blue;
		pwm-0 = &pwm0;
		kscan0 = &kscan;
	};
};

&clk_xth {
	clock-frequency = <DT_FREQ_M(32)>;
	/* Enable the 32 MHz high speed crystal oscillator */
	status = "okay";
};

&clk_xtl {
	clock-frequency = <32768>;
	/* Enable the 32 KHz low speed crystal oscillator */
	status = "okay";
};

&dpll {
	/* f(dpll_output) = f(dpll_input) / clock_div * clock_mult */
	clocks = <&clk_xth>;
	clock-div = <2>;  /* Fixed to 2 */
	clock-mult = <4>; /* Can be 3 (48MHz) or 4 (64MHz) */
	status = "okay";
};

&rcc {
	clock-names = "clk_system", "clk_slow";
	clocks = <&dpll &clk_xtl>;
	clock-frequency-system = <DT_FREQ_M(64)>;
	clock-frequency-slow = <32768>;
	ahb-prescaler = <1>;
	apb1-prescaler = <1>;
	apb2-prescaler = <1>;
};

&dma0 {
	status = "okay";
};

&acc {
	status = "okay";
};

&p0 {
	status = "okay";
};

&p1 {
	status = "okay";
};

&p2 {
	status = "okay";
};

&p3 {
	status = "okay";
};

&p4 {
	status = "okay";
};

&p5 {
	status = "okay";
};

&uart0 {
	current-speed = <921600>;
	pinctrl-0 = <&p0_0_uart0_tx &p0_1_uart0_rx>;
	status = "okay";
};

&uart1 {
	current-speed = <115200>;
	pinctrl-0 = <&p0_6_uart1_tx &p0_7_uart1_rx>;
	status = "okay";
};

&timer0 {
	freq = <16000000>;
	status = "okay";
};

&timer1 {
	freq = <8000000>;
	status = "okay";
};

&timer2 {
	freq = <16000000>;
	status = "okay";
};

&pwm0 {
	pinctrl-0 = <&p1_0_pwm0_ch4 &p1_1_pwm0_ch5 &p1_6_pwm0_ch6>;
	status = "okay";
};

&adc {
	#io-channel-cells = <1>;
	status = "okay";
};

&qdec {
	event-threshold = <100>;
	polarity = "polarity-low";
	resolution = "cnt-resolution-1x";
	filter-threshold = "filter-threshold-3";
	pinctrl-0 = <&p0_4_qdec_x0 &p0_5_qdec_x1>;
	status = "okay";
};

&spi0 {
	pinctrl-0 = <&p3_0_spi0_mosi &p3_1_spi0_miso &p0_2_spi0_cs &p0_3_spi0_clk>;
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";
};

zephyr_udc0: &usbd {
	compatible = "panchip,pan-usbd";
	status = "okay";
};

&wdt {
	status = "okay";
};

&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x00000000 0x00010000>;
			read-only;
		};
		slot0_partition: partition@10000 {
			label = "image-0";
			reg = <0x00010000 0x00060000>;
		};
		slot1_partition: partition@70000 {
			label = "image-1";
			reg = <0x00070000 0x00060000>;
		};
		scratch_partition: partition@D0000 {
			label = "image-scratch";
			reg = <0x000D0000 0x00020000>;
		};
		storage_partition: partition@f0000 {
			label = "storage";
			reg = < 0xf0000 0xF000 >;
		};
	};
};

:此文件请谨慎修改,因为修改后可能会导致某些例程执行条件发生变化。如果某个 App 确实需要修改 dts 文件,则可以优先考虑通过 DTS Overlay 的方式进行修改,相关说明请参考 Zephyr配置系统指南 文档中的介绍。

2.5 pan108xxb5_evb.yaml

pan108xxb5_evb.yaml文件用于描述当前板级的测试环境相关信息,供 zephyr 自动化单元测试系统解析,以了解当前的板级硬件资源情况:

identifier: pan108xxb5_evb
name: PAN108X-XB5 Evaluation Board
type: mcu
arch: arm
toolchain:
  - zephyr
  - gnuarmemb
  - xtools
ram: 64
flash: 1020
supported:
  - adc
  - counter
  - dma
  - flash
  - gpio
  - i2c
  - kscan
  - pinmux
  - pwm
  - qdec
  - serial
  - spi
  - usb
  - watchdog

:仅供 Zephyr 自动化单元测试系统使用,一般实际项目中可以不用关心此文件。

2.6 pan108xxb5_evb_defconfig

pan108xxb5_evb_defconfig文件用于配置当前板级的默认值,并且此处配置的默认值是强制的,注意这点与Kconfig.defconfig不同;换句话说,如果在此处配置了默认值,那么后续将无法在 Menuconfig 中或者 App 工程目录的prj.conf文件中再进行修改:

# SPDX-License-Identifier: Apache-2.0

# SoC Configuration
CONFIG_SOC_SERIES_PAN1080=y
CONFIG_SOC_PAN1080XB5=y
# Board Configuration
CONFIG_BOARD_PAN108XXB5_EVB=y

# Kernel Memory Options (Total SRAM 64KB)
CONFIG_MAIN_STACK_SIZE=1280
CONFIG_IDLE_STACK_SIZE=1024
CONFIG_ISR_STACK_SIZE=1024
# Prevent Interrupt Vector Table in RAM
CONFIG_IS_BOOTLOADER=y

# Serial Drivers
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
# UART Console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# Pinmux Driver
CONFIG_PINMUX=y
# GPIO Controller
CONFIG_GPIO=y
# Clock Control
CONFIG_CLOCK_CONTROL=y

# Enable stack sentinel feature to make it easy to find issue
# caused by stack overflow
CONFIG_STACK_SENTINEL=y

# Set default BT log level to 4 (DBG)
# CONFIG_BT_LOG_LEVEL_DBG=y

:此文件可以根据实际需要进行修改。

3 创建一个自己的 Board

3.1 为什么要创建自己的 Board

由前面的介绍我们知道,SDK 中已经存在 2 个对应 PAN1080 EVB 的 board,其中的 DTS 文件描述了 EVB 的板级硬件资源以及各板级硬件模块之间的连接关系,Kconfig 文件中则配置了能保证各个例程均能正确运行所需要开启的 Zephyr 功能。

而然,对于一个实际项目来说,一定有单独的板级硬件,其中的硬件资源可能与 EVB 上的完全不同了,并且使用过程中所需的板级 Kconfig 配置也大概率会与 EVB 不同,因此,为自己的项目重新创建一个 zephyr board 是一个必要且合理的选择。

3.2 如何创建 Board

创建 Board 最简单的方法是从当前已有的模板中修改,方法如下(假设新的 board 硬件主控 SoC 型号与 pan108xxb5_evb 相同,如 PAN1080LB5,并将新的 board 命名为my_custom_board):

  1. zephyr\boards\arm路径下的pan108xxb5_evb目录整体拷贝一份,并重新命名为my_custom_board

  2. 进入my_custom_board子目录:

    1. pan108xxb5_evb.yaml文件删除;

    2. 分别将pan108xxb5_evb.dtspan108xxb5_evb_defconfig文件重命名为my_custom_board.dtsmy_custom_board_defconfig

    3. 打开Kconfig.board文件,将其中的 Kconfig 定义修改为:

      config BOARD_MY_CUSTOM_BOARD
      	bool "My Custom Board"
      
    4. 打开Kconfig.defconfig文件,将其开头的 if 判断条件,以及 BOARD 默认值改为:

      if BOARD_MY_CUSTOM_BOARD
      
      config BOARD
      	default "my_custom_board"
      
      ...
      
      endif # BOARD_MY_CUSTOM_BOARD
      
    5. 打开my_custom_board_defconfig文件,将当前的 Board Configuration 修改为新的 board 名称:

      ...
      
      # Board Configuration
      CONFIG_BOARD_MY_CUSTOM_BOARD=y
      
      ...
      
    6. 打开my_custom_board.dts文件,修改根节点下的modelcompatible值,以与 EVB 作区分:

      ...
      
      / {
      	model = "My custom Board";
      	compatible = "vendor,my-custom-board", "panchip,pan1080a-afld";
      
      ...
      
  3. 至此,一个除名称不同外,各种配置完全与 EVB 相同的可用 board 就创建好了;这时候我们打开ZAL工具,在 Board 下拉菜单上可以看到新创建的board已经被成功识别:

    image

    使用 ZAL 工具识别新增的 Board

  4. 我们选择这个新增的my_custom_board,编译 Synchronization 例程:

    image

    使用新增的 Board 编译 Synchronization 例程

  5. 直接点击Flash按钮进行烧录,查看 UART 串口 Log,可以看到例程成功运行,并且 board 名称也已经与我们新修改的相同:

    image

    烧录新编译的 Synchronization 例程

注意:在实际项目中,仅仅将 Board 重命名是不够的,后续还应根据实际需要:

  1. 修改 DTS 文件中的其他部分,以符合实际的板级硬件情况;

  2. 修改 Kconfig 文件中的其他部分,以符合当前项目的实际需求;

4 更多相关文档

  1. Zephyr Board Porting Guide:Zephyr官方板级目录移植指南