ZYNQ双核调试问题:CPU1程序下载失败及APB总线错误分析
问题描述
在ZYNQ平台上开发双核应用程序时遇到了一个棘手的问题。对代码进行修改后,Run模式运行出现异常:第一个核心(CPU0)可以正常下载程序并启动,但第二个核心(CPU1)无法完成程序下载。
错误信息
具体的错误提示如下:
Memory write error at 0x200A0000. AP transaction timeout
Cannot reset APU. APB AP transaction error, DAP status 0xF0000021
调试过程
通过XSDB Console获取了详细的调试日志。从日志中可以观察到以下关键信息:
CPU0的程序下载过程正常完成:
Info: ARM Cortex-A9 MPCore #0 (target 2) Stopped at 0x0 (Vector Catch)
Downloading Program -- /home/fang/workspace/zynq7015/25_ov5640_lcd/vitisnew/hello_world/build/hello_world.elf
section, .text: 0x00100000 - 0x001194eb
...
Setting PC to Program Start Address 0x00100000
Successfully downloaded /home/fang/workspace/zynq7015/25_ov5640_lcd/vitisnew/hello_world/build/hello_world.elf
Info: ARM Cortex-A9 MPCore #0 (target 2) Running
CPU1的程序下载时出现问题:
Info: ARM Cortex-A9 MPCore #1 (target 3) Stopped at 0x0 (Vector Catch)
Downloading Program -- /home/fang/workspace/zynq7015/25_ov5640_lcd/vitisnew/cpu1_apriltag/build/cpu1_apriltag.elf
section, .text: 0x20080000 - 0x200a4d03
...
aborting, 1 pending requests...
Failed to download /home/fang/workspace/zynq7015/25_ov5640_lcd/vitisnew/cpu1_apriltag/build/cpu1_apriltag.elf
Info: ARM Cortex-A9 MPCore #1 (target 3) Running (APB AP transaction error, DAP status 0xF0000021)
问题分析
仔细观察日志的时间顺序,发现了一个重要的现象:CPU0的程序下载完成后会立即启动运行,然后才会开始下载CPU1的程序。这提示问题可能出在CPU0的启动代码中。
经过逐步排查,找到了问题的根本原因:当CPU0已经启动而CPU1尚未启动时,如果在CPU0中执行内存写入操作并调用数据缓存刷新函数,会导致CPU1无法正常启动。
问题代码
导致问题的典型代码如下:
// 问题代码示例
#define DDR_BASE_ADDR XPAR_PS7_DDR_0_BASEADDRESS
#define OFFSET_ADDR 0x1000000
volatile u8 *shared_buffer = (volatile u8 *)(DDR_BASE_ADDR + OFFSET_ADDR);
// CPU0中执行的代码
shared_buffer[2400] = 0xAA; // 向共享内存区域写入数据
Xil_DCacheFlush(); // 刷新数据缓存
原因解释
这个问题涉及到ZYNQ的双核缓存一致性机制。当CPU0执行Xil_DCacheFlush()时,会尝试与CPU1进行缓存同步操作。但如果CPU1尚未启动或处于异常状态,APB总线事务会超时,从而导致整个调试器连接失败。
具体来说:
- Xil_DCacheFlush()函数会清理数据缓存并确保数据写回到DDR内存
- 在双核系统中,这个操作可能需要与其他核心进行同步
- 当CPU1未就绪时,调试器无法完成APB事务,导致下载失败
解决方案
针对这个问题,有几种可行的解决方案:
方案一:延迟缓存刷新
在CPU1启动完成后再执行缓存刷新操作。
方案二:使用信号量同步
在CPU0中等待CPU1准备就绪后再进行内存操作和缓存刷新。
方案三:修改启动顺序
调整CPU1的启动时序,确保在CPU0执行缓存操作前已经完成初始化。
总结
在ZYNQ双核开发中,需要特别注意多核之间的启动时序和缓存同步问题。建议在设计双核通信机制时,建立完善的同步机制,避免因为时序问题导致的调试失败。