硬件平台:Zynq-7000
软件工具:Xilinx Vitis Classic 2024.1
原理
在使用 Xilinx Vitis 软件调试时,如果存在 UART
引脚被占用的情况,可以将 BSP Settigns 中的 stdin 和
stdout 修改为
ps_coresight_comp_0,将输入输出重定向到 ARM 的 CoreSight
调试/跟踪组件,此时日志与调试不再依赖 UART,而是通过 JTAG
调试接口直接上传到 Vitis XSCT 中。
1 2 3 4 5 6 7 8 9
| ┌─────────────────┐ JTAG ┌─────────┐ │ ARM Cortex-A9 │◄──────► │ XSCT │ │ ┌───────────┐ │ │ Console │ │ │ DCC Reg │ │ └─────────┘ │ └───────────┘ │ │ ▲ │ │ │ │ │ 0xF8800000 │ └─────────────────┘
|
修改配置前后 BSP 程序对比如下(正文中仅展示关键区别,详见附录)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| // xparameters.h - #define STDIN_BASEADDRESS 0xE0000000 - #define STDOUT_BASEADDRESS 0xE0000000 + #define STDIN_BASEADDRESS 0xF8800000 + #define STDOUT_BASEADDRESS 0xF8800000
// inbyte.c / outbyte.c - #include "xuartps_hw.h" + #include "xcoresightpsdcc.h"
- return XUartPs_RecvByte(STDIN_BASEADDRESS); + return XCoresightPs_DccRecvByte(STDIN_BASEADDRESS);
- XUartPs_SendByte(STDOUT_BASEADDRESS, c); + XCoresightPs_DccSendByte(STDOUT_BASEADDRESS, c);
|
点击 👇 查看上述函数实现源代码
XUartPs_SendByte,
XUartPs_RecvByte
XCoresightPs_DccSendByte,
XCoresightPs_DccRecvByte
追踪其源代码实现可以发现
XUartPs_SendByte:利用 PS
端的 UART IP,数据写入 TX_FIFO ,然后由硬件按照既定波特率将 FIFO
数据串行输出到 TX 引脚,发送速率小于波特率,FIFO
有空闲,不会陷入阻塞;
XCoresightPs_DccSendByte:基于 ARM 架构的 Debug
Communication Channel (DCC),数据写入一个 32
位寄存器,然后调试器实时捕获 DCC 数据并显示在 XSCT
控制台。如果没有调试器连接,DCC 寄存器上一 32 位数据不会被取出,CPU
无法写入下一字节。
⚠️ 注意:XCoresightPs_DccSendByte 函数会调用
XCoresightPs_DccGetStatus 函数轮询 DCC
状态位,如果未读取到状态,将返回默认状态值
0,导致发送函数将陷入无限等待(没有超时保护,这合理嘛?),程序阻塞,无法继续运行!
因此为了确保程序脱离调试器仍可以运行,固化前需要切换到
ps_uart_0 配置!
总结
两种调试方案对比如下表
|
UART 方案 |
Coresight DCC 方案 |
| 驱动头文件 |
xuartps_hw.h |
xcoresightpsdcc.h |
| 基地址 |
0xE0000000 |
0xF8800000 |
| 发送函数 |
XUartPs_SendByte() |
XCoresightPs_DccSendByte() |
| 接收函数 |
XUartPs_RecvByte() |
XCoresightPs_DccRecvByte() |
| 传输介质 |
物理 UART 引脚 |
JTAG 调试接口 |
| 是否阻塞 |
FIFO 缓冲 |
⚠️
无超时,严格阻塞 |
| 脱离调试器 |
可独立运行 |
⚠️ 强依赖调试器 |
参考资料
Xilinx
Processor IP Lib
附录
配置修改前后 BSP 程序对比
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| // <platform>/ps7_cortexa9_0/freertos10_xilinx_domain/bsp/ps7_cortexa9_0/include/xparameters.h - #define STDIN_BASEADDRESS 0xE0000000 - #define STDOUT_BASEADDRESS 0xE0000000 +#define STDIN_BASEADDRESS 0xF8800000 +#define STDOUT_BASEADDRESS 0xF8800000
// <platform>/ps7_cortexa9_0/freertos10_xilinx_domain/bsp/ps7_cortexa9_0/libsrc/freertos10_xilinx_v1_15/src/inbyte.c #include "xparameters.h" -#include "xuartps_hw.h" +#include "xcoresightpsdcc.h"
#ifdef __cplusplus extern "C" { #endif char inbyte(void); #ifdef __cplusplus } #endif
char inbyte(void) { - return XUartPs_RecvByte(STDIN_BASEADDRESS); + return XCoresightPs_DccRecvByte(STDIN_BASEADDRESS); }
// <platform>/ps7_cortexa9_0/freertos10_xilinx_domain/bsp/ps7_cortexa9_0/libsrc/freertos10_xilinx_v1_15/src/outbyte.c #include "xparameters.h" -#include "xuartps_hw.h" +#include "xcoresightpsdcc.h"
#ifdef __cplusplus extern "C" { #endif void outbyte(char c);
#ifdef __cplusplus } #endif
void outbyte(char c) { - XUartPs_SendByte(STDOUT_BASEADDRESS, c); + XCoresightPs_DccSendByte(STDOUT_BASEADDRESS, c); }
|