返回所有文章
调试 / TSENGCHEN BLOG

2026-07-22_RV1126B_DSMC_CS2启动异常与DMA失败_RK3576验证

02_Debug · 2026-07-22_RV1126B_DSMC_CS2启动异常与DMA失败_RK3576验证

02_Debug · 第 1 / 5 篇

保留原笔记正文与技术内容,仅脱敏敏感信息。配图按作者要求保留原样。

RV1126B DSMC CS2 启动异常与 DMA 失败:RK3576 对比验证

本文记录 RV1126B EVB4 V10 通过 DSMC LocalBus 连接 Zynq FPGA 后出现的启动卡死、CS0/CS2 配置问题与 CS2 DMA 超时,并以 RK3576 的实测结果区分 FPGA 能力与 RV1126B 适配问题。

适用范围

  • SoC:RV1126B
  • 内核:Linux 6.1.172
  • 外设:Zynq FPGA,使用 DSMC LocalBus
  • 实际片选:DSMC CS2

现象

不连接 DSMC/FPGA 时,系统可以正常启动。连接 FPGA 后,内核在 DSMC probe 阶段异常,早期日志为:

dsmc 21ca0000.dsmc: init cs0 LB device

随后出现 RCU stall,卡住的 CPU 位于:

rockchip_dsmc_lb_init+0x2d8

后续还出现过 synchronous external abort。这不是串口工具停止接收;内核已经因 DSMC 首次访问外部 LocalBus slave 而处于异常状态。

文档依据

Rockchip_Developer_Guide_DSMC_CN.pdf 适用于 RV1126B 和 kernel 6.1。文档说明 DSMC 驱动加载后会访问 LocalBus slave;若读事务没有获得有效 DQS 返回,可能发生 external abort。文档同时要求 DSMC master 初始化前,slave 必须已经上电并完成初始化。

对应的可检索文档:[Rockchip DSMC 开发文档](本地源码:/home/user/workspace/private-docs/DSMC/Rockchip_Developer_Guide_DSMC_CN.md:789)。

已排除的方向

  • MMC、显示、USB、GMAC 和 UART 日志工具不是本次启动异常的根因。
  • RCU stall 是 DSMC 访问卡住后的结果,不是最初故障点。
  • 5 秒固定延时只用于验证 FPGA 初始化时序;该实验未作为最终方案保留。

根因定位

FPGA 实际连接在 DSMC CS2,而早期板级 DTS 启用的是 lb-slave0,所以驱动打印 init cs0 LB device 并向错误片选发起 LocalBus 初始化事务。

CS2 方案不能只将 lb-slave0 改名为 lb-slave2。DSMC 驱动作者提供的补丁还处理了 CS2 的 DQS、时钟/中断引脚复用以及 DMA 通道使用。

当前应用的补丁

当前代码已与以下补丁内容对齐:

/home/user/workspace/RK3588/patch/0001-memory-rv1126b_dsmc-used-zynq-fpga-by-cs2.patch

补丁来源:Zhihuang He。

修改项当前配置
LocalBus slave启用 lb-slave2
region启用 CS2 的 region0 和 region3
DSMC 频率50 MHz
DQS DLLrockchip,dqs-dll = <0x40 0x40 0x20 0x20 0x20 0x20 0x20 0x20>
LocalBus 位宽16 bit
中断序号CS2 节点使用 rockchip,int-en = <0x0>
pinctrl-2dsmc_clk_pins,避免 CLKN 与 INT0 的复用冲突
DMALocalBus DMA 准备和硬件模式使用通道 0

涉及文件:

  • kernel/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts
  • kernel/arch/arm64/boot/dts/rockchip/rv1126b.dtsi
  • kernel/drivers/memory/rockchip/dsmc-controller.c
  • kernel/drivers/memory/rockchip/dsmc-host.c

FPGA 启动时序的 5 秒延迟诊断方法

