一、HAL 层日志开关
HAL 层日志就是 librga.so 内部的打印。默认关闭,需要手动打开。
1.1 Linux 平台
FAQ 第 3.1.1 节原文:
Linux 平台支持通过设置环境变量的方式(librga 1.9.0 版本以上),开启/关闭 HAL 层日志打印:
- 开启日志打印:
export ROCKCHIP_RGA_LOG=1- 设置日志等级:日志等级分为全打印(0)、DEFAULT(1)、DEBUG(3)、INFO(4)、WRANING(5)、ERROR(6)
export ROCKCHIP_RGA_LOG_LEVEL=6
1.2 Android 平台
FAQ 第 3.1.1 节原文:
- 开启日志打印:
setprop vendor.rga.log 1,然后logcat -s librga- 设置日志等级:
setprop vendor.rga.log_level 6
1.3 使用建议
日常跑 demo 时关掉,避免 debug 日志淹没性能数据:
unset ROCKCHIP_RGA_LOG
unset ROCKCHIP_RGA_LOG_LEVEL
./3-best 2>&1 | tee log.txt
排查问题时打开,看 librga 传给驱动的参数:
export ROCKCHIP_RGA_LOG=1
export ROCKCHIP_RGA_LOG_LEVEL=6
./demo 2>&1 | tee debug.log
二、HAL 层日志怎么读
FAQ 第 3.1.2 节给出了一段完整的 librga 运行日志,逐行解读如下。
2.1 传入 librga 的参数
D librga : <<<<-------- print rgaLog -------->>
D librga : src->hnd = 0x0 , dst->hnd = 0x0 , src1->hnd = 0x0
D librga : src: Fd = 00 , phyAddr = 0x0 , virAddr = 0xb400007431ed6040
D librga : dst: Fd = 00 , phyAddr = 0x0 , virAddr = 0xb400007431b4f040
逐字段含义:
| 字段 | 含义 |
|---|---|
src->hnd / dst->hnd / src1->hnd | 三个通道传入的内存句柄值 |
src: Fd = 00 | src 通道传入的 DMA_FD |
src: phyAddr = 0x0 | src 通道传入的物理地址 |
src: virAddr = 0xb400007431ed6040 | src 通道传入的虚拟地址 |
注意:Fd = 00 是 librga 打印格式的写法,不是真的 fd = 0。FAQ 里示例日志也这样打印。
2.2 HAL 最终选择的内存类型
D librga : src: Fd = -01 , buf = 0xb400007431ed6040, mmuFlag = 1, mmuType = 0
D librga : dst: Fd = -01 , buf = 0xb400007431b4f040, mmuFlag = 1, mmuType = 0
| 字段 | 含义 |
|---|---|
Fd = -01 | 最终没有选择 DMA_FD(因为传入了虚拟地址) |
buf | 最终传给驱动的地址 |
mmuFlag = 1 | 使能 MMU |
mmuType = 0 | MMU 类型 |
这一行告诉你:HAL 层最终把哪个地址传给了驱动。
2.3 模式信息
E librga : blend = 0 , perpixelAlpha = 1
D librga : scaleMode = 0 , stretch = 0;
E librga : rgaVersion = 3.200000 , ditherEn = 0
D librga : srcMmuFlag = 1 , dstMmuFlag = 1 , rotateMode = 0
| 字段 | 含义 |
|---|---|
blend = 0 | 混合模式(0 表示不混合) |
perpixelAlpha = 1 | 图像格式本身有 Alpha 值 |
scaleMode = 0 | 缩放模式(RGA1 特有) |
rgaVersion = 3.200000 | 硬件版本号 |
ditherEn = 0 | 16 阶灰度图(Y4)dither 使能 |
srcMmuFlag / dstMmuFlag | MMU 使能标志 |
rotateMode = 0 | 旋转模式 |
2.4 配置入驱动的参数(重点)
E librga : <<<<-------- rgaReg -------->>
E librga : render_mode=0 rotate_mode=0
E librga : src:[0,b400007431ed6040,b400007431fb7040],x-y[0,0],w-h[1280,720],vw-vh[1280,720],f=0
E librga : dst:[0,b400007431b4f040,b400007431c30040],x-y[0,0],w-h[1280,720],vw-vh[1280,720],f=0
E librga : pat:[0,0,0],x-y[0,0],w-h[0,0],vw-vh[0,0],f=0
E librga : ROP:[0,0,0],LUT[0]
E librga : color:[0,0,0,0,0]
E librga : MMU:[1,0,80000521]
E librga : mode[0,0,0,0]
src 和 dst 行的字段含义(FAQ 里的解读):
| 位置 | 含义 |
|---|---|
[0, b400007431ed6040, b400007431fb7040] | 三个 plane 地址(Y / UV / V) |
x-y[0,0] | 偏移量(x_offset, y_offset) |
w-h[1280,720] | 实宽实高(active width/height) |
vw-vh[1280,720] | 虚宽虚高(virtual width/height = stride) |
f=0 | 格式 |
这三行就是判断"虚宽实宽有没有配错"的关键。 如果 x + w > vw,就会看到 err ws[...] 报错。
2.5 其他参数
E librga : pat:[0,0,0],x-y[0,0],w-h[0,0],vw-vh[0,0],f=0 ← pat/src1 通道,未使用
E librga : ROP:[0,0,0],LUT[0] ← ROP 模式、LUT 表
E librga : color:[0,0,0,0,0] ← colorkey、填充色
E librga : MMU:[1,0,80000521] ← MMU 配置
E librga : mode[0,0,0,0] ← palette、csc、colorkey
这些通常不用关心,除非你调 ROP / colorkey / MMU。
三、驱动调试节点
FAQ 第 3.2 节。驱动调试节点比 HAL 层日志更底层,能看到驱动真正下发给硬件的东西。
3.1 节点路径
不同驱动的调试节点不同:
| 驱动名称 | 调试节点路径 |
|---|---|
| RGA Device Driver | rga_debug |
| RGA2 Device Driver(无版本号) | rga2_debug |
| RGA2 Device Driver(v2.1.0) | rkrga |
| RGA multicore Device Driver | rkrga |
RK3588 用的是 multicore 驱动,所以节点是 /sys/kernel/debug/rkrga/。
FAQ 原文:
不同的 SDK kernel 的配置不同,通常 RGA 的调试节点存在在以下两个目录其中一个或者均存在:
- 使用默认使能
CONFIG_ROCKCHIP_RGA_DEBUG_FS编译选项的 kernel:/sys/kernel/debug- 使能
ROCKCHIP_RGA_PROC_FS编译选项的 kernel:/proc
3.2 六个子命令
FAQ 第 3.2.3.2.1 节给出六个命令,切换方式相同,每次 echo 切换状态:
| 命令 | 作用 |
|---|---|
echo reg > debug | 打印每次 RGA 工作的寄存器配置值 |
echo msg > debug | 打印上层调用驱动传递的参数 |
echo time > debug | 打印每一次调用 RGA 工作的耗时 |
echo int > debug | RGA 进入中断后打印中断寄存器和状态寄存器当前值 |
echo check > debug | 开启内部测试 case,每次工作时检查参数、内存与对齐。若内存存在越界,将会导致内核 crash。可以通过 crash 前的打印确认是 src 还是 dst 的问题 |
echo stop > debug | 开启后 RGA 不工作直接返回,用于特殊情况的调试 |
echo slt > debug | 让驱动执行内部 SLT case 测试硬件是否正常。若输出 rga slt success!! 表示功能正常 |
注意:这些日志的打印级别是 KERNEL_DEBUG,必须 dmesg 才能看到。
3.3 一次完整的驱动日志抓取
cd /sys/kernel/debug/rkrga/
# 查看当前开关状态
cat debug
# 打开 msg 和 time
echo msg > debug
echo time > debug
# 确认已打开
cat debug
# 清空内核日志缓冲
dmesg -c
# …… 运行你的程序 ……
./demo
# 取出这一轮日志
dmesg -c
# 关闭
echo msg > debug
echo time > debug
3.4 time 模式日志(FAQ 第 3.2.3.2.2 节)
librga 1.3.0 以下版本:
rga3_reg: set cmd use time = 196 // 开始处理请求到配置寄存器的耗时
rga_job: hw use time = 554 // 硬件启动到硬件中断返回耗时
rga_job: (pid:3197) job done use time = 751 // 开始处理请求到请求完成的耗时
rga_job: (pid:3197) job clean use time = 933 // 开始处理请求到请求资源处理完毕的耗时
librga 1.3.0 及以上版本:
rga_mm: request[3300], get buffer_handle info cost 188 us // 获取 buffer_handle 信息
rga3_reg: request[3300], generate register cost time 2 us // 生成寄存器配置
rga3_reg: request[3300], set register cost time 301 us // 配置寄存器
rga_job: request[3300], hardware[RGA3_core0] cost time 539 us // ★ 硬件核心完成任务
rga_mm: request[3300], put buffer_handle info cost 153 us // 释放 buffer_handle
rga_job: request[3300], job done total cost time 1023 us // ★ 从提交到完成返回用户态
rga_job: request[3300], job cleanup total cost time 1030 us // 从提交到资源释放完毕
怎么用这组数据(FAQ 建议):
| 现象 | 判断 |
|---|---|
hardware cost 大 | 真的在跑,看是否符合理论值(第五篇公式) |
get/put buffer_handle 大(几百 us) | 你踩了 buffer pool 的坑,或用了虚拟地址/cacheable buffer |
job done total ≫ hardware cost | 大量时间花在调度与映射上,检查 buffer 是否复用、是否有多核争抢 |
四、四个状态查询节点
FAQ 第 3.2.3.3 ~ 3.2.3.7 节。
4.1 版本信息 driver_version
cat /sys/kernel/debug/rkrga/driver_version
# → RGA multicore Device Driver: v1.2.23
4.2 负载查询 load
cat /sys/kernel/debug/rkrga/load
FAQ 给出的示例输出:
num of scheduler = 3 // 当前搭载硬件核心数
================= load =================
scheduler[0]: rga3_core0
load = 0% // 对应核心负载占比
-----------------------------------
scheduler[1]: rga3_core1
load = 0%
-----------------------------------
scheduler[2]: rga2
load = 0%
-----------------------------------
用途:看三颗核的实时负载。如果某颗核长期 100%,说明负载不均衡,可能需要 imconfig 指定核心。
4.3 内存管理器 mm_session
cat /sys/kernel/debug/rkrga/mm_session
FAQ 给出的示例输出:
rga_mm dump:
buffer count = 3 // 内存管理器内保存的 buffer 数量
===============================================================
handle = 34 refcount = 1 mm_flag = 0x2 tgid = 3210 // 句柄/引用计数/内存标识/进程号
virtual address:
va = 0xb400007286e1c000, pages = 0x...ae081f65, size = 3686400
iova = 0xffc70000, offset = 0x0, sgt = 0x...cc976f9e, size = 3686400, map_core = 0x1
---------------------------------------------------------------
handle = 35 refcount = 1 mm_flag = 0x2 tgid = 3210
virtual address:
va = 0xb400007286a95000, pages = 0x...2f083efc, size = 3686400
iova = 0xff8e0000, offset = 0x0, sgt = 0x...62bb1297, size = 3686400, map_core = 0x1
---------------------------------------------------------------
handle = 36 refcount = 1 mm_flag = 0x2 tgid = 3210
virtual address:
va = 0xb40000728670e000, pages = 0x...785fef63, size = 3686400
iova = 0xff550000, offset = 0x0, sgt = 0x...cdd7688d, size = 3686400, map_core = 0x1
用途:
- buffer 是否被正确释放:
buffer count是否持续增长 - 映射到了哪个核心:
map_core - 句柄、引用计数、进程号:排查"这个 buffer 被谁占着"
4.4 任务请求 request_manager
cat /sys/kernel/debug/rkrga/request_manager
FAQ 给出的示例输出:
rga internal request dump:
request count = 1 // 任务管理器内任务请求数量
===============================================================
------------------ request: 200073 ------------------
set cmd num: 1, finish job: 0, failed job: 0, flags = 0x0, ref = 2
cmd dump:
rotate_mode = 0
src: y = 25 uv = 0 v = e1000 aw = 1280 ah = 720 vw = 1280 vh = 720
src: xoff = 0, yoff = 0, format = 0x0, rd_mode = 1
dst: y=26 uv=0 v=e1000 aw=1280 ah=720 vw=1280 vh=720
mmu: mmu_flag=0 en=0
alpha: rop_mode = 0
yuv2rgb mode is 0
set core = 0, priority = 0, in_fence_fd = -1
用途:
- 卡住时的排查利器:
request count持续增长或finish job停滞,说明有任务没完成 rd_mode含义:1 = raster,2 = FBC,3 = tile 16×16
4.5 硬件信息 hardware
cat /sys/kernel/debug/rkrga/hardware
FAQ 给出的示例输出:
rga3_core0, core 1: version: 3.0.76831
input range: 68x2 ~ 8176x8176
output range: 68x2 ~ 8128x8128
scale limit: 1/8 ~ 8
byte_stride_align: 16
max_byte_stride: 32768
csc: RGB2YUV 0xf YUV2RGB 0xf
feature: 0x4
mmu: RK_IOMMU
rga3_core1, core 2: version: 3.0.76831
...(同上)
rga2, core 4: version: 3.2.63318
input range: 2x2 ~ 8192x8192
output range: 2x2 ~ 4096x4096
scale limit: 1/16 ~ 16
byte_stride_align: 4
max_byte_stride: 32768
csc: RGB2YUV 0x7 YUV2RGB 0x7
feature: 0x5f
mmu: RGA_MMU
用途:确认当前搭载的核心数、每颗核的能力。
五、dump 运行数据
FAQ 第 3.2.3.8 节。
5.1 设置 dump 路径
echo /data/rga_image > /sys/kernel/debug/rkrga/dump_path
dmesg -c
# → rga_debugger: dump path change to: /data/rga_image
5.2 设置 dump 帧数
echo 1 > /sys/kernel/debug/rkrga/dump_image
dmesg -c
# → rga_debugger: dump image 1
5.3 运行 RGA,看 dump 结果
# …… 运行 RGA ……
./demo
dmesg -c
# → rga_debugger: dump image to:
# /data/rga_image/1_core1_src_plane0_virt_addr_w1280_h720_RGBA8888.bin
# /data/rga_debugger: dump image to:
# /data/rga_image/1_core1_dst_plane0_virt_addr_w1280_h720_RGBA8888.bin
ls /data/rga_image/
# 1_core1_dst_plane0_virt_addr_w1280_h720_RGBA8888.bin
# 1_core1_src_plane0_virt_addr_w1280_h720_RGBA8888.bin
"没有该节点说明当前 kernel 不支持内核写入写出数据。"
5.4 用途:定位"图像是花的"(FAQ Q2.20)
官方原文:
通常 RGA 的异常不会出现图像花掉的现象,一般遇到这种问题需要先定位问题是否是 RGA 出现的问题,在一些系统流程中需要先确认输入 RGA 的源数据是否已经是异常的,可以通过在调用 RGA 前将内存里的数据调用
fwrite()写文件出来,查看源数据是否正常。
用 dump_path + dump_image 就能 dump 出 RGA 真正读到的 src 和写出的 dst,对比就知道是输入问题还是 RGA 问题。
六、实战:用 debugfs 排查Color Fill 失败
可以用 debugfs 定位问题:
6.1 打开驱动日志
cd /sys/kernel/debug/rkrga/
echo msg > debug
echo time > debug
dmesg -c
6.2 运行程序
./demo
6.3 看驱动日志
dmesg -c
如果看到:
rga_policy: start policy on core = 4
rga_policy: RGA2 only support under 4G memory!
rga_policy: optional_cores = 0
rga_policy: invalid function policy
rga_policy: assign core: -1
rga_job: job assign failed
就确认了:Color Fill 落到 RGA2 上,但 buffer 落在 4G 以上,RGA2 访问不了。
这正是 FAQ Q4.6 给的日志。
6.4 对照 cat hardware
cat hardware | grep -A 2 "rga2"
# rga2, core 4:
# ...
# mmu: RGA_MMU ← 32bit IOMMU,只支持 4G 内
看到 RGA_MMU,就知道 RGA2 只支持 4G 内。 对照 rga3_core0/1 的 RK_IOMMU(40bit),就明白为什么 Color Fill 必须用 dma32。
七、本篇小结
第一,HAL 层日志用环境变量开关:
export ROCKCHIP_RGA_LOG=1export ROCKCHIP_RGA_LOG_LEVEL=6
第二,HAL 层日志看 src / dst 的 x-y、w-h、vw-vh:这是判断"虚宽实宽有没有配错"的关键。
第三,驱动调试节点在 /sys/kernel/debug/rkrga/,六个子命令:
msg:看上层传的参数time:看硬件耗时reg:看寄存器配置check:检查参数/内存/对齐(越界会 crash)stop:让 RGA 不工作slt:硬件自检
第四,四个状态查询节点:
driver_version:驱动版本load:三颗核的负载mm_session:内存管理器状态request_manager:任务请求状态hardware:硬件拓扑
第五,dump_path + dump_image 能把 RGA 真正读到的 src 和写出的 dst dump 到文件,用于定位"图像是花的"。
第六,time 模式日志分四段:
get/put buffer_handle:映射耗时generate/set register:寄存器配置耗时hardware[RGAx_corex]:硬件真正执行耗时job done total:从提交到返回用户态的全程耗时
对比 job done total 和 hardware cost,就知道时间花在哪。
第七,日志打印级别是 KERNEL_DEBUG,必须 dmesg 才能看到,cat /var/log/syslog 看不到。