自学内容网 自学内容网

移植 Zephyr 到 Art-Pi

背景

​ 最近工作中接触到了 Zephyr,不由觉得 Zephyr 是个很强大、全面、优秀的实时操作系统,但同时是有一定的上手难度的,其复杂的构建系统让小编倒吸一口凉气。为了深入研究并完全掌控 Zephyr,小编决定把它移植到手头的开发板上,为后续探究 Zephyr 源码仓库的构建原理、系统启动原理、多种调度机制 打下基础。

基础知识

  • 搭建 Zephyr 环境
  • 能够使用基本的 west 命令编译、烧录、调试 bsp

可通过 Zephyr 源码调试 章节验证基础知识的掌握程度。具体 west 工具的细节以及整个 elf 文件链接过程暂时不要深究,这是个很深的坑。

移植

​ Zephyr 仓库下面有很多开发板的基础 bsp,我们可以寻找一个与我们开发板上芯片型号类似的 bsp 作为参考。Art-Pi 主控是 Stm32H750XBH6,主频高达 480Mhz,片上资源非常丰富。

我们可以参考 zephyr/boards/st 目录下的 stm32h750b_dk ,该目录树结构如下:

stm32h750b_dk
├── Kconfig.stm32h750b_dk
├── arduino_r3_connector.dtsi
├── board.cmake
├── board.yml
├── doc
│   ├── img
│   │   └── stm32h750b_dk.png
│   └── index.rst
├── stm32h750b_dk.dts
├── stm32h750b_dk.yaml
├── stm32h750b_dk_defconfig
└── support
    └── openocd.cfg

各文件描述如下:

  • Kconfig.stm32h750b_dk : 板级 Kconfig 定义,用于控制板级资源,如使能 HAL 层的各个驱动
  • arduino_r3_connector.dtsi : arduino 扩展引脚设备树定义,我们的板子不需要该文件,直接删除
  • board.cmake :板级 CMake 配置,一般用于配置板子所使用的调试器参数,比如使用 openocd 作为调试器 Server
  • board.yml : 板级描述文件,暂时不清楚有什么用,但没有这个文件,构建系统会报错
  • doc:板子介绍
  • stm32h750b_dk.dts : 板子设备树定义
  • stm32h750b_dk.yaml : 板级测试相关(Zephyr 自动化单元测试系统使用)
  • stm32h750b_dk_defconfig : 板级 Kconfig 默认值,如果在此处配置了默认值,就无法通过 menuconfig 或者 App 目录下的 pri.conf 文件中进行修改
  • openocd.cfg : openocd 配置文件,如果 board.cmake 中使用 openocd 作为调试器的 server,该文件将会被传递给 openocd 使用

主要是板子设备树文件比较重要,该文件涉及芯片时钟、外设、内存、flash 配置。其余文件中的内容全部改为自己的开发板,Art-Pi 设备树文件最终配置如下:

