Rockchip 音频调试完全手册:从 "没声音" 到 "定位根因" 的系统化排查法 电子说
|
音频出问题的时候,很多人的排查是这样的:先随便改改 DTS,不行就换颗 CODEC,再不行就怀疑硬件...... 折腾一圈下来,可能连问题出在软件还是硬件都没搞清楚。 这篇文章给你一个有章法、可复现的排查流程,以及每个环节要用到的具体命令。读完你会有一张清晰的 "诊断地图",知道先看什么、后看什么、每一步该验证什么。 |
一、核心思路:六步排查法
不管遇到什么音频问题,都按这个顺序来,不要跳步:
① 声卡注册了吗? → ② 设备节点存在吗? → ③ 时钟跑起来了吗? │ ▼④ 播放/录制测试能过吗? → ⑤ 有 XRUN 或报错吗? → ⑥ 抓数据/上仪器验证
这六步覆盖了从软件配置到硬件信号的完整链路。前四步全是软件排查,第五步定位性能 / 时序问题,第六步确认硬件信号完整性。
二、第一步:确认声卡已注册
2.1 查看声卡列表
cat /proc/asound/cards
正常输出示例:
0 [rockchipes8388c]: simple-card - rockchip-es8388 rockchip-es8388 1 [rockchip-hdmi ]: rockchip-hdmi - rockchip-hdmi
如果什么都没有,或者没有你期望的声卡,说明 Machine Driver 注册失败。此时应该看内核日志:
dmesg | grep -E 'simple-card|snd_soc|ASoC'
常见错误:
| 错误日志 | 含义 | 排查方向 |
| ASoC: no CODEC DAI found | CODEC 节点有问题 | 检查 CODEC 的 status = "okay" |
| ASoC: failed to instantiate card -19 | CPU DAI 驱动没加载 | 检查 I2S/SAI 驱动是否编译进内核 |
| failed to get clock | 时钟配置缺失 | 检查 DTS 中的 clocks 属性 |
2.2 查看 PCM 设备
cat /proc/asound/pcm
输出示例:
00-00: ES8388 HiFi es8388-hifi-0 []00-01: SPDIF RX spdif-hifi-1 []01-00: HDMI PCM hdmi-hifi-0 []
00-00 表示 card0 device0,对应 /dev/snd/pcmC0D0p(播放)和/dev/snd/pcmC0D0c(录制)。
三、第二步:确认设备节点存在
ls -l /dev/snd/
你应该能看到:
| 节点 | 含义 |
| controlC0 | 声卡 0 的控件(音量、静音、路由) |
| pcmC0D0p | 声卡 0、设备 0、playback(播放) |
| pcmC0D0c | 声卡 0、设备 0、capture(录制) |
| timer | 全局定时器 |
如果/dev/snd/ 下没有这些节点,检查:
•CONFIG_SND 相关配置是否开启
•udev 规则是否正确
•SELinux 是否拦截(Android 上常见)
四、第三步:检查时钟—— 最容易被忽视的一环
4.1 查看时钟树
cat /sys/kernel/debug/clk/clk_summary | grep -E 'i2s|sai|pdm|spdif|mclk|bclk|lrck'
正常输出示例:
clock enable_cnt prepare_cnt rate----------------------------------------------------------- i2s_mclk_src 1 1 12288000 i2s_bclk 1 1 1536000 i2s_lrck 1 1 48000 pdm_clk 1 1 3072000
关键检查点:
| 时钟 | 正常值(48kHz/16bit/2ch) | 计算公式 |
| MCLK | 12.288 MHz | 采样率× mclk-fs(256×) |
| BCLK | 1.536 MHz | 采样率× 位深 × 通道数 |
| LRCK | 48 kHz | = 采样率 |
如果enable_cnt 或prepare_cnt 为 0,说明时钟没使能,驱动里的 clk_enable() 可能没调到。
4.2 常用采样率的 BCLK 速查
| 采样率 | 位深 | 通道 | BCLK |
| 8k | 16 | 2 | 256 kHz |
| 16k | 16 | 2 | 512 kHz |
| 44.1k | 16 | 2 | 1.4112 MHz |
| 48k | 16 | 2 | 1.536 MHz |
| 48k | 24 | 8 | 9.216 MHz |
| 96k | 32 | 8 | 24.576 MHz |
如果 BCLK 和预期不符,优先检查 mclk-fs 配置和hw_params() 里的时钟计算逻辑。
五、第四步:播放 / 录制功能测试
5.1 Linux 系统(有 ALSA utils)
# 播放测试aplay -D hw:0,0 -r 48000 -c 2 -f S16_LE test.wav# 录制测试arecord -D hw:0,0 -r 16000 -c 2 -f S16_LE -d 5 test.wav# 管道测试(一边录一边放,测延迟)arecord -D hw:0,1 -f cd | aplay -D hw:0,0# 生成静音测试(确认 DAI 本身没问题)aplay -D hw:0,0 -r 48000 -c 2 -f s16_le /dev/zero
5.2 Android 系统(TinyALSA)
# 播放tinyplay /sdcard/test.wav -D 0 -d 0# 录制tinycap /sdcard/record.wav -D 0 -d 0 -c 2 -r 16000 -b 16# 查看 PCM 设备信息tinypcminfo -D 0
5.3 控件操作
Linux(amixer):
# 列出所有控件amixer -c 0 contents# 设置播放路径(SPK = 扬声器,HP = 耳机)amixer -c 0 sset 'Playback Path' SPK# 设置音量amixer -c 0 sset 'DAC Volume' 175
Android(tinymix):
# 列出所有控件tinymix# 按 ID 设置(ID 和值从 tinymix 输出里找)tinymix 0 2 # 设置控件 0 的值为 2tinymix "DAC Volume" 175
六、第五步:XRUN 和性能问题

