1. 项目目标
本次任务的核心目标是在 RK3568 平台上,成功使能并调试多个I2S接口(I2S1, I2S2, I2S3),以实现与外部设备(如FPGA)的数字音频数据通信。具体包括:
- 配置I2S1和I2S3为音频输出 (Playback)。
- 配置I2S2为音频输入 (Capture)。
2. 调试主线与过程
整个调试过程遵循“硬件分析 -> DTS配置 -> 命令行测试 -> 问题定位与解决”的清晰脉络。
前期准备 - 硬件资源分析:
- 首先,对RK3568 SoC的I2S硬件资源进行梳理,明确了I2S0/1/2/3控制器的基本功能和用途(如I2S0用于HDMI,I2S1/2/3为通用)。
- 将DTS中的I2S控制器节点(
i2s@fe4...)与产品原理图上的GPIO引脚进行了一一对应,为后续的pinctrl配置打下了坚实基础。
中期实施 - DTS配置与声卡注册:
- 使用
simple-audio-card驱动模型来“链接”SoC的I2S控制器(CPU DAI)和一个虚拟的dummy-codec(Codec DAI),从而在ALSA框架下注册了三张独立的声卡。 - 分别为
card 1(I2S1, output),card 2(I2S2, input),card 3(I2S3, output) 编写了DTS节点。
- 使用
后期验证 - 系统性测试与问题发现:
- 使用
aplay -l和arecord -l命令,成功验证了三张声卡均已在系统中注册。 - I2S1 (Output): 使用
speaker-test -D hw:1,0 ...进行测试,设备工作正常,无报错。 - I2S2 (Input): 使用
arecord -D hw:2,0 ...进行测试,命令按预期“挂起”等待外部时钟,符合I2S Slave模式的正确行为。 - I2S3 (Output): 使用
speaker-test -D hw:3,0 ...进行测试,发现严重问题:设备虽能打开,但持续抛出Write error: -32, Broken pipe错误。
- 使用
3. 核心知识学习与沉淀
在调试过程中,对Linux音频子系统和DTS进行了系统性的学习。
I2S 协议基础:
- 引脚功能: 明确了 SCLK (位时钟), WS/LRCLK (帧同步/左右声道选择), SD/D0 (串行数据) 以及 MCLK (主时钟) 的核心作用。
- 主从模式: 深入理解了Master(提供时钟)与Slave(接收时钟)模式的区别,并掌握了“数据源即时钟源”的最佳实践原则(输出时SoC做Master,输入时SoC做Slave)。
Linux 音频子系统 (ASoC & ALSA):
- ASoC 架构: 掌握了其核心的“Platform-Codec-Machine”三组件解耦思想。清晰地将
rockchip-i2s-tdm驱动对应为Platform,dummy-codec对应为Codec,simple-audio-card对应为Machine。 - DAI 概念: 理解了CPU DAI和Codec DAI是Machine驱动用于“链接”的两个软件端点。
- ASoC 架构: 掌握了其核心的“Platform-Codec-Machine”三组件解耦思想。清晰地将
设备树 (DTS) 深度应用:
- 主从配置: 明确了I2S主从模式是在
simple-audio-card节点中通过simple-audio-card,bitclock-master和simple-audio-card,frame-master属性进行配置的,而非在I2S硬件节点中。 - 调试工具: 掌握了使用
dtc工具进行逆向分析的核心调试手段。能够将在开发主机上将.dtb反编译为.dts,以检查最终生效的设备树配置,这成为解决关键问题的钥匙。
- 主从配置: 明确了I2S主从模式是在
4. 关键问题与解决方案
在调试中遇到了两个典型问题,并通过分析成功解决。
问题一:DTS 编译失败
Unable to parse input tree- 现象: 在
.dtsi文件中添加一个独立的dummycodec节点,导致编译时报语法错误。 - 分析: DTS文件的语法要求所有自定义的顶级节点都必须被包含在根节点
/ { ... };的作用域内。 - 解决: 将
dummycodec节点的定义移入/ { ... };结构中,问题解决。这加深了对DTS文件结构的理解。
- 现象: 在
问题二:I2S3 测试时持续报
Broken pipe错误- 现象:
speaker-test在向I2S3写入数据时,不断出现数据下溢(Underrun)错误。 - 分析过程:
- 初步排查: 尝试简化I2S3的
pinctrl配置,但问题依旧。 - 核心方法 - 对比分析: 既然I2S1工作正常,那么其最终配置即为“黄金标准”。
- 关键工具 -
dtc: 使用dtc反编译最终的.dtb文件,提取出I2S1和I2S3最终生效的节点内容进行逐行对比。 - 发现差异: 发现出问题的I2S3节点中,多了一个
rockchip,bclk-fs = <32>;的私有属性,而正常工作的I2S1节点中没有。
- 初步排查: 尝试简化I2S3的
- 根本原因: 该私有属性强制I2S硬件使用固定的时钟比率,与
simple-audio-card驱动尝试动态设置的比率产生冲突,导致硬件无法正确工作。 - 解决方案: 在板级dts文件中,针对
&i2s3_2ch节点,使用/delete-property/ rockchip,bclk-fs;指令,明确删除了这个从上游.dtsi文件继承来的冲突属性,问题彻底解决。
- 现象:
5. 测试方法与工具
本次调试促使整理了一套标准、可复现的命令行测试(调试)流程:
- 设备枚举:
aplay -l/arecord -l(检查声卡是否注册) - 输出测试:
speaker-test -D hw:X,Y -c 2 -r 48000 -f S16_LE(验证输出通路,无需音频文件) - 输入测试:
arecord -D hw:X,Y -c 2 -r 48000 -f S16_LE -d 5 test.wav(验证输入通路配置) - DTS 验证:
dtc -I dtb -O dts -o final.dts <path_to_dtb>(反编译并检查最终设备树)
6. 技术栈与工具
- 硬件平台: Rockchip RK3568 SoC
- 软件环境: Linux Kernel 5.10, Buildroot
- 核心技术: Device Tree (DTS), I2S ASOC Subsystem
- 调试工具:
dtc,speaker-test,aplay,arecord, dmesg, 串口调试