概要

在做小梅哥 ZYNQ 裸机课程中的 RGB TFT 图像显示实验时,我先后遇到了 Debug 卡 99%、System Debugger 异常、DDR 参数修改后 platform 混乱、BSP 绑定错误以及屏幕黑屏等一系列问题。 一开始一直以为是代码、SDK、排线或者开发板硬件有问题,最后才发现,真正的核心原因是 Vivado 导出的 platform、SDK 中的 BSP 和 Application 工程没有保持一一对应,再叠加老版本 SDK 调试链路不稳定,导致问题越来越复杂。 本文记录了整个排查过程、踩坑原因以及最终成功点亮 RGB TFT 屏幕的正确流程,希望能帮到遇到类似问题的同学。

前言

最近在做 ZYNQ 裸机开发中的 VDMA + RGB TFT 图像显示实验 时,连续踩了几个很典型但又很折磨人的坑:

  • Debug 一直卡在 99%
  • System Debugger 经常异常
  • TFT 屏幕一直黑屏,没有任何显示
  • 改了 DDR 配置后,SDK 里出现多个 platform
  • BSP、Application、hardware platform 三者关系越来越混乱

一开始我几乎把所有可能性都怀疑了一遍:

  • 代码写错了
  • RGB565 转换有问题
  • DDR 配置不对
  • LCD 排线插反了
  • 背光没开
  • SDK 坏了
  • 板子坏了

但最后发现,这些都不是单一主因。真正的问题,是整个 Vivado → SDK 的工程关系被我越改越乱,最终导致 platform、BSP、Application 没有保持一致。

这篇文章就把我这次从黑屏、99% 卡死,到最后成功出图的整个过程完整复盘一下,希望能帮到做同类实验的同学。

1. 实验背景

我做的是小梅哥 ZYNQ 裸机课程中的 基于 VDMA 的 RGB TFT 显示实验。
整个显示链路大致是:

  • PS 端 DDR 中存放图像数据
  • VDMA 从 DDR 读取图像
  • AXI4-Stream to Video Out 输出视频流
  • VTC 提供时序
  • RGB888 转 RGB565
  • 最终驱动 RGB TFT 屏显示图像
    在这里插入图片描述

从原理上看,这个实验逻辑并不算特别复杂,但一旦 Vivado 硬件配置、SDK 软件工程、DDR 参数、platform/BSP/Application 之间没有理顺,排查起来会非常痛苦。

2. 最开始出现的问题

2.1 Debug 一直卡在 99%

最开始最让我崩溃的现象就是:
点击 SDK 里的 Debug 之后,经常卡在:
在这里插入图片描述

Launching GDB Debug... (99%)

有时还伴随一些典型报错,比如:

AP transaction error, DAP status f0000021

或者:

Memory read error at 0xF8007080

以及:

Memory write error at 0x100000

这些报错会让人误以为:

  • 是代码问题
  • 是 DDR 坏了
  • 是 JTAG 驱动坏了
  • 是 SDK 坏了

但实际情况比这复杂得多。

2.2 屏幕一直黑屏

另一个更直接的问题是:
屏幕完全没显示
不是花屏,也不是错位,而是:

  • 没图像
  • 没明显背光变化
  • 看起来像根本没驱动起来
    在这里插入图片描述

这个时候最自然的怀疑方向就是:

  • LCD 排线插错
  • 屏坏了
  • 背光没开
  • RGB 数据没出来

但后面排查发现,真正的问题并不只是屏本身。

3. 一开始走过的弯路

3.1 怀疑 RGB888 转 RGB565 模块有问题

一开始我注意到了 rgb888to565 模块,担心是不是这里的位宽转换有问题。
后来证明,这不是导致黑屏和 99% 卡死的主因。

3.2 怀疑 LCD 排线问题

我反复检查了:

  • 排线方向
  • 插接位置
  • 屏幕接口

确认排线本身没有插反,也没有松脱。

3.3 怀疑 DDR 型号不正确

我的板子实际 DDR 型号是:

在这里插入图片描述

而工程最开始的 DDR 配置并不完全对应,后面确实做了修改。
这个点是问题的一部分,但并不是全部。

