i.MX6ULL 内置 8 路 UART 接口,均支持2 线(无硬件流控,仅 TX/RX) 和4 线(带硬件流控,TX/RX/CTS/RTS) 工作模式,由 Linux 统一驱动管理。其中 UART1 为默认调试口,UART2 默认适配蓝牙模块(4 线模式),UART7/UART8 因与 ENET、LCD 引脚复用存在硬件冲突,使能方式与前 6 路不同。本文详细讲解 i.MX6ULL 上UART2 转为普通串口、UART7/UART8 正常使能的完整步骤,包含设备树修改、内核编译、硬件冲突规避,基于 Linux 6.1.1_1.0.0 BSP,适配 EVK 开发板。
资料获取:在i.MX6ULL 上使能UART2以及UART7和UART8
1. i.MX6ULL UART 核心特性与引脚复用说明
1.1 UART 工作模式区别
- 2 线模式:仅使用 TX(发送)、RX(接收)引脚,无硬件流控,需软件实现数据流控制,适用于常规串口通信(如外接传感器、串口屏);
- 4 线模式:在 2 线基础上增加 CTS(清送)、RTS(请求发送)硬件流控引脚,实现硬件 “握手”,适用于大数据量、高可靠性通信(如蓝牙、4G 模块)。
1.2 关键 UART 引脚复用冲突
i.MX6ULL 的 UART 引脚与 ENET、LCD 等外设复用,是使能的核心难点:
- UART2:默认复用为蓝牙 4 线模式,CTS/RTS 引脚与 UART3 部分引脚复用;
- UART7/UART8:核心冲突为RTS 引脚与 ENET TX_CLK 引脚复用,RX/TX 引脚与 LCD_DATA 引脚复用,若不做配置,ENET 时钟会干扰 UART 通信,LCD 使能时会占用 UART 引脚。
1.3 设备节点命名规则
Linux 系统中,i.MX6ULL 的 UART 设备节点统一命名为/dev/ttymxcX,X 为 UART 编号 - 1,即:
UART1→ttymxc0、UART2→ttymxc1、UART7→ttymxc6、UART8→ttymxc7。
2. UART2 使能:从蓝牙 4 线模式转为普通串口
i.MX6ULL EVK 板中 UART2 默认配置为蓝牙 4 线模式(带 uart-has-rtscts 流控),并绑定蓝牙设备树节点,需通过修改设备树剥离蓝牙配置,转为普通 2 线 / 4 线串口,步骤简单且无硬件冲突。
2.1 核心修改:设备树文件imx6ul-14x14-evk.dtsi
设备树路径:arch/arm/boot/dts/imx6ul-14x14-evk.dtsi,找到 UART2 节点&uart2,按需求修改为2 线普通串口(推荐)或自定义 4 线串口。
(1)转为 2 线普通串口(主流用法)
注释蓝牙节点、硬件流控配置,保留基础 TX/RX 引脚配置,修改后代码:
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
/* 注释硬件流控,关闭4线模式 */
// uart-has-rtscts;
/* 注释DTE模式配置(默认DCE模式,无需修改) */
// fsl,dte-mode;
// pinctrl-0 = <&pinctrl_uart2dte>;
status = "okay";
/* 注释蓝牙设备节点,剥离蓝牙绑定 */
// bluetooth {
// compatible = "nxp,88w8987-bt";
// };
};
/* 保留原有pinctrl_uart2引脚配置(仅TX/RX生效,CTS/RTS自动失效) */
pinctrl_uart2: uart2grp {
fsl,pins = <
MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1
MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x1b0b1
MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1
MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x1b0b1
>;
};
- 引脚配置值
0x1b0b1:为 i.MX6ULL UART 引脚标准配置(拉偏、速度、驱动能力),无需修改; - 若需彻底删除无用的 CTS/RTS 引脚,可直接从
fsl,pins中移除对应行。
(2)自定义为 4 线普通串口
若需保留 4 线硬件流控,仅剥离蓝牙绑定,删除bluetooth节点即可,保留uart-has-rtscts;配置。
2.2 重新编译内核与设备树
修改设备树后,需编译内核并部署镜像,使用 Yocto/bitbake 编译命令(适配 NXP 官方 BSP):
# 重新编译Linux内核
bitbake -c compile -f linux-imx
# 部署内核镜像
bitbake -c deploy linux-imx
# 重新编译根文件系统(可选,若仅修改设备树可省略)
bitbake core-image-base
2.3 烧写与验证
使用 NXP UUU 工具将编译后的镜像烧写到 EVK 板,启动后通过以下命令验证 UART2 使能:
# 查看UART设备节点,存在ttymxc1即表示成功
ls /dev/ttymxc*
# 测试串口发送(需外接串口模块,接UART2的TX/RX引脚)
echo "test uart2" > /dev/ttymxc1
3. UART7/UART8 使能:核心解决硬件冲突问题
UART7/UART8 的使能是重点与难点,核心需解决两个硬件冲突:RTS 与 ENET TX_CLK 冲突、RX/TX 与 LCD_DATA 引脚冲突,且根据ENET/LCD 是否启用,配置方式不同,本文以EVK 板 UART7 使能为例(UART8 方法完全一致),讲解最通用场景:ENET 启用、LCD 禁用、UART7 为 2 线模式(无 RTS/CTS)。
3.1 使能前提:明确硬件配置场景
i.MX6ULL 官方手册规定,UART7/UART8 的使能需根据 ENET 和 RTS/CTS 是否启用分场景处理,核心规则:
| 场景 | ENET 状态 | UART7/8 RTS/CTS | 配置要点 |
|---|---|---|---|
| 1 | 禁用 | 任意 | 无需特殊操作,直接配置设备树引脚即可 |
| 2 | 启用 | 启用(4 线) | 设备树配置 RTS/CTS 引脚,内核自动配置冲突寄存器,无需手动修改 |
| 3 | 启用 | 禁用(2 线) | 需手动修改内核代码配置冲突寄存器,设备树配置 TX/RX 引脚并禁用 LCD |
本文讲解场景 3(最通用):ENET 启用(保留网口功能)、UART7 为 2 线模式(常规串口)、禁用 LCD(释放引脚)。
3.2 步骤 1:设备树修改(禁用 LCD + 配置 UART7 引脚)
需修改两个设备树文件:imx6ul-14x14-evk.dtsi和imx6ul-14x14-evk.dts,核心操作:禁用 LCDIF 控制器 + 添加 UART7 引脚与节点配置。
(1)禁用 LCDIF 控制器(释放 LCD_DATA 引脚)
在imx6ul-14x14-evk.dts中找到 LCDIF 节点&lcdif,设置status = "disabled";,彻底禁用 LCD,释放与 UART7 复用的 LCD_DATA16/LCD_DATA17 引脚:
&lcdif {
status = "disabled"; // 禁用LCDIF,释放引脚
// 原有LCD配置全部保留,仅修改status即可
};
(2)添加 UART7 节点与引脚配置
在imx6ul-14x14-evk.dtsi中添加&uart7节点,并在&iomuxc中配置引脚(TX→LCD_DATA16,RX→LCD_DATA17):
// 1. 添加UART7设备节点
&uart7 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart7>; // 绑定引脚配置
status = "okay"; // 使能UART7
// 无uart-has-rtscts,为2线模式
};
// 2. 在&iomuxc中添加UART7引脚配置
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
// 原有其他配置保留,添加以下uart7grp节点
pinctrl_uart7: uart7grp {
fsl,pins = <
// UART7 TX → LCD_DATA16,标准配置0x1b0b1
MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x1b0b1
// UART7 RX → LCD_DATA17,标准配置0x1b0b1
MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x1b0b1
>;
};
};
- UART8 引脚配置参考:TX→LCD_DATA20,RX→LCD_DATA21,节点为
&uart8,引脚配置节点为pinctrl_uart8。
3.3 步骤 2:内核代码修改(解决 RTS 与 ENET TX_CLK 冲突)
当ENET 启用且 UART7/8 为 2 线模式时,内核不会自动配置冲突寄存器,需手动修改 mach-imx6ul.c,设置 IOMUXC 寄存器,规避 ENET TX_CLK 对 UART RTS 引脚的干扰。
(1)修改内核文件mach-imx6ul.c
文件路径:arch/arm/mach-imx/mach-imx6ul.c,找到板级初始化函数imx6ul_init_machine(void),添加寄存器映射与值写入代码,配置 UART7 RTS 冲突寄存器:
static void __init imx6ul_init_machine(void)
{
struct device *parent;
void __iomem *iomux; // 定义IOMUXC寄存器虚拟地址指针
struct device_node *np; // 设备树节点指针
.........
imx6ul_pm_init();
// 新增代码开始:配置UART7 RTS与ENET TX_CLK冲突寄存器
// 找到iomuxc设备树节点
np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-iomuxc");
// 将iomuxc物理地址映射为内核虚拟地址
iomux = of_iomap(np, 0);
// 向UART7 RTS选择寄存器写入0x2,规避ENET TX_CLK冲突
// 寄存器偏移地址0x650为i.MX6ULL UART7 RTS_B_SELECT_INPUT
writel_relaxed(0x2, iomux + 0x650);
// 新增代码结束
.........
}
(2)UART8 冲突寄存器配置
若需使能 UART8,在上述代码后添加 UART8 的寄存器配置,偏移地址为 0x654,写入值为0x3:
// 新增UART8 RTS冲突寄存器配置
writel_relaxed(0x3, iomux + 0x654);
- 寄存器值
0x2(UART7)/0x3(UART8):为 i.MX6ULL 官方指定值,用于将 RTS 引脚的输入源从 ENET TX_CLK 切换为其他引脚,彻底规避冲突。
4. 步骤 3:编译内核与设备树
与 UART2 编译命令一致,使用 bitbake 编译并部署:
# 编译内核(含代码修改)
bitbake -c compile -f linux-imx
# 部署内核与设备树
bitbake -c deploy linux-imx
# 烧写镜像(UUU工具)
5. 步骤 4:UART7/UART8 验证
烧写完成后启动 EVK 板,通过以下命令验证使能结果:
# 查看UART设备节点,存在ttymxc6(UART7)/ttymxc7(UART8)即成功
ls /dev/ttymxc*
# 测试UART7发送(外接串口模块,接LCD_DATA16/TX、LCD_DATA17/RX引脚)
echo "test uart7" > /dev/ttymxc6
# 测试UART8发送(若使能)
echo "test uart8" > /dev/ttymxc7
4. UART7/UART8 4 线模式使能(ENET 启用场景)
若需将 UART7/UART8 配置为4 线模式(带 RTS/CTS) 且ENET 启用,无需修改内核代码,仅需在设备树中完成3 个配置,内核会自动处理 RTS 与 ENET TX_CLK 的冲突:
- 禁用 LCDIF 控制器,释放 TX/RX/CTS/RTS 对应的 LCD_DATA 引脚;
- 在 UART7/8 节点中添加
uart-has-rtscts;,启用硬件流控; - 在
pinctrl_uart7/8中配置完整的 4 线引脚(TX/RX/CTS/RTS)。
设备树示例(UART7 4 线模式)
&uart7 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart7>;
uart-has-rtscts; // 启用4线硬件流控
status = "okay";
};
&iomuxc {
pinctrl_uart7: uart7grp {
fsl,pins = <
MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x1b0b1
MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x1b0b1
MX6UL_PAD_LCD_DATA06__UART7_DCE_CTS 0x1b0b1
MX6UL_PAD_LCD_DATA07__UART7_DCE_RTS 0x1b0b1
>;
};
};
5. 关键注意事项
- 引脚配置值统一:i.MX6ULL 的 UART 引脚配置值固定为
0x1b0b1,包含上拉 / 下拉、速度等级、驱动能力,无需修改; - 设备树节点与引脚对应:
pinctrl-0必须绑定正确的pinctrl_uartX节点,否则 UART 引脚复用失败; - 寄存器偏移地址不可错:UART7 RTS 冲突寄存器偏移为
0x650(值 0x2),UART8 为0x654(值 0x3),错写会导致通信异常; - LCD 与 UART 互斥:UART7/8 的 RX/TX 引脚与 LCD_DATA 复用,LCD 启用时 UART 无法使用,反之亦然,需根据硬件需求取舍;
- 烧写验证顺序:修改后需先烧写内核镜像(含设备树与代码修改),再启动验证,仅烧写根文件系统无效;
- UART8 与 UART7 完全一致:所有 UART7 的配置步骤、代码、设备树修改,仅需替换为 UART8 对应的节点、引脚、寄存器,即可实现 UART8 使能。
i.MX6ULL UART2/UART7/UART8 的使能核心围绕设备树配置与硬件冲突解决,不同 UART 的使能要点可概括为:
- UART2:无核心冲突,仅需修改设备树,注释蓝牙节点和硬件流控,即可转为普通串口;
- UART7/UART8:核心解决RTS 与 ENET TX_CLK、RX/TX 与 LCD_DATA两大冲突,根据 ENET/LCD 是否启用分场景配置,2 线模式(ENET 启用) 需手动修改内核寄存器,4 线模式(ENET 启用) 仅需配置设备树即可。
本文所有配置均基于 NXP 官方 EVK 板与 Linux 6.1.1_1.0.0 BSP,UART8 的使能与 UART7 完全一致,仅需替换对应的节点、引脚和寄存器偏移地址,配置完成后可通过/dev/ttymxcX节点直接使用,与普通串口无差异,可外接传感器、串口屏、无线模块等外设。
213