该方法只用于判断 DSMC 开始 DLL training 时 FPGA 是否尚未完成配置或 LocalBus 初始化,不是正式修复方案。当前工作区未保留此前的临时补丁;后续需要复测时,按以下方法在 dsmc-host.c 中临时加入代码。

插入位置:rockchip_dsmc_probe() 内,dsmc_mem_remap() 成功之后、rockchip_dsmc_dll_training(priv) 之前。此时 DSMC 地址空间已建立,但驱动尚未向 FPGA 发起 DLL training 读写。

if (dsmc_mem_remap(dev, dsmc)) {
    ret = -ENODEV;
    dev_err(dev, "DSMC memory remap fail!\\n");
    goto err_release_dma;
}

/* Diagnostic only: allow FPGA configuration/LocalBus logic to become ready. */
dev_info(dev, "DSMC: wait 5000 ms before DLL training\\n");
msleep(5000);

if (rockchip_dsmc_dll_training(priv)) {
    ret = -ENODEV;
    dev_err(dev, "DSMC dll training fail!\\n");
    goto err_release_dma;
}

dsmc-host.c 已包含 linux/delay.h,可直接使用 msleep()。不要使用 mdelay(5000):该函数会持续占用 CPU 五秒,可能引入新的 RCU stall 表象。

复测步骤与判定

  1. 仅加入上述延迟,不同时修改 CS、DQS DLL、频率或 DMA 配置。
  2. 编译并刷写测试镜像,至少进行 5 次完整断电冷启动;记录 init cs2 LB device、DLL training 与是否进入系统。
  3. 移除延迟后,以相同条件重复冷启动,作为对照。
结果判定后续方向
加延迟稳定启动,移除后复现失败FPGA ready 时序是高概率因素设计 FPGA Ready GPIO 或延后 DSMC probe,不保留固定 5 秒延迟
加延迟仍失败不是单纯上电时序问题继续核对 CS、pinctrl、DQS、时钟和物理连线
加延迟后 DLL 通过但 DMA 仍超时启动时序与 DMA 问题独立按 DMA 请求、INT 与 CLKN 复用路径排查

完成诊断后必须删除这段临时代码,避免每次启动无条件增加五秒,并防止将时序问题掩盖为“已修复”。

编译后的检查点

使用当前代码编译并刷写后,启动日志必须首先确认:

dsmc 21ca0000.dsmc: init cs2 LB device

若仍打印 init cs0 LB device,说明启动镜像中的 DTB 或 kernel 未更新,不能继续分析 FPGA 通信。

若打印 init cs2 LB device 后仍发生 external abort,应保留从该行开始到异常发生的完整日志,并进一步检查 FPGA 是否实现与 Rockchip LocalBus slave 相同的协议及其上电初始化时序。

板端检查命令:

uname -a
dmesg | grep -Ei 'dsmc|dll|external abort|rcu'

CS2 DMA 测试入口

原厂 dsmc-test.c 使用固定的 rockchip,rk3576-dsmc compatible,在 RV1126B 上无法找到 DSMC 控制器。该源文件不是 UTF-8 编码,未直接修改,以避免重编码影响共享测试代码。

新增 dsmc-rv1126b-test.c 作为独立入口,使用 rockchip,rv1126b-dsmc 查找控制器,并只对 CS2 调用原厂 plc_simple_test()。该函数保留原来的 4 MiB 双向 DMA 测试流程。

涉及文件:

  • kernel/drivers/memory/rockchip/dsmc-rv1126b-test.c
  • kernel/drivers/memory/rockchip/Makefile

编译、刷写并启动后,先确认文件存在:

ls /sys/kernel/rk_dsmc_test_rv1126b/cpu_cs2_test \
   /sys/kernel/rk_dsmc_test_rv1126b/plc_cs2_test

执行测试:

cat /sys/kernel/rk_dsmc_test_rv1126b/plc_cs2_test

预期输出为:

