LV04-04-串口通信-02-IMX6ULL的UART配置

本文主要是串口通信——驱动IMX6ULL串口的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
Win32DiskImager Win32DiskImager v1.0
点击查看本文参考资料
分类 网址 说明
官方网站 https://www.arm.com/ ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.nxp.com.cn/ NXP官方网站
https://www.nxpic.org.cn/NXP 官方社区
https://u-boot.readthedocs.io/en/latest/u-boot官网
https://www.kernel.org/linux内核官网
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
https://elixir.bootlin.com/linux/latest/source 在线阅读linux kernel源码
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)

一、硬件原理分析

1. 原理图

我使用的是正点原子的ALPHA开发板,原理图如下:

image-20230729131921853

可以看到,我们需要使用的是串口1,也就是UART1。

2. 开发板连接

我们还需要用 USB 串口线将串口 1 和电脑连接起来,并且还需要设置 JP5 跳线帽,将串口 1 的 RXD、 TXD 两个引脚分别与 P116、 P117 连接一起,如图所示:

image-20230729132141751

二、寄存器配置

1. 配置并使能 UART1 时钟

1.1 配置 UART 模块的时钟(寄存器: CCM_CSCDR1)

配置并使能 UART1 时钟,参考资料:《i.MX 6ULL Applications ProcessorReference Manual》参考手册的《 Chapter 18: ClockController Module (CCM)》。 (下图来自参考手册的Figure 18-3. Clock Tree - Part 2 )

image-20230729132507093

根据上图,我们需要配置CCM_CSCDR1[UART_CLK_SEL]和 CCM_CSCDR1 [UART_CLK_PODF]两个位:

image-20230729132809695

由上图 CCM_CSCDR1 寄存器,我们可以了解到 CCM_CSCDR1 [UART_CLK_SEL]默认值为 0; CCM_CSCDR1 [UART_CLK_PODF]默认值为 0。我们一般选择 pll3_80m 作为 UART 的时钟源, UART_CLK_PODF 分频系数选 1 分频(不分频),最后得到 UART 的时钟频率为 80MHz。

image-20230729132913115

正好默认值都为 0 满足我们的时钟需求,所以后续的编程实验,串口时钟这部分可以不设置,用默认值就可以了。

1.2 使能 UART 模块的时钟(寄存器: CCM_CCGR5)

image-20230729133551559

由上图 CCM_CCGR5 寄存器,我们可以了解到 CCM_CCGR5[CG12] 的默认值为 11。我们知道 11 表示该模块全程使能,使用默认值,无需设置。

2. 复用相关 GPIO 为 UART1 功能

2.1 配置 UART1_TX 复用功能

可以参考《i.MX 6ULL Applications ProcessorReference Manual》参考手册的32.6.17 SW_MUX_CTL_PAD_UART1_TX_DATA SW MUX Control Register (IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA) 用到的寄存器为IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA。

image-20230729134232829

由上图我们得知 IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA[MUX_MODE]的默认值为 0101,因此我们需要将其改为 0,用于 UART_TX 功能。

2.2 配置 UART1_RX 复用功能

可以参考《i.MX 6ULL Applications ProcessorReference Manual》参考手册的32.6.18 SW_MUX_CTL_PAD_UART1_RX_DATA SW MUX Control Register (IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA) 用到的寄存器为IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA。

image-20230729134410390

由上图我们得知 IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA[MUX_MODE]的默认值为 0101,因此我们需要将其改为 0,用于 UART_RX 功能。

2.3 选择引脚

IMX6ULL 中,可能会有多个引脚都可以驱动某个模块,还需要进一步选择。比如下图中: A、 B、 C 三个引脚都可以设置为工作于 Module X,它们都可以驱动 Module X。但是使用哪一个引脚呢?还需要设置“ Daisy Chain select”,

image-20230729134721637

对 于 UART1_RX 引 脚 , 我们除 设置IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA 让它工作于 ALT0 之外,还需要设置寄存器 IOMUXC_UART1_RX_DATA_SELECT_INPUT,可以参考《i.MX 6ULL Applications ProcessorReference Manual》参考手册的32.6.360 UART1_RX_DATA_SELECT_INPUT DAISY Register(IOMUXC_UART1_RX_DATA_SELECT_INPUT)

image-20230729135117571

