RK3568平台 I2S的接口调试与dts配置

1. 项目目标

本次任务的核心目标是在 RK3568 平台上,成功使能并调试多个I2S接口(I2S1, I2S2, I2S3),以实现与外部设备(如FPGA)的数字音频数据通信。具体包括:

  • 配置I2S1和I2S3为音频输出 (Playback)。
  • 配置I2S2为音频输入 (Capture)。

2. 调试主线与过程

整个调试过程遵循“硬件分析 -> DTS配置 -> 命令行测试 -> 问题定位与解决”的清晰脉络。

  1. 前期准备 - 硬件资源分析:

    • 首先,对RK3568 SoC的I2S硬件资源进行梳理,明确了I2S0/1/2/3控制器的基本功能和用途(如I2S0用于HDMI,I2S1/2/3为通用)。
    • 将DTS中的I2S控制器节点(i2s@fe4...)与产品原理图上的GPIO引脚进行了一一对应,为后续的pinctrl配置打下了坚实基础。
  2. 中期实施 - 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节点。
  3. 后期验证 - 系统性测试与问题发现:

    • 使用 aplay -larecord -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驱动用于“链接”的两个软件端点。
  • 设备树 (DTS) 深度应用:

    • 主从配置: 明确了I2S主从模式是在 simple-audio-card 节点中通过 simple-audio-card,bitclock-mastersimple-audio-card,frame-master 属性进行配置的,而非在I2S硬件节点中。
    • 调试工具: 掌握了使用 dtc 工具进行逆向分析的核心调试手段。能够将在开发主机上将 .dtb 反编译为 .dts,以检查最终生效的设备树配置,这成为解决关键问题的钥匙。

4. 关键问题与解决方案

在调试中遇到了两个典型问题,并通过分析成功解决。

  • 问题一:DTS 编译失败 Unable to parse input tree

    • 现象:.dtsi 文件中添加一个独立的 dummycodec 节点,导致编译时报语法错误。
    • 分析: DTS文件的语法要求所有自定义的顶级节点都必须被包含在根节点 / { ... }; 的作用域内。
    • 解决:dummycodec 节点的定义移入 / { ... }; 结构中,问题解决。这加深了对DTS文件结构的理解。
  • 问题二:I2S3 测试时持续报 Broken pipe 错误

    • 现象: speaker-test 在向I2S3写入数据时,不断出现数据下溢(Underrun)错误。
    • 分析过程:
      1. 初步排查: 尝试简化I2S3的 pinctrl 配置,但问题依旧。
      2. 核心方法 - 对比分析: 既然I2S1工作正常,那么其最终配置即为“黄金标准”。
      3. 关键工具 - dtc: 使用 dtc 反编译最终的 .dtb 文件,提取出I2S1和I2S3最终生效的节点内容进行逐行对比。
      4. 发现差异: 发现出问题的I2S3节点中,多了一个 rockchip,bclk-fs = <32>; 的私有属性,而正常工作的I2S1节点中没有。
    • 根本原因: 该私有属性强制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, 串口调试