PASS: PLC DMA test completed on CS2

该输出仅表示测试函数没有返回超时或 DMA 错误。最终结果还应检查 dmesg 中是否存在 offset ... error、wait copy ... timeout 或 dsmc-rv1126b-test: PLC DMA test failed。

DMA 测试后立即保留控制器状态和日志:

dmesg | grep -Ei 'dsmc|dma|copy|timeout|int_status|lbc|app_con'
grep -E 'dma-controller|dsmc' /proc/interrupts

2026-07-22 板端实测结果

本次使用 ADB 对运行中的板端进行只读检查,并使用板端已有的 devmem 工具完成最小 CPU 写读验证。未修改板端设备树、驱动或 FPGA。

DLL training 状态

当前运行内核为 Linux 6.1.172 #18。CS2 的两个 byte lane 均完成 DLL training,且 DSMC 平台驱动已绑定:

dsmc 21ca0000.dsmc: init cs2 LB device
dsmc 21ca0000.dsmc: cs2 byte0: DLL window [0x41-0x44] length=0x4, current=0x42
dsmc 21ca0000.dsmc: cs2 byte1: DLL window [0x46-0x4a] length=0x5, current=0x48

这说明 CS2、DQS、16-bit 数据线和基础 LocalBus CPU 读写时序已经满足训练要求。

复核 DLL training 的命令:

dmesg | grep -E 'init cs2 LB device|cs2 byte[01]|DLL|dll'

CPU 通信验证

优先执行 CPU 轮询测试入口:

cat /sys/kernel/rk_dsmc_test_rv1126b/cpu_cs2_test

预期为 PASS: CS2 read-only CPU probe passed。该测试访问 CS2 的 region0,不会触发 DMA。

当前 DTS 的 LocalBus 空间配置有两个启用 region,每个 region 大小为 0x02000000。按驱动的 CS2 region 分配规则,region0 的物理地址为 0x18000000。

测试操作:

devmem 0x18000000 32 0x5AA5F00F
devmem 0x18000000 32

实测结果:

before: 0x00FF0000
after : 0x5AA5F00F

结论:RV1126B 与 FPGA 之间的 CS2 region0 CPU 单字写读通信正常。测试后未出现 DSMC external abort、RCU stall 或新的 DSMC 总线异常。

RV1126B DMA 通信失败点

原厂 PLC 测试的第一阶段为 DDR 写入 CS2 region0。测试在等待 DMA 回调时超时:

grep -E 'dma-controller|dsmc' /proc/interrupts
cat /sys/kernel/rk_dsmc_test_rv1126b/plc_cs2_test
grep -E 'dma-controller|dsmc' /proc/interrupts
dmesg | grep -Ei 'dsmc|dma|copy|timeout|int_status|lbc|app_con'
start copy_to cs2, src_phy = 0x7cd00000, size = 0x400000
DSMC: wait copy to complete timeout
dsmc-rv1126b-test: PLC DMA test failed: -1

测试前后,系统 DMA 控制器 IRQ 60 的计数均为 0,说明 DMA 请求没有完成。

DSMC 硬件 DMA 的流程为:host 配置 DMA 后向 CS2 region3 的 LBC_CON15 写入通知;FPGA 需要处理该通知,并通过写 APP_CON15 和拉起 DSMC INT 信号返回 DMA 请求。RV1126B 测试中未收到 DMA 完成回调,因此该路径在 RV1126B 上未成立。

当前硬件上 DSMC_CLKN 与 DSMC_INT0 复用。DSMC 驱动作者提供的 CS2 适配补丁选择 dsmc_clk_pins 保留差分时钟,因此不能同时使用 INT0 作为 DMA 返回信号。

运行时确认当前 INT 选择与 DSMC pinctrl:

od -An -tx4 /sys/firmware/devicetree/base/dsmc-slave/lb-slave/lb-slave2/rockchip,int-en
ls -l /sys/firmware/devicetree/base/dsmc-slave/lb-slave/lb-slave2/pinctrl-2