在上图中,引脚 GPIO1_IO02 设置为 ALT8 模式时,它也可以用作 UART1 的 RX输入引脚;引脚 UART1_RX 设置为 ALT0 模式时,它也可以用作 UART1 的 RX 输入引脚。UART1_RX 为何可以选择那么多引脚?

image-20230729135201594

UART1 的发送引脚有 2 个选择: GPIO1_IO02、 UART1_TX,假设选择了UART1_TX 作为发送引脚。UART1 的接收引脚有 2 个选择: GPIO1_IO03、 UART1_RX,假设选择了UART1_RX 作为接收引脚。

但是 UART1 的模块还可能通过 daisy 引脚再次选择: GPIO1_IO02、GPIO1_IO03、 UART1_TX、 UART1_RX 中的某一个。比如上图中,选择 UART1_TX时,这就构成了回环,可以用于测试: IMX6ULL 发出去的数据直接返回给自己;选择 UART_RX 是,就可以接收外面设备比如 PC 机的数据。

2.4 配置 UART1_TX 硬件参数

寄存器: IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA。经过比对,我们使用默认值( 0x10b0)即可,无需配置。

2.5 配置 UART1_RX 硬件参数

寄存器: IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA。经过比对,我们使用默认值( 0x10b0)即可,无需配置。

3. 设置 UART1 传输格式,波特率

3.1 配置寄存器 UART1_UCR2(0x2020084)

设置 UART1 传输格式 :

1
UART1->UCR2 |= (1<<14) |(1<<5) |(1<<2)|(1<<1);

bit[14]: 1,忽略 RTS 引脚

bit[8] : 0,关闭奇偶校验 默认为 0,无需设置

bit[6] : 0,停止位 1 位 默认为 0,无需设置

bit[5] : 1,数据长度 8 位

bit[2] : 1,发送数据使能

bit[1]: 1,接收数据使能

3.2 配置寄存器 UART1_UCR3(0x2020088)

1
UART1->UCR3 |= (1<<2);

3.3 寄存器 UART1_UFCR(0x2020090)

UART1_UFCR[9-7]: UART 的时钟源分频系数,我们选择 101(即十进制的 5),表示不分频。

1
UART1->UFCR = 5 << 7; /* Uart 的时钟 clk: 80MHz */

3.4 寄存器 UART1_UBIR(0x20200A4)和UART1_UBMR(0x20200A8)

通过设置 UART1_UBIR 与 UART1_UBMR,最终确定波特率。

image-20230729140054127

(1)设置 115200 的波特率即 BaudRate = 115200;

(2)UART1 的时钟频率前面内容已确定 80Mhz 即 Ref Freq = 80000000;

(3)IMX6ULL 波特率计算公式得 115200 = 80000000 /(16*(UBMR +1)/(UBIR+1));

(4)选取一组满足上式的参数: UBMR、 UBIR 即可;

(5)UART1_UBIR = 71 ; UART1_UBMR = 3124

1
2
UART1->UBIR = 71;
UART1->UBMR = 3124;

4. 使能 UART1

使能 UART1, 需要配置的是UART1_UCR1(0x2020080)寄存器。配置 UART1_UCR1[0]: 1 表示使能 UART, 0 表示关闭 UART。

三、实现串口的收发

这里就具体直接看gitee仓库吧:02_UART · sumumm/imx6ull-bare-demo - 码云 - 开源中国 (gitee.com)。里边有几点修改需要说明一下,主要是对Makefile文件的修改:

(1)makefile添加了数学库:Makefile 文件在链接的时候加入了数学库, 因为在 bsp_uart.c 中有个函数uart_setbaudrate,在此函数中使用到了除法运算,因此在链接的时候需要将编译器的数学库也链接进来。一般的交叉工具链里都提示有基本的数学运算,它们位于 libgcc.a 中。我们需要把 libgcc.a也链接进程序里,所以就需要修改 Makefile。

(2)makefile编译选项:加入了选项“-fno-builtin”,否则编译的时候提示“putc”、“puts”这两个函数与内建函数冲突,错误信息如下所示:

1
2
warning: conflicting types for built-in function ‘putc’
warning: conflicting types for built-in function ‘puts’

在编译的时候加入选项“-fno-builtin”表示不使用内建函数,这样我们就可以自己实现 putc和 puts 这样的函数了。