这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【ZephyrGD32F503V-EVAL】移植

共1条 1/1 1 跳转至

【ZephyrGD32F503V-EVAL】移植

高工
2026-07-03 19:16:48     打赏

我接到了一个GD32F503的zephyr RTOS移植任务,通过几天的努力,已经基本实现了,现在总结如下:

目录

  1. 参考了哪些文档(source-of-truth 清单)

  2. 文件全图(provenance)

  3. 完整目录树

  4. 移植 recipe:给下一个 GD 芯片用的 checklist

  5. 本次可复用的脚本 / 模板

  6. 附录 A:Zephyr 4.x symbol 改名词典


1. 参考了哪些文档(source-of-truth 清单)

移植过程中引用为权威依据的文档,按可获取性排:

1.1 厂商原始资料(vendor)

文件 / 路径用途在哪个 bug / 阶段被引用
D:\GD\gd32F503\docs\GD32F50x_用户手册_Rev1.4.pdf(829 页)Ground truth:内存映射、时钟树、Cortex-M33 中断表、AF SEL 范围、PLL 公式§阶段 2 时钟配置、阶段 3 DTS、阶段 5 linker
D:\GD\gd32F503\GD32F50x_Demo_Suites_V1.0.4\...\Ground truth:哪些 pin/AF 在实际 demo 被用过(vendor 自己保证「能跑」)阶段 4 pinctrl YAML、附录 B pin 速查表
D:\GD\gd32F503\GD32F50x_Demo_Suites_V1.0.4\...\Utilities\gd32f503v_eval.{h,c}Ground truth:板子 LED/KEY/COM 完整定义阶段 4 board DTS
D:\GD\gd32F503\GD32F50x_Firmware_Library_V1.0.3\...\GD32F50x_Firmware_Library\Ground truth:SPL CMSIS、标准外设库阶段 1 HAL 拷贝;gd32f50x.h 里 _BASE 系列宏被 Bug #1 引用为真值
D:\GD\gd32F503\GD32F50x_Firmware_Library_V1.0.3\...\CMSIS\GD\GD32F50x\Source\Templates\gd32f503xK.ldGround truth:F503 启动代码、链接脚本 MEMORY 段阶段 5 linker
板子原理图(在 Demo Suites V1.0.4 Docs/Schematic/ 下)Ground truth:哪些 pin 接 LED、按键、COMLED 极性 → Bug #3 衍生

1.2 Zephyr 既有移植参考