当前可启动配置应读到 00000000,即逻辑 INT0。这只能确认 DT 选择,不能证明 FPGA 已实际拉起 INT0。

RK3576 DMA 对比验证

RK3576 通过 ADB 执行板端原厂测试入口 /sys/kernel/rk_dsmc_test/plc_test。测试入口存在,且 DSMC CS0 的两个 byte lane 均完成 DLL training:

dsmc 2a280000.dsmc: init cs0 LB device
dsmc 2a280000.dsmc: cs0 byte0: DLL window [0x1e-0xff] length=0xe2, current=0x8e
dsmc 2a280000.dsmc: cs0 byte1: DLL window [0x1f-0xff] length=0xe1, current=0x8f

执行命令:

grep '2ab90000.dma-controller' /proc/interrupts
cat /sys/kernel/rk_dsmc_test/plc_test
grep '2ab90000.dma-controller' /proc/interrupts

内核日志显示双向 DMA 均完成:

phase 1: dma memcopy from host DDR to slave memory
phase2 : dma memcopy from slave memory to host DDR
plc_simple_test test done

同时,2ab90000.dma-controller 的 IRQ 64 计数从 0 增至 2,与两阶段 DMA 传输一致,且日志未出现超时或校验失败。

该结果证明:在 RK3576 的连接与配置下,FPGA 能响应 DSMC DMA 握手并产生有效 DMA 请求。因此,RV1126B 的超时不能再归因于“FPGA 不支持 DSMC DMA”;应集中排查 RV1126B 的 CS2 DMA 请求映射、INT 与 CLKN 复用,以及驱动作者提供的 CS2 适配补丁的实际生效状态。

DSMC DMA 引脚与调用链分析

DSMC DMA 不增加专用数据引脚,而是复用 LocalBus。数据搬运由系统 DMAC 完成,DMAC 是否开始工作取决于 FPGA 通过 DSMC INTx 返回 DMA 请求。

类别信号作用
基础 LocalBusCSN0~3选择 FPGA;必须与 DTS 中启用的 LocalBus slave 一致
基础 LocalBusD0~D15DDR 与 FPGA 间 DMA 数据双向传输
基础 LocalBusDQS0/1FPGA 返回读数据时的采样选通
基础 LocalBusCLKP/CLKNSoC 输出 LocalBus 差分时钟
可选流控RDYN外设 ready/等待信号,是否使用取决于协议与时序配置
DMA 握手INT0~3 中的一根FPGA 向 DSMC 返回 slave-to-host DMA 请求

LBC_CON15 和 APP_CON15 是映射到 FPGA 的 LocalBus 寄存器,不是独立引脚。DMA 测试通常使用 region0 传输数据、使用 region3 读写上述握手寄存器。

Host DDR 写 FPGA 的调用顺序

plc_test
  -> plc_simple_test(dsmc_dev, cs)
  -> ops->copy_to(dsmc_dev, cs, region0, src_phys, offset, size)
  -> 配置 DMAC 描述符:DDR 为源,DSMC CSx region0 为目的
  -> Host 写 CSx region3 的 LBC_CON15 通知 FPGA
  -> FPGA 写 APP_CON15 = 1,并拉起已选 DSMC_INTx
  -> DSMC 产生 DMA request
  -> DMAC 经 D0~D15 搬运 DDR 到 FPGA
  -> DMAC 完成中断,copy_to_state() 变为空闲

ops->copy_from() 的方向相反:DMAC 从 DSMC CSx region0 读取数据并写入 Host DDR。若 FPGA 未写 APP_CON15 或 INTx 未到达 DSMC,DMA 描述符会一直等待,最终出现 wait copy ... timeout,且系统 DMAC IRQ 不增加。

RK3576 与 RV1126B 的关键硬件差异