6.1 什么是 XRUN?
| 类型 | 场景 | 表现 |
| Underrun | 播放时 buffer 空了,DMA 没数据可取 | 爆音、断音 |
| Overrun | 录制时 buffer 满了,DMA 没地方放 | 丢数据、无声 |
6.2 开启 XRUN 调试
# 开启最详细的 XRUN 日志echo 7 > /proc/asound/card0/pcm0p/xrun_debug# 播放测试,然后查看日志dmesg | grep -i xrun
6.3 调整 period/buffer 大小
如果频繁 XRUN,尝试增大缓冲区:
aplay -D hw:0,0 --period-size=2048 --buffer-size=8192 test.wav
排查思路:
1.period_size 是否太小?→ DMA 中断太频繁,CPU 来不及响应
2.buffer_size 是否太小?→ 抗抖动能力差
3.CPU 负载是否过高?→ 后台任务占用了太多时间
4.DMA burst size 是否正确?→ 传输效率低
七、第六步:深入寄存器和数据
7.1 查看 CODEC 寄存器
# 查看所有 regmap 设备ls /sys/kernel/debug/regmap/# 查看特定 CODEC 的寄存器(按 I2C 地址)cat /sys/kernel/debug/regmap/0-001c/registers# 写寄存器调试(关闭 cache,开启 bypass)echo N > /sys/kernel/debug/regmap/0-001c/cache_onlyecho Y > /sys/kernel/debug/regmap/0-001c/cache_bypassecho "0x03=0x80" > /sys/kernel/debug/regmap/0-001c/registers
7.2 I2C Tools 直接操作 CODEC
# 扫描 I2C 总线i2cdetect -y 0# Dump 寄存器i2cdump -f -y 0 0x1c b# 读写单个寄存器i2cget -f -y 0 0x1c 0x03 bi2cset -f -y -r 0 0x1c 0x03 0x80 b
7.3 查看 SoC DAI 寄存器
# 查看 I2S/SAI 寄存器(地址从设备树 reg 属性获取)cat /sys/kernel/debug/regmap/ff800000.i2s/registers# 或用 io 命令直接读写io -4 -l 0x40 0xff800000io -4 0xff800000 0x0
八、Android 特有调试手段
8.1 Logcat 音频相关日志
# AudioFlinger 层(混音、路由、设备切换)logcat -s AudioFlinger# Audio HAL 层(PCM open/close、控件设置)logcat -s audio_hw# 音频路由变化logcat -s alsa_route
8.2 PCM Dump:抓取音频数据
# 抓取播放数据(Android 10+)touch /data/misc/audioserver/debug.pcmchmod 777 /data/misc/audioserver/debug.pcmsetenforce 0setprop vendor.audio.record 5# 抓取录制数据(Android 12+)touch /data/misc/audioserver/debug_in.pcmchmod 777 /data/misc/audioserver/debug_in.pcmsetprop vendor.audio.record.in 5
抓取后用 Audacity 导入分析:File → Import → Raw Data,选 Signed 16-bit PCM、Little-endian、48000Hz。
8.3 AudioPolicy 状态
# 查看音频策略状态dumpsys media.audio_policy# 查看 AudioFlinger 状态dumpsys media.audio_flinger# 查看音频相关属性getprop | grep audio
九、硬件验证:什么时候该上示波器?
软件排查完后如果还有问题,就需要验证硬件信号了:
| 仪器 | 用途 | 关键检查点 |
| 万用表 | 电源电压、GPIO 电平 | CODEC 的 AVDD/DVDD 是否正常 |
| 示波器 | BCLK/LRCK/SDO 时序 | 频率对不对?有没有信号? |
| 逻辑分析仪 | 数字信号时序 | 协议格式是否正确? |
示波器探头连接建议:
CH1 → BCLK(检查频率 = 采样率 × 位深 × 通道数)CH2 → LRCK(检查频率 = 采样率)CH3 → SDO(检查是否有数据波形)
如果 BCLK 和 LRCK 都有正常波形,但 SDO 是平的,问题在软件数据通路;如果 BCLK 或 LRCK 没有,问题在时钟配置。
十、一键诊断脚本
把下面这个脚本保存为audio_diag.sh,出问题直接跑一遍:
#!/bin/bashecho "=== 声卡列表 ==="cat /proc/asound/cardsecho ""echo "=== PCM 设备 ==="cat /proc/asound/pcmecho ""echo "=== 设备节点 ==="ls -l /dev/snd/echo ""echo "=== 时钟摘要 ==="cat /sys/kernel/debug/clk/clk_summary | grep -E 'i2s|sai|pdm|spdif|mclk|bclk'echo ""echo "=== CODEC 寄存器 ==="cat /sys/kernel/debug/regmap/*/registers 2>/dev/nullecho ""echo "=== 内核
十一、总结
音频调试的核心链路:
1.先看声卡:/proc/asound/cards 确认注册成功
2.再看节点:/dev/snd/ 确认设备文件存在
3.检查时钟:clk_summary 确认频率和使能状态正确
4.功能测试:aplay/arecord 或tinyplay/tinycap
5.排查 XRUN:调整 period/buffer,检查 CPU 负载
6.深入寄存器:regmap、i2ctools、io 命令
7.抓取数据:PCM Dump + Audacity 分析
8.硬件验证:示波器确认 BCLK/LRCK/SDO
记住这个顺序,不要一上来就改代码。先把问题范围缩小到某个环节,再针对性深入。
你在音频调试中踩过最大的坑是什么?时钟?XRUN?还是路由?分享一下你的经历。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !