NXP RT1010-EVK 在 ZephyrRTOS 中启用 I2S 驱动,核心是通过设备树 Overlay 扩展硬件配置、修改 SAI 时钟初始化函数适配硬件差异,配合 Zephyr 标准化驱动模型实现音频输出。本文基于官方示例工程samples/drivers/i2s/output,详解从环境搭建到信号验证的完整步骤,帮助开发者快速上手 Zephyr 外设驱动配置,适用于 RT1010 系列音频传输场景。
1. 核心目标与环境准备
1.1 技术目标
- 基于 ZephyrRTOS 4.2 + 版本,启用 RT1010-EVK 的 SAI1(I2S 兼容接口);
- 输出正弦波音频数据流,无需外部 Codec,通过 I2S 接口直接发送;
- 实现应用层与底层硬件解耦,复用 Zephyr 标准化 I2S 驱动接口。
1.2 软硬件环境
- 硬件:NXP RT1010-EVK 开发板(仅支持 SAI1、SAI3,无 SAI2);
- 软件:VS Code + MCUXpresso for VS Code 插件(简化 Zephyr 环境搭建);
- 依赖资源:Zephyr SDK、RT1010-EVK 对应 Zephyr 板级支持包(BSP);
- 验证工具:串口终端(查看日志)、信号分析仪(验证 I2S 输出波形)。
2. ZephyrRTOS 核心优势(驱动配置基础)
- 统一设备模型:上层应用无需关注硬件细节,通过标准化 I2S 接口调用,可移植性强;
- 模块化配置:通过 Kconfig 和设备树 Overlay 精准启用功能,减少冗余代码;
- 丰富硬件支持:NXP RT 系列全系列适配,官方提供完善 BSP,降低移植成本。
3. 分步实现流程(重点实操)
2.1 开发环境搭建
(1)快速搭建 Zephyr 环境
- 安装 VS Code 及 MCUXpresso for VS Code 插件;
- 参考官方指南配置 Zephyr SDK(链接:https://docs.zephyrproject.org/latest/develop/getting_started/index.html);
- 同步 Zephyr 源码:执行
git pull更新主线分支,west update同步依赖项目,确保代码为最新版本。
(2)导入 I2S 示例工程
- 打开插件,通过 “Import Example from Repository” 导入项目;
- 选择路径:
samples/drivers/i2s/output,目标开发板选择mimxrt1010_evk。
2.2 确定开发板标识符(Overlay 命名关键)
Zephyr 中开发板的设备树 Overlay 需按固定格式命名,步骤如下:
- 查找板级配置文件:Zephyr 源码路径
boards/nxp/mimxrt1010_evk/board.yml; - 提取核心标识符:文件中定义
name: mimxrt1010_evk、SOCS: name: mimxrt1011; - Overlay 文件名规则:
mimxrt1010_evk_mimxrt1011.overlay(板名 + SOC 名)。
2.3 创建设备树 Overlay 文件(启用 SAI1)
新建
mimxrt1010_evk_mimxrt1011.overlay文件,添加 SAI1 配置(I2S 功能依赖 SAI 接口):/* SPDX-License-Identifier: Apache-2.0 */
/ {
aliases {
i2s-tx = &sai1; // 定义I2S发送别名,关联SAI1
};
};
&sai1 {
status = "okay"; // 启用SAI1接口
pinctrl-0 = <&pinmux_sai1>; // 绑定SAI1引脚复用配置
pinctrl-names = "default"; // 引脚配置名称
};
(2)新增配置文件(优化 DMA 队列)
CONFIG_DMA_TCD_QUEUE_SIZE=4 // 调整DMA传输队列大小,适配I2S数据传输
2.4 验证项目配置(prj.conf)
确保工程根目录的
prj.conf已启用 I2S 相关配置,无需手动修改(示例工程默认配置):CONFIG_I2S=y // 启用I2S驱动子系统
2.5 驱动适配:修改 SAI 时钟初始化函数(关键修复)
RT1010 无 SAI2 接口,默认
soc.c中imxrt_audio_codec_pll_init函数适配有误,需添加条件编译:(1)原函数问题
默认函数包含 SAI2 时钟配置,RT1010 无此接口,编译会报错,原代码片段:
case IMX_CCM_SAI2_CLK:
CLOCK_SetMux(kCLOCK_Sai2Mux, clk_src);
CLOCK_SetDiv(kCLOCK_Sai2PreDiv, clk_pre_div);
CLOCK_SetDiv(kCLOCK_Sai2Div, clk_src_div);
break;
(2)修改后代码
通过
DT_NODE_HAS_STATUS_OKAY判断 SAI 节点是否存在,仅配置实际支持的接口:#if CONFIG_I2S_MCUX_SAI
void imxrt_audio_codec_pll_init(uint32_t clock_name, uint32_t clk_src,
uint32_t clk_pre_div, uint32_t clk_src_div) {
switch (clock_name) {
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai1))
case IMX_CCM_SAI1_CLK:
CLOCK_SetMux(kCLOCK_Sai1Mux, clk_src);
CLOCK_SetDiv(kCLOCK_Sai1PreDiv, clk_pre_div);
CLOCK_SetDiv(kCLOCK_Sai1Div, clk_src_div);
break;
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai2))
case IMX_CCM_SAI2_CLK:
CLOCK_SetMux(kCLOCK_Sai2Mux, clk_src);
CLOCK_SetDiv(kCLOCK_Sai2PreDiv, clk_pre_div);
CLOCK_SetDiv(kCLOCK_Sai2Div, clk_src_div);
break;
#endif
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai3))
case IMX_CCM_SAI3_CLK:
CLOCK_SetMux(kCLOCK_Sai3Mux, clk_src);
CLOCK_SetDiv(kCLOCK_Sai3PreDiv, clk_pre_div);
CLOCK_SetDiv(kCLOCK_Sai3Div, clk_src_div);
break;
#endif
default:
break;
}
return;
}
#endif
- 说明:该修复已合并至 Zephyr 主线分支(参考:https://github.com/zephyrproject-rtos/zephyr/pull/92225),若使用最新源码可跳过此步骤。
2.6 编译与烧录
(1)命令行编译(可选)
在工程根目录执行:
west build -b mimxrt1010_evk samples/drivers/i2s/output
(2)烧录
- 开发板连接 PC,执行命令烧录:
west flash; - 或通过 MCUXpresso 插件:直接点击 “Build” 编译、“Flash” 烧录,操作更便捷。
4. 结果验证
4.1 串口日志验证
烧录完成后,开发板上电,串口终端输出如下日志,说明 I2S 驱动加载成功:
*** Booting Zephyr OS build v4.2.0-rc1-26-gb15404f99834 ***
All I2s blocks written
4.2 波形验证
- 用信号分析仪连接 RT1010-EVK 的 SAI1 输出引脚;
- 观测到正弦波信号,频率、幅度符合预期,证明 I2S 数据正常发送。
5. 关键避坑事项
- Overlay 命名规范:必须严格遵循 “板名_SOC 名.overlay”,否则设备树配置不生效;
- 源码同步:务必更新 Zephyr 至最新版本,避免因旧版驱动适配问题报错;
- 引脚配置:确保
pinmux_sai1在板级设备树中已定义,无需额外修改引脚复用; - DMA 队列大小:
CONFIG_DMA_TCD_QUEUE_SIZE设为 4 即可满足 I2S 传输需求,无需过大。
RT1010-EVK 在 Zephyr 中启用 I2S 驱动的核心是 “设备树配置 + 驱动适配”:通过 Overlay 启用 SAI1 接口,修改时钟初始化函数适配硬件差异,借助 Zephyr 标准化驱动模型实现快速移植。整个流程无需复杂硬件改动,重点在于理解 Zephyr 的设备树机制和板级适配逻辑,适用于各类 RT 系列 MCU 的 Zephyr 外设驱动开发。
阅读全文
206