RK3576 TEST1 原理图第 38 页的 J9200 将 DSMC_CSN0、DSMC_CLKP、DSMC_CLKN 和 DSMC_INT0 引出到独立信号:CSN0 为 GPIO3_D3,CLKP/CLKN 为 GPIO3_D5/GPIO3_D6,INT0 为 GPIO4_A0。TEST1 DTS 启用 CS0 并配置 rockchip,int-en = <0>,因此可以同时保持差分时钟并接收 FPGA 的 INT0;板端 DMA IRQ 增加 2 已验证该链路有效。

RV1126B 的 FPGA 接在 CS2,且原理图中 DSMC_CLKN 与 DSMC_INT0 复用 GPIO5_B6。当前 CS2 方案为使用差分时钟选择 dsmc_clk_pins,使 INT0 不能同时作为 FPGA 到 SoC 的输入。该差异可解释 RV1126B 的 DMA 请求未到达系统 DMAC;50 MHz 与 RK3576 的 25 MHz 是信号裕量差异,但不能解释 DMA IRQ 为 0,因此不是当前首要原因。

测试程序的 CS 选择方式

dsmc-test.c 中的 plc_simple_test() 接收调用者传入的 cs 参数,并不在该函数内固定 CS0。plc_test_show() 遍历全部 CS 配置,只跳过 DSMC_UNKNOWN_DEVICE,对每个 DTS 已启用的 LocalBus slave 调用 plc_simple_test(dsmc_dev, i)。

因此,RK3576 测试日志显示 cs = 0 的原因是 TEST1 DTS 只启用 dsmc_lb_slave0,不是测试函数硬编码 CS0。测试程序也不会通过硬件自动识别 FPGA 接线;若 DTS 错误启用了 CS0,程序仍会测试 CS0。RV1126B 使用 CS2 时,必须由 DTS 正确启用 lb-slave2,或由专用测试入口显式传入 CS2。

当前结论

项目结论
CS2 DTS、pinctrl 和驱动绑定正常
DLL training正常通过
CPU 读写 CS2 region0正常
FPGA LocalBus 基础通信正常
RV1126B 的 CS2 DSMC DMA超时,DMA 请求/完成路径未成立
RK3576 的 DSMC DMA双向 DMA 成功,DMA IRQ 增加 2
FPGA DSMC DMA 能力已由 RK3576 实测确认可用

在 RV1126B DMA 问题修复前,可采用 CPU 方式访问 /dev/dsmc/cs2/region0 或对应寄存器 region;不要将该平台的 DMA 超时误判为 CS2 总线通信失败或 FPGA 不支持 DMA。

2026-07-22 最新状态

DLL training

DLL training 用于确认 CS2 的 DQS、数据线和时钟读时序。当前日志显示两个 byte lane 均已通过训练:

dsmc 21ca0000.dsmc: cs2 byte0: DLL window [0x36-0x39] length=0x4
dsmc 21ca0000.dsmc: cs2 byte1: DLL window [0x2c-0x30] length=0x5

启动前增加 5 秒延迟仅用于判断 FPGA 是否尚未 ready;延迟后 training 能通过,说明基础 CS2 通信正常。该延迟不能解决 DMA。

INT2 试验与回退

INT2 试验的原理是:保留 DSMC_CLKN,再使用 GPIO5_D3 接收 FPGA 的 INT2,以避开 GPIO5_B6 上 CLKN 与 INT0 的复用冲突。

该试验未能稳定启动,已完全回退。当前保持可启动的 CS2 + INT0 配置:

&dsmc_lb_slave2 {
    rockchip,int-en = <0x0>;
};

已确认结果

  • CPU 读 CS2 正常:0x00ff0000。
  • DMA 已配置但未完成:DMA_EN=1、INT_STATUS=0。
  • DMA 卡在 Host 通知 FPGA 后,等待 FPGA 经 APP_CON15 和 INT 返回 DMA 请求的阶段。