路径用途
D:\luglZephyrproject\zephyr\soc\gd\gd32\gd32f4xx\F4xx SOC 层:拿来套 F50x(同厂商兄弟)
D:\luglZephyrproject\zephyr\dts\arm\gd\gd32f4xx\F4xx DTS:拿来抄 RCU 时钟 ID 宏
D:\luglZephyrproject\zephyr\boards\gd\gd32f450i_eval\F450I EVAL 板:拿来套 GD32F503V-EVAL(同封装档)
D:\luglZephyrproject\zephyr\drivers\gpio\gpio_gd32.c上游 GPIO driver:Bug #2 / Bug #3 全部在这里发生
D:\luglZephyrproject\zephyr\subsys\shell\Kconfig、Kconfig.backendsshell 启动顺序、DEVICE_DT_GET 模板
D:\luglZephyrproject\zephyr\include\zephyr\sys\util_macro.hBIT macro 定义(Bug #4)
D:\luglZephyrproject\zephyr\include\zephyr\dt-bindings\clock\gd32f50x-clocks.h自己写的 clock ID 表,对照 demo suites 写对

1.3 工具

工具版本 / 路径用法
Zephyr SDKD:\luglZephyrproject\zephyr-sdk-1.0.1\zephyr-sdk-1.0.1west build / arm-zephyr-eabi-* 工具链
west1.5.0west build -b <board> .
dtcZephyr SDK 自带DTS 编译检查
SEGGER OzoneV3.50故障 halt + 反汇编 + 外设寄存器 Watch
J-Link烧录 + 调试;board_runner_args(jlink "--device=GD32F503RE")
PuTTY / Tera Term / minicomZephyr shell 串口交互

2. 文件全图(provenance)

2.1 复制的文件(vendor SPL / Demo Suites → Zephyr HAL)

原则:Zephyr HAL 是 vendor 库的「翻译层」。vendor 头文件是 ground truth,我们改 vendor 源码——HAL 层通过 #include <gd32f50x.h> 直接接入,但所有改动都集中在 compat shim 里(gd32f50x_compat.h)。

源目标 (相对 Zephyr 根)数量 / 文件数
D:\GD\gd32F503\GD32F50x_Firmware_Library_V1.0.3\...\Firmware\CMSIS\GD\GD32F50x\Include\modules/hal/gigadevice/gd32f50x/cmsis/gd/gd32f50x/Include/4 个 .h(gd32f50x.h, core_cm33.h, system_gd32f50x.h, gd32f50x_err_report.h)
D:\GD\gd32F503\GD32F50x_Firmware_Library_V1.0.3\...\Firmware\CMSIS\GD\GD32F50x\Source\modules/hal/gigadevice/gd32f50x/cmsis/gd/gd32f50x/Source/gd32f50x_err_report.c, system_gd32f50x.c
同上 Source\GCC\同上 Source\GCC\SPL 启动汇编(SPL 内核启动代码,我们不用作 Zephyr 的 Reset_Handler——Zephyr 自带 vector_table.S)
同上 Source\GCC\Ld\同上 Source\GCC\Ld\F50x linker scripts(参考用,实际 board 用的 linker 由 Zephyr template 生成
D:\GD\gd32F503\GD32F50x_Firmware_Library_V1.0.3\...\Firmware\GD32F50x_standard_peripheral\Include\modules/hal/gigadevice/gd32f50x/standard_peripheral/Include/27 个 外设头(gd32f50x_gpio.h, gd32f50x_usart.h, ...)
同上 Source\同上 Source/27 个 外设 .c 实现
D:\GD\gd32F503\GD32F50x_Firmware_Library_V1.0.3\...\Firmware\GD32F50x_usbfs_library\未拷USB FS 库,这次不需要(CONFIG_USB=n)
D:\GD\gd32F503\GD32F50x_Demo_Suites_V1.0.4\...\Utilities\只参考不拷gd32f503v_eval.{h,c} 内 LED/KEY/COM 定义在 board DTS 里重新写(不能直接 include 它,那是 STM32-style HAL)

口子提示:vendor 头文件里 BIT / REG32 / BITS 三大基础设施宏如果直接拷过来而不加 #ifndef 保护,会和 Zephyr util_macro.h 撞名,→ Bug #4。这次手动加了 #ifndef BIT

2.2 改写的 vendor 源(patch)

原则:vendor 源码尽量不动。但 GCC 在某些版本 / 配置下做静态分析会误报,而 SPL 厂商的代码写得很「乐观」(默认所有路径都被覆盖,不写 default: 初值)。这两类「误报且无人调用」的函数,可以直接 patch。

源文件(拷贝目标)行改动触发背景
modules/hal/gigadevice/gd32f50x/cmsis/gd/gd32f50x/include/gd32f50x.h218BIT(x) 加 #ifndef BIT ... #endif 保护Zephyr util_macro.h:36-46 已经先 define 了 BIT,没保护会撞名
modules/hal/gigadevice/gd32f50x/standard_peripheral/source/gd32f50x_rcu.c1264cksys_freq, ahb_freq, apb1_freq, apb2_freq, pll0_freq 加 = 0U-Wmaybe-uninitialized 警告(Bug #5)
modules/hal/gigadevice/gd32f50x/standard_peripheral/source/gd32f50x_rcu.c1265pll0sel, pll1sel, prediv0, pll0mf, prediv1, pll1mf, ck_src, idx, clk_exp 加 = 0U同上
modules/hal/gigadevice/gd32f50x/cmsis/gd/gd32f50x/source/system_gd32f50x.c966ck_src, idx, clk_exp 加 = 0U-Wmaybe-uninitialized(Bug #6)
modules/hal/gigadevice/gd32f50x/cmsis/gd/gd32f50x/source/system_gd32f50x.c969pll0sel, pll1sel, prediv0, pll0mf, prediv1, pll1mf, pll0div 加 = 0U同上

可重复:这些 patch 都是「加了等号 0U」这种纯增量改动,可以用一个 shell 脚本一次性给所有 GD 系列 HAL 应用。

2.3 新生成的文件

按层划:

HAL 模块层(modules/hal/gigadevice/gd32f50x/)文件作用
include/gd32f50x_compat.hcompat shim:屏蔽 F4xx vs F50x 在 SPL API 上的差异(单/双 CTL、AFIO/SYSCFG、有/无 toggle register)
pinconfigs/gd32f503xx.ymlF503 系列 pinmux AF 表,从 demo suites 实际用法 + 手册 §11 整理
SOC 层(zephyr/soc/gd/gd32/gd32f50x/)文件作用
KconfigSOC 系列定义(SOC_SERIES_GD32F50X、SOC_GD32F503)+ select GD32_HAS_AFIO_PINMUX 等
Kconfig.socSOC 子选项(默认 CPU / 工具链等)
Kconfig.defconfig.gd32f503时钟频率默认(252 MHz)、IRQ 数(88)、NUM_IRQ_PRIO_BITS=4
gd32_regs.h寄存器偏移 + 桥基址的统一描述(下面有详细注释)
soc.c / soc.hSystemInit、clock 初始化钩子、SOC_EARLY_INIT_HOOK / SOC_RESET_HOOK
DTS 层(zephyr/dts/arm/gd/gd32f50x/)文件作用
gd32f50x.dtsi通用:cpus 节点、armv8-m 包含、外设基址骨架
gd32f503.dtsiF503 全部外设节点:RCU、GPIOA-E、USART0/1/2、SPI0/1/2、I2C0/1、TIMER0/1..15/16、ADC0/1/2、DAC、EXTI、FMC、SYSCFG、AFIO、TRIGSEL、CTC、CMP、PMU、RTC、WWDGT/FWDGT、CAN0/1、USBFS、CAU/HAU/TRNG、DMA0/1、DMAMUX
gd32f503xk.dtsi1MB flash + 128KB SRAM(最大存储变体)
gd32f503xe.dtsi512KB flash + 64KB SRAM
gd32f503xc.dtsi256KB flash + 64KB SRAM
Board 层(zephyr/boards/gd/gd32f503v_eval/)文件作用
Kconfig.boardBOARD_GD32F503V_EVAL 入口
Kconfig.gd32f503v_evalBoard 内部 Kconfig 钩子
board.cmake烧录器相关(J-Link 配 GD32F503RE)
board.ymlTwister 元数据
gd32f503v_eval_defconfigboard 默认 Kconfig 集合
gd32f503v_eval.dts板上 LED / 按键 / chosen (zephyr,console = &usart0)
gd32f503v_eval-pinctrl.dtsiUSART0/I2C0/SPI0/PWM7 等 pinmux 映射
support/post_build.cmake烧录钩子
应用层(app/gd32f503_blink/)文件作用
prj.conf用户级开关:CONFIG_GPIO=y、CONFIG_SERIAL=y、CONFIG_CONSOLE=y、CONFIG_UART_CONSOLE=y、CONFIG_SHELL=y 等
src/main.c三灯流水 + printk 自检
boards/gd32f503v_eval.overlay用户 overlay(当前为空)
文档层文件角色
D:\GD\gd32F503\zephyt_docs\GD32F503_Zephyr_Porting_Plan.md移植写的方案
D:\GD\gd32F503\zephyt_docs\GD32F503_Actual_Porting_Report.md移植的事后报告
D:\GD\gd32F503\zephyt_docs\GD_Zephyr_Port_Recipe.md本文:文件溯源 + 移植 recipe

3. 完整目录树

D:\luglZephyrproject\                # Zephyr 根目录
├── zephyr\                          # Zephyr 主仓(不可改 vendor 上游)
│
├── modules\hal_gigadevice\
│   └── gd32f50x\                    # 新增 HAL 模块
│       ├── module.yml                # Zephyr HAL 模块描述(name: hal_gigadevice)
│       │
│       ├── cmsis/gd/gd32f50x/        # ← 整包从 SPL V1.0.3 拷过来
│       │   ├── Include/
│       │   │   ├── gd32f50x.h        # ← 最权威的 _BASE 真值表
│       │   │   ├── core_cm33.h
│       │   │   ├── system_gd32f50x.h
│       │   │   └── gd32f50x_err_report.h
│       │   └── Source/
│       │       ├── gd32f50x_err_report.c
│       │       ├── system_gd32f50x.c   # ← patch: `= 0U` 一处(行 966/969)
│       │       ├── ARM/startup_gd32f50x.s   # SPL 自带启动代码(参考用,不启用)
│       │       ├── GCC/
│       │       │   ├── startup_gd32f50x.S   # SPL 启动代码
│       │       │   ├── newlib/syscalls.c
│       │       │   └── Ld/*.ld             # F50x linker scripts
│       │
│       ├── standard_peripheral/      # ← 27 个外设,从 SPL V1.0.3 拷过来
│       │   ├── Include/
│       │   │   ├── gd32f50x_gpio.h        # Bug #2 / #3 关键源
│       │   │   ├── gd32f50x_usart.h
│       │   │   ├── gd32f50x_rcu.h          # Bug #1 关键源
│       │   │   ├── gd32f50x_fmc.h
│       │   │   ├── gd32f50x_adc.h
│       │   │   └── ... 共 27 个
│       │   └── Source/
│       │       ├── gd32f50x_gpio.c
│       │       ├── gd32f50x_usart.c
│       │       ├── gd32f50x_rcu.c          # ← patch: `= 0U` 两处
│       │       └── ... 共 27 个
│       │
│       ├── include/
│       │   └── gd32f50x_compat.h     # ★ 自写 compat shim(**Bug #2 + #3 主战场**)
│       │
│       └── pinconfigs/
│           └── gd32f503xx.yml        # ★ 自写 pinctrl AF 表
│
├── zephyr\soc\gd\gd32\gd32f50x\      # 新增 SOC 层
│   ├── Kconfig                     # ★ 自写
│   ├── Kconfig.soc                 # ★ 自写
│   ├── Kconfig.defconfig.gd32f503  # ★ 自写
│   ├── Kconfig.defconfig.series    # ★ 自写
│   ├── gd32_regs.h                 # ★ 自写(RCU / FMC / GPIO 等 offset + 桥基址)
│   ├── soc.h                       # ★ 自写
│   └── soc.c                       # ★ 自写(SystemInit 钩子)
│
├── zephyr\dts\arm\gd\gd32f50x\       # 新增 DTS 层
│   ├── gd32f50x.dtsi               # ★ 自写(armv8-m + cpus)
│   ├── gd32f503.dtsi               # ★ 自写(所有外设节点)
│   ├── gd32f503xk.dtsi             # ★ 自写(1MB flash)
│   ├── gd32f503xe.dtsi             # ★ 自写(512KB flash)
│   └── gd32f503xc.dtsi             # ★ 自写(256KB flash)
│
└── zephyr\boards\gd\gd32f503v_eval\ # 新增 board 层
    ├── Kconfig.board               # ★ 自写
    ├── Kconfig.gd32f503v_eval      # ★ 自写
    ├── board.cmake                 # ★ 自写
    ├── board.yml                   # ★ 自写
    ├── gd32f503v_eval_defconfig    # ★ 自写(默认 y Kconfig 集合)
    ├── gd32f503v_eval.dts          # ★ 自写(LED + KEY + chosen)
    ├── gd32f503v_eval-pinctrl.dtsi # ★ 自写(USART0/I2C0/SPI0/PWM7 pinmux)
    ├── doc/index.rst
    └── support/post_build.cmake

D:\GD\gd32F503\                       # 用户本地工程目录
├── GD32F50x_用户手册_Rev1.4.pdf      # 厂商资料(**最高优先级 ground truth**)
├── GD32F50x_Firmware_Library_V1.0.3\  # 厂商 SPL 源码(**被拷到 HAL 模块的根**)
├── GD32F50x_Demo_Suites_V1.0.4\     # 厂商参考 demo(**板子 pin 速查 ground truth**)
└── zephyt_docs\                       # 移植相关文档
    ├── GD32F503_Zephyr_Porting_Plan.md   # 移植**前**写的方案
    ├── GD32F503_Actual_Porting_Report.md # 移植**后**的事后报告
    └── GD_Zephyr_Port_Recipe.md          # ★ 本文:溯源 + recipe

D:\luglZephyrproject\app\gd32f503_blink\  # 用户应用目录
├── CMakeLists.txt
├── prj.conf
├── src/main.c
├── boards/
│   └── gd32f503v_eval.overlay       # 当前为空
├── build/                            # west build 产物(不入版本库)
└── docs/
    └── gd32f503_zephyr_port.md       # bug 详细技术文章(482 行)

图例:

  • <- 整包拷 是从 SPL 复制

  • ★ 自写 是新写的文件

  • ← patch 是改写的 vendor 源


4. 移植 recipe:给下一个 GD 芯片用的 checklist

这一节绑死 F503;任何 GD32 系列(GD32F3x0 / GD32F4xx / GD32F50x / GD32E5x / GD32A50 / GD32L2x / GD32VF103)都可以拿这个流程走。

4.0 决定要不要新加 HAL vs 用兄弟 HAL

先看看已有 HAL 是否覆盖

modules/hal/gigadevice/
├── common_include/   # 跨系列共用 HAL 抽象(gd32_gpio.h 等)
├── gd32f3x0/         # F3x0
├── gd32f4xx/         # F4xx
├── gd32f50x/         # F50x(**这次新建**)
├── gd32a50x/         # A50x
├── gd32e10x/         # E10x
├── gd32e50x/         # E50x
├── gd32f403/         # F403
├── gd32l23x/         # L23x
└── gd32vf103/        # VF103
  • 如果新芯片是已有 HAL 的兄弟系列(比如 GD32F5xx 已经存在,那 GD32F503 就是它的子系列)→ 在原 HAL 里加子目录即可,不要新开 HAL 模块。

  • 如果芯片架构 / 工具链差异大(比如 riscv-v 替代 arm)→ 新开 HAL。

4.1 移植前准备(spawn check)

4.1.1 必备文档类别来源优先级
用户手册 / Reference Manual厂商官网 + 内部 D:\GD\...docs\第一
SPL Vx.x / Standard Peripheral Library厂商官网 + 内部 SDK第一
Demo Suites Vx.x厂商官网 + 内部 SDK第一
板子原理图内部硬件组第一
Zephyr 主仓代码git clone 整套第二
Zephyr 同厂商的兄弟 HALzephyr/modules/hal/gigadevice/gd32*/第二
Zephyr 通用移植文档docs.zephyrproject.org第三
4.1.2 必备工具
Zephyr SDK(推荐 1.0+),west CLI,
SEGGER Ozone + J-Link(或厂商调试器 + pyOCD),
串口终端(PuTTY/Tera Term/minicom),
DTS 编译器 dtc(SDK 自带),
objdump(arm-zephyr-eabi-* 在 SDK 内),
grep + 文本编辑器(有 LSP 的体验翻倍),
Node / Python(用来现场算 offset 比手算快得多)。
4.1.3 信息表(在动 DTS 之前一定先填)项怎么拿备
ARM core用户手册 §2.1Cortex-M3 / M4 / M33 / M7 → 哪个 armvX-m.dtsi
FPU 是否有用户手册 §2.1 + SPL 启动 .fpu不确定就
TrustZone用户手册 §2开不开关系到 Kconfig 选 CPU_HAS_FPU 还是 TZ
AHB / APB 桥基址SPL 头 <chip>.h 的 _BUS_BASEDT 一切地址计算的真值表
APB1 / APB2 子基址同上用于选 AF 编号时知道哪个桥接
总 SRAM 起始用户手册 §1.3 + SPL 启动代码SRAM0 = 0x20000000 几乎所有 STM32/GD 如此
Flash 总容量(变体)SPL linker scriptsxk/xe/xc 多版本
中断向量数(IRQ 数)用户手册 §3 + SPL 头 IRQn enumKconfig.defconfig 里 NUM_IRQS
IRQ 优先级 bit 数用户手册 §3.1NUM_IRQ_PRIO_BITS
AF 范围用户手册 §11 GPIO+AFF4xx AF0~15,F50x 收窄到 AF0~8
GPIO 寄存器布局用户手册 §11 + SPL 头单 CTL 还是双 CTL(影响 compat shim)
EXTI 源选择寄存器用户手册 §3 + SPL 头用 SYSCFG 还是 AFIO,区别非常大
Toggle register 是否有用户手册 §11F4xx 有 GPIO_TG,F50x 没有

这一步必须在动 DTS/compat shim 之前做完。否则你就跟这次的 Bug #1 / #2 / #3 一样,改了好几轮才发现「哦原来 AHB1 桥基址不是 0x40010000」。

4.2 5 层结构 + 拷贝顺序

顺序层路径改还是拷
HAL cmsis/modules/hal/gigadevice/<chip>/cmsis/...整包拷 vendor
HAL standard_peripheral/modules/hal/gigadevice/<chip>/standard_peripheral/...整包拷 vendor
HAL compat shim + pinconfigs同上自写
SOCzephyr/soc/gd/gd32/<chip>/自写
DTSzephyr/dts/arm/gd/gd32/<chip>.dtsi自写(按 § 4.3 做)
Boardzephyr/boards/gd/<board>/自写
Applicationapp/<app>/用户自写
DebugOzone + J-Link第一次 boot 验证

4.3 DTS 编写清单(按步骤)

1.  cpus 节点:
    - arm core(M-profile)
    - clock-frequency = <手册 §9 的 CK_SYS>
    - #address-cells / #size-cells
    - mpu 子节点(Cortex-M33 需要)

2.  chosen 节点:
    - zephyr,sram = &sram0;
    - zephyr,flash = &flash0;
    - zephyr,console = &usart0  (或别的)
    - zephyr,shell-uart = &usart0  (启用 shell 才加)
    - zephyr,flash-controller = &fmc;

3.  通用桥节点:
    - rcu、gpioa/b/c/..、usart0/1、SPI0/1/2、I2C0/1、timer0..16、adc0/1/2、dac、
      fmc、syscfg、exti、afio、trigsel、ctc、cmp、pmu、rtc、wwdgt/fwdgt、
      can0/1、usbfs、cau/hau/trng、dma0/1、dmamux

4.  每个节点的 reg:必须从 vendor SPL `<chip>.h` 里 _BASE 真值表查
    ‐ 反例:注释手算 `AHB1 + 0x9000 = 0x40019000`,却忘了 AHB1 桥基址是
      0x40018000 不 0x40010000 → 整族外设基址全错 (本次 Bug #1)

5.  memory@<ORIG> 节点 + sizes(flash / sram 全容量)
    - 不同变体(xk/xe/xc)用 #include 区分 .dtsi

4.4 必过:3 件实事验证「能跑」

Plan 阶段只验证 build pass,这是不够的首轮 boot 实物验证要在第 1 周内发生,不然接下来几周都会在猜。

必过项怎么过为什么
LED 跑一次(哪怕只是常亮)gpio_pin_configure_dt + gpio_pin_set 一轮验证 DTS 把 GPIO 节点变成可访问的 struct device*
USART0 跑一次 console让 Zephyr 的 printk 落到 PC 端串口验证:USART clock、pinctrl AF、TX 路径
Ozone 能 halt + 看寄存器halt 后读 chip 关键寄存器(RCU.APBxEN、GPIO.CTL、USART.SR)验证 JTAG/SWD 不被大电流芯片干扰

任何一件过不了,回去查 DTS 里的 reg 地址——10 次有 9 次是这里错。

4.5 7 个常见坑 + 自检 checklist

这些是 F503 移植亲历 的 7 个 bug。下一个 GD 移植一开始就要把它们存档对一遍。

#类别现象自检
1DT 里 AHB1 桥基址手算首轮 boot BusFault,halt 在 z_arm_bus_fault,PC 在 clock_control_* 或 pinctrl_apply_state 里DT 的每个外设 reg 都对照 vendor <chip>.h _BASE 真值表,不要靠 hand-computed 注释
2compat shim 双 derefUsageFault UNALIGNED,PC 在 GPIO 配置函数里&(*X) == X 一定是单 deref lvalue;不要 (uint32_t)(cast) 包一层
3driver 假设 F4xx 寄存器布局跑起来了但部分 pin 配置失败(pin=8 或 15 跳到 base 位 0..1)在 Ozone 里看 GPIO.CTL 那些 pin 的 mode 字段,是不是 OUT_PP
4vendor 头缺 #ifndef 保护基础设施宏warning: "BIT" redefinedgrep vendor 头里的 BIT / REG32 / BITS,加保护
5,6SPL vendor 源 -Wmaybe-uninitialized3 个警告一起出通常是 switch-case 没覆盖,runtime 不调用即可;但为了清 build,加 = 0U 即可
7shell 提示符有但输入无响应提示符来,输入不来强制 CONFIG_SHELL_BACKEND_SERIAL_API_POLLING=y 绕开中断

4.6 验证矩阵(按 demo 对应)

验证项跑哪个 demo通过标志
GPIO 输出#01 GPIO_Running_LED三盏 300ms 切换
GPIO 输入(轮询)#02 GPIO_Key_Polling按键按下读出 0 / 松开读出 1
EXTI 中断#03 EXTI_Key_Interrupt按键触发 ISR
USART TX#04 USART_PrintfPC 端看到 printk 输出
USART RX(IRQ)#05 USART_Echo_Interrupt串口回显
USART TX(DMA)#06 USART_DMA大块数据吞吐
ADC#07 ADC_Temperature_Vrefint内部温度读数
I2C#12 I2C_EEPROM24C02 写读一致
SPI#13 SPI_Quad_FlashW25Q 写读一致
PMU 休眠#20 PMU_Sleep_WakeupStop → RTC / WKUP 唤醒
RTC#21 RTC_Calendar秒计数走起
PWM#22 TIMER_Breath_LEDPC7 渐变可见
USB#23 USB_FS枚举成功

每次过一个,把 ✅ 填进 plan § 7.2 的验收清单。

4.7 五个角色的工具脚本

4.7.1 拷 SPL(自动化拷贝)
# 给新 chip 时拷 SPL 的标准脚本。
# 跑完会输出:<src> -> <dst> 行清单
SRC=$1   # 比如 D:/GD/gd32a50x/AHPL_V1.0.3
DST=$2   # 比如 modules/hal/gigadevice/gd32a50x
CHIP=$3  # 比如 gd32a50x

if [ -z "$SRC" ] || [ -z "$DST" ] || [ -z "$CHIP" ]; then
    echo "Usage: $0 <src-root> <dst-root> <chip-name>"
    exit 1
fi

# CMSIS
mkdir -p "$DST/cmsis/gd/$CHIP"/{Include,Source/GCC/Ld}
cp -v "$SRC/Firmware/CMSIS/GD/$CHIP/Include/"*.h     "$DST/cmsis/gd/$CHIP/Include/"
cp -v "$SRC/Firmware/CMSIS/GD/$CHIP/Source/"*.c      "$DST/cmsis/gd/$CHIP/Source/"
[ -d "$SRC/Firmware/CMSIS/GD/$CHIP/Source/ARM" ] && \
    cp -v "$SRC/Firmware/CMSIS/GD/$CHIP/Source/ARM/"*.s "$DST/cmsis/gd/$CHIP/Source/ARM/" 2>/dev/null
[ -d "$SRC/Firmware/CMSIS/GD/$CHIP/Source/GCC" ] && \
    cp -rv "$SRC/Firmware/CMSIS/GD/$CHIP/Source/GCC/"  "$DST/cmsis/gd/$CHIP/Source/GCC/"

# Standard Peripheral
mkdir -p "$DST/standard_peripheral"/{Include,Source}
cp -v "$SRC/Firmware/${CHIP//a50x/A50x}_standard_peripheral/Include/"*.h \
      "$DST/standard_peripheral/Include/" 2>/dev/null \
   || cp -v "$SRC/Firmware/${CHIP^^}_standard_peripheral/Include/"*.h \
           "$DST/standard_peripheral/Include/" 2>/dev/null \
   || find "$SRC/Firmware/" -type d -name '*standard_peripheral*' -exec \
        cp -v {}/Include/*.h "$DST/standard_peripheral/Include/" \;

这个脚本不通用(路径名跟 GD32 系列 / SPL 版本绑得太死),但思路通用:先 find 找到 SPL 根,然后 cp -v 拷贝到对应位置、打日志、留 verbatim 行便于审计。

4.7.2 vendor 头#ifndef` 巡检脚本
#!/usr/bin/env bash
# grep vendor 头里同 Zephyr util_macro.h 撞名的宏
# 命中后要看是不是要加 #ifndef 保护
set -e
HEADER_DIR=${1:?usage: $0 modules/hal/gigadevice/<chip>/cmsis/gd/<chip>/Include}

for sym in BIT BITS BIT_MASK REG32 REG16 REG8; do
    hits=$(grep -E "^#define\s+${sym}\b" "$HEADER_DIR"/*.h | head -3)
    if [ -n "$hits" ]; then
        echo "==> $sym:"
        echo "$hits"
    fi
done
4.7.3 Ozone Watch 启动套装(按 SOC 类别选)
(M Series Cortex-M, GD/SPL 系列)
/* === 时钟门 === */
APBxEN_BASE + 0x?            ; (RCU APBxEN,per 手册 §9)
/* === 控制寄存器 === */
GPIO_BASE + 0x00 (CTL/IMODE) ; 模式
GPIO_BASE + 0x14 (OCTL)      ; 输出态
GPIO_BASE + 0x10 (ISTAT)     ; 输入态
USART_BASE + 0x08 (CTL1)     ; bit13 UE = 启用?
USART_BASE + 0x00 (SR)        ; bit5 RXNE / bit6 TC
4.7.4 dtc 编译检查(DTS 语法)
dtc -I dts -O dtb -o /dev/null path/to/your.dts 2>&1 | tee dts.log

4.8 失败模式示例(失败先查这几件

现象优先查
west build 直接不识别 boardSOC_GD32XXX=y 在 defconfig 里?Kconfig.board 里 BOARD_<X> = y?
编译通过但 .elf 没产出 zephyr.binlinker script 出错;查 build/zephyr/linker.cmd.dep
烧完完全不跑(halt 看 PC = 0x00000000 或 magic number)reset 流程没跑通;查 __start 里的 soc_reset_hook
BusFault halt 在 pinctrl_apply_state 入口pinctrl 节点没绑对,pin 在 reg 跑出范围
halt 在 clock_control_* 函数里DTS AHB/APB 桥基址错(Bug #1 那一类
halt 在 GPIO 配置函数里、UFSR UNALIGNED bit 1compat shim 写错(Bug #2 那一类
Pin 8-15 配置不到 OUT mode(mode 字段始终是输入态)driver 上游假设 F4xx 双 CTL 寄存器(Bug #3 那一类);加 #ifdef AF_PINMUX select
shell 提示符有,但 help 没反应CONFIG_SHELL_BACKEND_SERIAL_API_POLLING=y;或调 SHELL_BACKEND_SERIAL_INIT_PRIORITY

5. 本次可复用的脚本 / 模板

把这次踩的坑沉淀成 3 段 shell:

5.1 拷 SPL 到新 HAL 的模板(占位)

见 § 4.7.1。

5.2 vendor 头补丁自动加保护(占位)

见 § 4.7.2。TODO:扫 vendor 头里所有可能被 Zephyr 利用的宏(BIT, BITS, REG32, REG16, REG8, WRITE_BIT, …),批量加 #ifndef。

5.3 SPL -Wmaybe-uninitialized 自动化补丁(占位)

每个 vendor SPL 源文件有几个函数是「runtime 不会被调」的(SystemCoreClockUpdate、rcu_clock_freq_get 等)。写一个脚本:

  1. grep 文件中的局部变量声明

  2. 对每个声明加 = 0U(如果是裸 uint32_t xxx)

风险:不是所有声明都要 patch——只 patch 被编译器 warn 的。所以是 interactive 工作,半自动最合理。

5.4 工具脚本位置建议

app/<your_app>/tools/
├── copy_spl.sh                 # § 4.7.1
├── vendor_header_audit.sh      # § 4.7.2
├── maybe_uninit_patch.sh       # § 5.3
├── ozone_watch_template.txt    # § 4.7.3
└── dts_check.sh                # § 4.7.4

附录 A:Zephyr 4.x symbol 改名词典

这些在 prj.conf 写错时不会立刻报「symbol not found」,而是 Kconfig warnings 然后升级成 error 让 west build 失败。提前知道,省半小时查 Kconfig grep。

Zephyr 4.3 之前的名字Zephyr 4.x 的现行名字来源 Kconfig 文件
CONFIG_KERNEL_SHELL_CMDCONFIG_KERNEL_SHELLsubsys/shell/modules/kernel_service/Kconfig
CONFIG_DEVICE_SHELL_CMDCONFIG_DEVICE_SHELLsubsys/shell/modules/Kconfig
CONFIG_DATE_SHELL_CMDCONFIG_DATE_SHELLsubsys/shell/modules/Kconfig
CONFIG_DEVMEM_SHELL_CMDCONFIG_DEVMEM_SHELLsubsys/shell/modules/Kconfig
CONFIG_APP_VERSION_SHELL_CMDCONFIG_APP_VERSION_SHELLsubsys/shell/modules/Kconfig
CONFIG_ZYCLICTEST_SHELL_CMDCONFIG_ZYCLICTEST_SHELLsubsys/shell/modules/Kconfig
CONFIG_GPIO_SHELL_CMDCONFIG_GPIO_SHELLdrivers/gpio/Kconfig

使用方法:在 prj.conf 写一个新的 Kconfig 时,先 grep 一遍 subsys/shell/Kconfig* 等目标位置:

grep -rE "^config [A-Z_]+$" zephyr/subsys/shell/modules/ | head

把名字摸熟再写。


附录 B:Ozone Watch 通用模板(按 SOC 类别选地址)

第一次到一块新板子,给自己 6 个 Watch 就够定位 80% 的「寄存器层故障」。

B.1 STM32 / GD32 通用(按手册 §9「Memory map」+ §11 GPIO 章节定地址)

╔══════════════════════════════════════════════════════════════╗
║                 Watch 一栏(按 SOC 类别)                    ║
╠══════════════════════════════════════════════════════════════╣
║ Cortex-M + AHB/APB1/APB2 标准桥:                          ║
║   APBxEN_BASE  ; RCU_APBxEN 看 clock 门                    ║
║   GPIOA_BASE + 0x00  ; GPIOx.CTL  模式                     ║
║   GPIOx_BASE + 0x14  ; GPIOx.OCTL 输出态                   ║
║   USART0_BASE + 0x08 ; USARTx.CTL1 bit13 UE              ║
║   USART0_BASE + 0x00 ; USARTx.SR  bit5 RXNE              ║
║                                                             ║
║ 不同桥基址按手册 §1.4 memory map 替换:                   ║
║   GD32F50x: AHB1=0x40018000, APB2=0x40010000, APB1=0x40000000 ║
║   STM32F4xx: AHB1=0x40020000, APB2=0x40010000, APB1=0x40000000 ║
║   GD32F4xx: AHB1=0x40020000, APB2=0x40010000, APB1=0x40000000 ║
╚══════════════════════════════════════════════════════════════╝

B.2 故障定位映射

现象第一个看
LED 不亮 1(pin mode 没设好)GPIO.CTL mode bits
LED 不亮 2(clock 没开)RCU.APBxEN bit
LED 不亮 3(active 极性错)OCTL bit + 看板子「亮态」
串口不输出 1USART.CTL1 bit13 UE
串口不输出 2USART.CTL1 bit14 TE
串口不输出 3GPIO.CTL/OMODE pin AF 模式
串口输入无反应USART.SR bit5 RXNE,每次按键应该跳变

【验证】

编译sapmle\blink,已经成功的运行了流水灯:

image.png




关键词: Zephyr     GD32F503V-EVAL    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]