3.4 怀疑 SDK 软件坏了

因为 Debug 一直卡 99%,很容易让人以为是软件本身坏了。
但最后证明,SDK 本身不是“坏了”,而是:

工程关系乱了 + SDK 的调试链路本身也不稳定

4. 真正的核心问题是什么

最后把整个过程回头复盘后,我发现根因其实主要有三类。

4.1 修改 DDR 后,SDK 里生成了多个 platform

在 Vivado 里改过 DDR 参数后,我重新导出了硬件。
结果 SDK 里先后出现了:

system_wrapper_hw_platform_0
system_wrapper_hw_platform_1
system_wrapper_hw_platform_2

在这里插入图片描述

这本身并不是绝对错误,但如果继续在旧 workspace 里反复更新,就会非常容易混乱。

因为你很容易出现这种情况:

  • 当前硬件平台是新的
  • BSP 还是旧的
  • Application 工程又是另一套
  • Run/Debug 配置还可能指向更旧的一套 platform

于是最终结果就是:

  • 工程能编译
  • 但运行不正常
  • BSP regenerate 报错
  • Debug 卡 99%
  • 屏幕黑屏
    在这里插入图片描述

4.2 platform、BSP、Application 没有一一对应

这个是本次问题里最关键的点。

在 ZYNQ 的 Vivado + SDK 开发流程里,三者关系必须清楚:

platform
是 Vivado 导出的 硬件平台
BSP
是基于 platform 自动生成的 软件支持包
Application
是你自己的 应用程序

它们的关系应该始终是:

Vivado硬件设计
   ↓
platform
   ↓
BSP
   ↓
Application

也就是说:

一个 platform 对应一个 BSP,对应一个 Application

而我前面的问题,本质就是这三者关系被多次导入、更新之后弄乱了。

4.3 lcd_bl 背光信号处理有问题

在继续排查硬件设计时,我还发现了一个很关键的点:

lcd_bl 背光信号一开始没有被正确处理

如果背光控制信号不对,即使视频链路本身起来了,屏幕看起来仍然可能像“完全黑”。

这一点在后面的修正中也是影响最终能不能正常显示的重要因素。

5. 对 platform、BSP、Application 的重新理解

这次踩坑之后,我对这几个概念终于真正理解清楚了。

5.1 platform 是什么

platform 就是 硬件平台,来自 Vivado 导出的硬件设计信息,里面包括:

DDR 配置
PS 配置
bitstream
ps7_init
外设地址映射

你可以把它理解成:

当前这套硬件设计的“说明书 + 初始化信息”

5.2 BSP 是什么

BSP 是 Board Support Package,是基于当前 platform 自动生成的软件支持包,里面包括:

xparameters.h
各种驱动
standalone 库
设备地址宏定义

你代码里能直接使用的:

XPAR_VTC_0_DEVICE_ID
XPAR_PS7_DDR_0_S_AXI_BASEADDR

这些其实都来自 BSP。

5.3 Application 是什么

Application 就是你自己真正写的程序,比如:

helloworld.c
vdma_api.c
pic0.h

5.4 为什么这三者一定要对应

因为一旦你改了 Vivado 里的 DDR 或硬件结构,platform 就变了。
platform 一变,BSP 理论上也要重新生成,Application 也应该绑定新的 BSP 和 platform。

如果只是改了 platform,BSP 和 Application 还沿用旧的,那很容易出现:

编译没问题,运行异常,Debug 卡 99%,内存地址不对,程序下载失败。

6. 最终正确解决方案

真正让我最终跑通这套实验的办法,不是继续在旧工程上修修补补,而是:

开一个全新的 SDK workspace,重新搭一套干净工程

6.1 Vivado 侧:重新确认并导出正确硬件

在 Vivado 中,我重新确认了以下几点:

DDR 型号和板子实际一致
硬件设计连接正确
lcd_bl 背光信号处理正确
Validate Design
Generate Bitstream
Export Hardware,并勾选 Include bitstream

这一步的目标只有一个:

导出一份唯一正确的 hardware platform

6.2 SDK 侧:新建一个干净 workspace

