连接外部 codec 播放音频

在标准的完整开发板镜像上,以 root 身份运行 S31 端的命令。首先完成 通用引脚与 overlay 检查。 明确标注为构建主机操作的命令应在 Linux 主机上执行。

选择时钟关系

随仓库提供的 i2s0 和 i2s1 覆盖层使用虚拟 codec,在播放和录音两个方向 都接收外部 BCLK 和帧时钟。I2S0 的时钟输入为 GPIO42/BCLK 和 GPIO43/WS, 播放数据使用 GPIO44,录音数据使用 GPIO45。产生时钟的 codec 或测试对端 必须在传输前启动匹配的时钟。仓库的I2S HIL 流程 使用 P4 对端提供时钟。只应用默认覆盖层,无法让常见的时钟输入型 DAC 工作。

下面是一个通过 PCM5102A 播放立体声音频的完整新开发板集成示例,依据 S31 DAI、simple-card 和 PCM5102A 驱动编写。它不是仓库已提供的 S31 板级 配置,也没有经过 S31 硬件验证。S31 产生 BCLK 和 WS,DAC 接收这两个时钟。 该 codec 不提供录音。

连接 PCM5102A

使用已正确供电、数字输入兼容 3.3 V 的模块,与 S31 共地,并按下表连接信号。 将硬件配置设为 I2S 格式(FMT 为低)、SCK 为低以使用 BCK 派生的 PLL、 XSMT 为高以解除静音;DEMP 为低可禁用去加重。供电和其他配置脚应遵循模块 原理图。将线路输出连接到合适的线路输入或放大器。这些要求依据 TI PCM5102A 数据手册的引脚功能和三线时钟说明。

本示例中的 S31 信号

PCM5102A 信号

时钟/数据角色

GPIO42

BCK

S31 输出,DAC 输入

GPIO43

LRCK/WS

S31 输出,DAC 输入

GPIO44

DIN

S31 播放数据输出

地

地

公共参考地

不连接外部 MCLK。在 48 kHz 下,两个 32 位时隙对应 3.072 MHz 的 BCLK; mclk-fs = <256> 为 S31 内部 MCLK 请求 12.288 MHz。这些是配置值和推导值, 不是测量结果。

添加声卡并构建

在构建主机上,将以下选项加入 linux-esp32-s31/arch/riscv/configs/esp32s31_defconfig;统一完整配置仍需额外选择此 codec 与声卡驱动。 父仓库的构建流程会根据该源 defconfig 重新生成 .config,仅修改 out/linux/.config 不会持久生效:

CONFIG_SND_SIMPLE_CARD=y
CONFIG_SND_SOC_PCM5102A=y

创建 linux-esp32-s31/arch/riscv/boot/dts/espressif/esp32s31-overlay-i2s0-pcm5102a.dtso, 内容如下,这是完整的覆盖层:

/dts-v1/;
/plugin/;

#include <dt-bindings/pinctrl/esp32s31-pinmux.h>

/ {
    espressif,overlay-name = "i2s0-pcm5102a";
    espressif,resource-claims = "i2s0";
};

&ahb_gdma {
    status = "okay";
};

&gpio {
    pcm5102a_pins: pcm5102a-pins {
        i2s-pins {
            pinmux = <ESP32S31_MATRIX_OUT(42, 25, 0)>,
                     <ESP32S31_MATRIX_OUT(43, 27, 0)>,
                     <ESP32S31_MATRIX_OUT(44, 28, 0)>;
            drive-strength = <20>;
        };
    };
};

&i2s0 {
    #sound-dai-cells = <0>;
    espressif,external-card;
    pinctrl-names = "default";
    pinctrl-0 = <&pcm5102a_pins>;
    status = "okay";
};

&{/} {
    pcm5102a: audio-codec {
        compatible = "ti,pcm5102a";
        #sound-dai-cells = <0>;
    };

    sound-pcm5102a {
        compatible = "simple-audio-card";
        simple-audio-card,name = "S31-PCM5102A";
        simple-audio-card,format = "i2s";
        simple-audio-card,bitclock-master = <&pcm5102a_cpu>;
        simple-audio-card,frame-master = <&pcm5102a_cpu>;
        simple-audio-card,mclk-fs = <256>;

        pcm5102a_cpu: simple-audio-card,cpu {
            sound-dai = <&i2s0>;
            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <32>;
            system-clock-direction-out;
        };

        simple-audio-card,codec {
            sound-dai = <&pcm5102a>;
        };
    };
};

在同一 DTS 目录下的 Makefile 中加入这一行:

dtb-$(CONFIG_ARCH_ESPRESSIF) += esp32s31-overlay-i2s0-pcm5102a.dtbo

CPU 端点的 system-clock-direction-out 不能省略:S31 DAI 的 set_sysclk() 只接受 ID 0 和 SND_SOC_CLOCK_OUT。声卡中的 master 引用使 CPU 同时产生 BCLK 和 WS,default pinctrl 状态将两个时钟路由为输出。 espressif,external-card 防止内置虚拟声卡占用 DAI。来源: S31 格式和时钟接口、 simple-card 时钟方向、 PCM5102A 驱动。

在构建主机上重新构建并烧录匹配的内核、无线组件和根文件系统。 按烧录指南选择端口并准备串口连接:

make image
make flash-existing-all PORT=/dev/ttyUSB0

rootfs 打包步骤会将 esp32s31-overlay-*.dtbo 复制到覆盖层目录。在 S31 上 移除已有的 i2s0 覆盖层并停止占用冲突引脚的程序后,启用自定义声卡:

s31-overlay apply i2s0-pcm5102a --volatile
aplay -l

使用 aplay -l 报告的声卡和设备编号。以下命令假设设备为 hw:0,0,并且 /mnt/media/audio.raw 已有一份交错立体声、S16_LE、48 kHz 的原始音频文件; 请将两者替换为实际值。在此格式下,1008 帧的周期等于 4032 字节,8064 帧的 缓冲区包含八个周期:

aplay -D hw:0,0 -t raw -f S16_LE -c 2 -r 48000 \
    --period-size=1008 --buffer-size=8064 /mnt/media/audio.raw
s31-overlay remove i2s0-pcm5102a --volatile

预期现象是能够列出 PCM 声卡、播放时没有 ALSA 错误,并且 DAC 线路输出端 能够输出所提供的音频。若没有声卡,检查内核选项、覆盖层应用结果及 dmesg 中的探测错误。若播放正常但无声,检查输出时钟路由、FMT/XSMT/SCK 配置脚、 供电和放大器路径。测量 BCLK/WS 可验证实际时钟配置。移除声卡前应停止所有 ALSA 使用者。

默认的外部时钟声卡也可接入合适的时钟/数据源进行录音。对于立体声 48 kHz S16_LE,默认声卡使用两个 16 位时隙,需要提供 48 kHz WS、1.536 MHz BCLK 及匹配的 I2S 数据。应用默认 i2s0 覆盖层并录制两秒:

s31-overlay apply i2s0 --volatile
arecord -l
arecord -D hw:0,0 -t raw -f S16_LE -c 2 -r 48000 -d 2 \
    --period-size=1008 --buffer-size=8064 /tmp/capture.raw
s31-overlay remove i2s0 --volatile

同样需要将 hw:0,0 替换为实际设备。PCM5102A 是播放 DAC,不能提供此录音 数据流。在同一个 S31 DAI 上进行全双工传输时,两个方向必须使用相同的采样率, 并满足共享 MCLK 的兼容性要求。