未解决问题

  • FPGA 当前实际输出的是哪一路 INTx。
  • FPGA 是否在收到 LBC_CON15 后写入 APP_CON15。
  • RV1126B 的 INT0 与 CLKN 复用下,DMA 中断如何实现。

2026-07-22:CS2 DLL training 失败与 FPGA RTL 复核

本轮失败日志表明,5 秒延迟并不能保证 DLL training 通过。CS2 byte0 曾扫描到很窄的候选窗口,但最终读回校验失败:

dsmc 21ca0000.dsmc: cs2 byte0: DLL window [0x32-0x32] length=0x1, current=0x32
dsmc 21ca0000.dsmc: DSMC: cs2 byte0 current DLL 0x32 verification failed
dsmc 21ca0000.dsmc: DSMC: cs2 byte0 DLL training attempt 1/3 failed

另一次日志的候选窗口为 [0x38-0x3b],长度只有 0x4。窗口会随启动变化且最终校验失败,说明这不是可用于固定 DLL 值的稳定训练结果。

FPGA RTL 对失败原因的解释

复核的工程为 dsmc_slave_open_source_env_v1。它是 DSMC slave RTL 验证环境,不包含 Vivado 工程、XDC 约束、FSBL 或 BOOT.BIN 生成文件;因此它不能单独证明实际板卡的物理 CS2 连线或当前 BOOT.BIN 一定由该 RTL 构建。但其数据通路与当前的 FIFO 型 LocalBus 配置一致,可用于解释训练行为。

  • FIFO 类型事务写入 RX FIFO:rx_fifo_wr = trans_hdr_type == TRANS_TYPE_FIFO_MEM && trans_wvalid。
  • FIFO 类型读事务从独立的 TX FIFO 取数据:tx_fifo_rd = trans_rvalid && trans_hdr_type == TRANS_TYPE_FIFO_MEM。
  • TX FIFO 的写入来源是 FPGA 应用 AXI 返回数据,不是 RX FIFO 的自动回环。
  • RDYN 受 FIFO 满/空、写事务结束等状态控制,并非持续有效的固定 ready 信号。

因此,内核通用 DLL training 的“连续写测试模式,再连续读回并比较”假设不适用于 FIFO region0:写入会累积在 RX FIFO,读回依赖应用侧预先填充 TX FIFO。训练偶尔得到短窗口只是当时 FIFO、RDYN 与 FPGA 初始化状态恰好允许若干读写完成,不能证明 DQS DLL 已训练成功;最终校验或后续事务可能阻塞。

对应 RTL 位置:

  • dsmc_slave_top.v:953 行(RX FIFO 写入)、1012 行(TX FIFO 读取)。
  • dsmc_slave_bus_ctrl.v:345 行(应用 AXI 返回数据写入 TX FIFO)。
  • dsmc_slave_csm.v:637 行(RDYN 与 FIFO 状态关联)。

INT 结论

参考顶层 env/dsmc_slave_io_wrapper.v 中,rpc_int1、rpc_int2、rpc_int3 被固定为低,仅 rpc_int0 连接 slave-to-host 中断输出。故在该 RTL 版本下,切换 RV1126B 到 INT2 不会得到 FPGA 的 DMA 请求信号。实际 BOOT.BIN 是否采用同一顶层仍需由 FPGA 工程约束或 Zynq 端日志确认。

当前处理原则

CS2 region0 为 FIFO 时,不再以通用 RAM 写读算法作为 DLL training 成功判据。启动稳定性应采用板级已知的固定 DLL 参数并跳过 CS2 FIFO 的通用模式训练;CPU/DMA 通信测试则必须由 FPGA 应用侧按协议消费 RX FIFO,并向 TX FIFO 或 APP_CON15 + INT0 提供响应。

02_Debug · 文档目录
下一篇2026-07-23_RK3506G_EVB1_DSMC主从通信调试