这一点非常关键。

不要继续在旧 workspace 上修,因为旧 workspace 里很容易已经混进了:

多个 platform
多个 BSP
多个测试工程
多份 Run/Debug 配置

正确做法是:

在 SDK 里 Switch Workspace
选一个全新的空目录
从 Vivado 重新 Launch SDK

在这里插入图片描述

这样做完后,左边的 Project Explorer 里只剩下:

system_wrapper_hw_platform_0

在这里插入图片描述

这就说明环境干净了。

6.3 新建 BSP

在 SDK 中执行:

File -> New -> Board Support Package

在这里插入图片描述

新建:

rgb_tft_bsp

并绑定当前唯一的:

system_wrapper_hw_platform_0

6.4 新建应用工程

继续执行:

File -> New -> Application Project

新建:

rgb_tft

并选择已有 BSP:

rgb_tft_bsp

在这里插入图片描述

6.5 只复制旧工程里的源码文件

这里有一个非常容易出错的点:

只复制源码文件,不复制旧 BSP 和旧链接脚本

我最后只从旧工程里复制了这几个文件到新的 rgb_tft/src:

helloworld.c
pic0.h
platform.c
platform.h
platform_config.h
vdma_api.c

我没有复制:

旧的 lscript.ld
旧的 BSP
旧的 launch 配置

在这里插入图片描述

因为这些都应该基于新的 platform 重新生成。

6.6 Build + Program FPGA + Run

在新工程里完成这些操作后,我执行了:

Build Project
Xilinx Tools -> Program FPGA
右键 rgb_tft -> Run As

这里有一个非常重要的经验:

先 Run,不要先 Debug

因为老版本 Xilinx SDK 的 System Debugger 在这个实验环境下非常容易卡 99%。

7. 最终结果

在重新理顺:

platform
BSP
Application
背光控制

这些关系之后,RGB TFT 屏幕终于成功显示了图片。

这里插入最终成功显示的实拍照片
接下来Debug调试。
在这里插入图片描述
在这里插入图片描述
在这里就进入了单步调试。
在这里插入图片描述
最终结果:
在这里插入图片描述

这说明问题并不是:

板子坏了
屏幕坏了
代码完全错了
SDK 完全坏了

而是:

工程关系乱了,导致 platform / BSP / Application 没保持一致

8. 这次踩坑最大的经验总结

8.1 修改硬件后,不要让 SDK 里堆很多 platform

如果 DDR、PS、硬件设计改了,最稳的办法是:

开一个干净 workspace
重新导入唯一一套 platform

而不是一直叠加 _1、_2。

8.2 一个 platform 只对应一套 BSP 和一套 Application
这是本次最核心的经验。

8.3 旧代码可以复制,但旧 BSP 和旧 lscript.ld 不要直接搬
源码文件可以复用,但软件支持包和链接脚本必须跟着当前新的 platform 重新生成。

8.4 Debug 卡 99% 不一定是代码问题
很多时候是:

SDK 调试链路本身不稳定
platform 混乱
Run/Debug 配置混乱

所以不要一开始就被 99% 带跑。

8.5 对这种实验,先 Run,后 Debug
能先跑起来、能先看到屏幕变化,比单步调试更重要。

9. 给后来者的建议

如果你也在做 ZYNQ 的 RGB TFT 显示实验,并且遇到了:

Debug 卡 99%
BSP regenerate 报错
platform 越来越多
屏幕黑屏
下载内存地址异常

我的建议是:

不要在旧工程上死磕太久

最有效的方式通常是:

Vivado 导出正确 hardware
新建干净 SDK workspace
只保留一个 platform
新建 BSP
新建 Application
只复制自己的源码文件
先 Run

这样往往比在旧环境上继续修补更快。

10. 结语

这次问题折腾了很久,但也正因为踩了这些坑,我终于真正理解了:

Vivado 导出的 platform 是什么
BSP 的作用是什么
Application 应该如何依赖 BSP 和 platform
为什么修改 DDR 后,SDK 里的旧工程不能随便继续用

以前这些概念总觉得有点抽象,这次算是被迫踩坑踩明白了。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