/*
 * Copyright (c) 2023 STMicroelectronics
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/dts-v1/;
#include <st/h7/stm32h750Xb.dtsi>
#include <st/h7/stm32h750xbhx-pinctrl.dtsi>
#include <zephyr/dt-bindings/input/input-event-codes.h>

/ {
model = "STM32H750XBH6 ART PI";
compatible = "st,stm32h750xb-art-pi";

chosen {
zephyr,console = &uart4;  // uart4 作为控制台输出
zephyr,shell-uart = &uart4; // uart4 作为控制台输入
zephyr,sram = &sram0; // 使用 sram0 作为片内 sram,sram0 的定义在 dtsi 文件中
zephyr,flash = &flash0; // 使用 flash0 作为片内 flash,这个并不决定链接时各符号的加载地址,而是由 CONFIG_FLASH_BASE_ADDRESS 这个宏决定,zephyr 构建系统的链接脚本有点复杂,暂时不深究
};

leds {
compatible = "gpio-leds";
blue_led: led_1 {
gpios = <&gpioi 8 GPIO_ACTIVE_LOW>; // 定义板子蓝灯引脚
label = "USER2 LD7";
};
red_led: led_2 {
gpios = <&gpioc 15 GPIO_ACTIVE_LOW>; // 定义板子红灯引脚
label = "USER2 LD7";
};
};

gpio_keys {
compatible = "gpio-keys"; // 定义板子按键引脚
user_button: button {
label = "User";
gpios = <&gpioh 4 GPIO_ACTIVE_LOW>;
zephyr,code = <INPUT_KEY_0>;
};
};

sdram1: sdram@c0000000 { // 定义板子片外 sdram 地址,使用 fmc 驱动
compatible = "zephyr,memory-region", "mmio-sram";
device_type = "memory";
reg = <0xc0000000 DT_SIZE_M(32)>; // 定义 sdram 起始地址、尺寸
zephyr,memory-region = "SDRAM1";
zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>;
};

aliases {
led0 = &blue_led;
led1 = &red_led;
sw0 = &user_button;
};
};

&clk_hse { // 外部 hse 定义
clock-frequency = <DT_FREQ_M(25)>;
status = "okay";
};

&pll { // pll 配置,h750 系列的时钟树比较复杂,可通过 cubemx 简化配置
div-m = <5>;
mul-n = <192>;
div-p = <2>;
div-q = <4>;
div-r = <4>;
clocks = <&clk_hse>;
status = "okay";
};

&rcc { // 系统各时钟域配置
clocks = <&pll>;
clock-frequency = <DT_FREQ_M(480)>;
d1cpre = <1>;
hpre = <2>;
d1ppre = <2>;
d2ppre1 = <2>;
d2ppre2 = <2>;
d3ppre = <2>;
};

&uart4 { // uart4 作为 zephyr 控制台
pinctrl-0 = <&uart4_tx_pa0 &uart4_rx_pi9>;
pinctrl-names = "default";
current-speed = <115200>;
status = "okay";
};

&fmc { // fmc 配置,用于驱动 sdram 芯片
status = "okay";
pinctrl-0 = <&fmc_nbl0_pe0 &fmc_nbl1_pe1
     &fmc_sdclk_pg8 &fmc_sdnwe_ph5 &fmc_sdcke0_pc3
     &fmc_sdne0_pc2 &fmc_sdnras_pf11 &fmc_sdncas_pg15
     &fmc_a0_pf0 &fmc_a1_pf1 &fmc_a2_pf2 &fmc_a3_pf3 &fmc_a4_pf4
     &fmc_a5_pf5 &fmc_a6_pf12 &fmc_a7_pf13 &fmc_a8_pf14
     &fmc_a9_pf15 &fmc_a10_pg0 &fmc_a11_pg1 &fmc_a12_pg2
     &fmc_a14_pg4 &fmc_a15_pg5 &fmc_d0_pd14 &fmc_d1_pd15
     &fmc_d2_pd0 &fmc_d3_pd1 &fmc_d4_pe7 &fmc_d5_pe8 &fmc_d6_pe9
     &fmc_d7_pe10 &fmc_d8_pe11 &fmc_d9_pe12 &fmc_d10_pe13
     &fmc_d11_pe14 &fmc_d12_pe15 &fmc_d13_pd8 &fmc_d14_pd9
     &fmc_d15_pd10>;
pinctrl-names = "default";

sdram {
status = "okay";
power-up-delay = <100>;
num-auto-refresh = <8>;
mode-register = <0x221>;
refresh-rate = <0x02A5>;

bank@0 {
reg = <0>;

st,sdram-control = <STM32_FMC_SDRAM_NC_9
STM32_FMC_SDRAM_NR_13
    STM32_FMC_SDRAM_MWID_16
                        STM32_FMC_SDRAM_NB_4
    STM32_FMC_SDRAM_CAS_2
    STM32_FMC_SDRAM_SDCLK_PERIOD_2
    STM32_FMC_SDRAM_RBURST_ENABLE
    STM32_FMC_SDRAM_RPIPE_0>;
st,sdram-timing = <2 8 6 6 2 2 2>;
};
};
};

仅通过如上配置就能够编译并链接通过,其背后是 Zephyr 对 stm32 系列芯片 hal 库以及外设驱动的完美适配,以至于用户仅通过简单的设备树描述就能让外部设备正常工作起来。最终 Art-Pi 目录结构如下:

stm32h750_art_pi
├── Kconfig.defconfig
├── board.cmake
├── board.yml
├── stm32h750_art_pi.dts
├── stm32h750_art_pi_defconfig
└── support
    └── openocd.cfg // openocd 默认会掉用 openocd.cfg 文件,该文件用于描述 openocd 控制的硬件调试器,如 stlink,jlink 

板级调试

​ 以上步骤全部通过后会面临一个问题:如何将固件搞到芯片里面?由于我是使用的 stm32 系列,同时拥有 stlink 调试器,可通过 STM32CubeProgrammer 工具擦除并将固件下载到 flash。但会遇到一个问题,固件并没有按照预期执行,甚至没跑到 main 线程,此时连串口都不能打印日志,此时如果拥有调试器,那便是如虎添翼。

​ Zephyr 的构建系统是支持下载以及调试能力的,这时候也不需要使用 STM32CubeProgrammer 了。一般调试嵌入式设备需要硬件调试器(板子不足以运行 gdb server,但 Zephyr 貌似支持 gdb stub,这样的话可以不需要硬件调试器)、硬件调试器配套的 gdb server(stlink server、jlink server、openocd)、gdb。我们选择使用 openocd 作为 gdb server。可通过使用 west flash 命令验证能否下载固件,如图:请添加图片描述
​ 这一命令的背后到底发生了什么?其本质是调用 openocd 来将固件下入芯片内,但这背后是如何调用起 openocd,暂时不深追,这个坑很深,也正是 Zephyr 构建系统的复杂且神秘之处,给人一种知其然不知其所以然的感觉,小编决定后续几章来深究 Zephyr 构建系统原理。

​ 此时一般会发现固件跑不起来,这时候,可以使用 west debugserver 命令来起一个 gdb server,这个 gdb server 就是 openocd,它在某个端口上起一个 tcp 服务,通过 tcp 与 gdb client 交互,双方通信是明文传输,如图:请添加图片描述
​ Openocd 说它监听 3333 端口,此时我们便可以通过 gdb 来连接 3333 端口进行调试了,如图:

请添加图片描述

​ 使用命令行的方式虽然能进行调试,但是很麻烦,效率不高,这时候可参考 Zephyr 源码调试章节 进行图形化界面调试,这样子能大大提高解决问题的效率,终极调试界面如图:

请添加图片描述
我的开发环境是 wsl ubuntu,使用 wsl 连接 usb 设备需要简单的配置一下,可网上搜索 wsl usb 关键字查看相关教程。

应用配置

​ 移植完毕后,可通过 Zephyr 仓库 zephyr/samples/basic/blinky 下的应用来验证,比如可在 main 函数中翻转 led 灯来验证。但此时,Zephyr 的 shell 还不能使用,因为 shell 作为 Zephyr 的一个子系统此时还未使能,这也是 Zephyr 构建系统的一大优势,以搭积木的形式构建系统,缺少某一模块,仍然能够编译链接通过,仅仅是该能力缺失而已。可在 zephyr/samples/basic/blinky 下的 prj.conf 文件中添加如下配置:

CONFIG_GPIO=y
CONFIG_UART_CONSOLE=y //使能 uart console
CONFIG_SHELL=y //使能 shell 模块
CONFIG_MEMC=y
CONFIG_MEMC_STM32=y
CONFIG_MEMC_STM32_SDRAM=y

​ 最终就能丝滑的感受 Zephyr 了,这才有点操作系统的味道。
请添加图片描述
最终附上 项目地址 ,欢迎 Star~~~


原文地址:https://blog.csdn.net/m0_56548489/article/details/136978328

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!