串口
IMX6ULL 8路UART通道,每一路通道都有17个寄存器,其中UART1的寄存器如下图所示,其他通道仅仅是基地值不一样,参考UART1即可。

硬件分析
UART1接usb转串口,也是默认的调试串口

UART2通过J8跳线帽可接RS485-1或者RS232 CON2
UART3通过J7跳线帽可接RS485-2或者RS232 CON1


UART3还可以单独使用

本章节以UART1为例说明UART的编程
源码分析
参考代码【03.uart_printf】
时钟源选择
参考资料:芯片手册《Chapter 18: Clock Controller Module (CCM)》时钟树得到时钟源为UART_CLK_ROOT


从图中可以看出,需要配置CCM_CSCDR1寄存器的UART_CLK_SEL和UART_CLK_PODF位。CCM_CSCDR1寄存器如下图所示;
image-20210817112210441

UART_CLK_SEL设置为0,选择时钟源为pll3_80mUART_CLK_PODF设置为0,选择不分频,那么UART时钟源为80M
注:UART_CLK_SEL和UART_CLK_PODF位默认值都为0,所以可以使用默认值。
使能UART时钟
配置CCM_CCGR5寄存器CG12位为11,

注:从图中看出,CG12位默认值11,所以可以使用默认值。
复用UART引脚
IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA的MUX_MODE位 设置为0IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA的MUX_MODE位 设置为0IOMUXC_UART1_RX_DATA_SELECT_INPUT的DAISY位设置为11



注意:IOMUXC_UART1_RX_DATA_SELECT_INPUT解释说明:
如下图,如果
DAISY位设置为10(UART1_TX_DATA_ALT0),那么就形成下面的链路:UART1发送脚-》UART1_TX–》UART1接收脚 构成回环模式,也就是UART1的发送数据直接返回到UART1接收,可以用来测试。如下图,如果
DAISY位设置为11(UART1_RX_DATA_ALT0)为正常的rx模式,可以接收PC数据

设置UART1传输格式,波特率
配置寄存器
UART1_UCR2(0x2020084),设置UART1传输格式UART1->UCR2 |= (1<<14) |(1<<5) |(1<<2)|(1<<1);
[14]:忽略RTS引脚
[8] : 0: 关闭奇偶校验 默认为0,无需设置
[6] : 0: 停止位1位 默认为0,无需设置
[5] : 1: 数据长度8位
[2] : 1: 发送数据使能
[1] : 1: 接收数据使能


配置寄存器
UART1_UCR3(0x2020088)根据官方文档表示 [RXDMUXSEL]需要设置为1
UART1->UCR3 |= (1<<2);


寄存器
UART1_UFCR(0x2020090)UART1_UFCR[9-7]:UART的时钟源分频系数RFDIV这里配置不分频UART1->UFCR = 5 << 7; /* Uart的时钟clk:80MHz */


寄存器
UART1_UBIR(0x20200A4),UART1_UBMR(0x20200A8)波特率配置设置115200的波特率即BaudRate = 115200;
UART1的时钟频率前面内容已确定80Mhz即Ref Freq = 80000000;
IMX6ULL波特率计算公式得115200 = 80000000 /(16*(UBMR + 1)/(UBIR+1));
选取一组满足上式的参数:UBMR、UBIR即可;
UART1_UBIR = 71 ; UART1_UBMR = 3124
UART1->UBIR = 71; UART1->UBMR = 3124;



UART1_UCR1(0x2020080)寄存器,使能UART1配置
UART1_UCR1[0]:1表示使能UART, 0表示关闭UART。Base->UCR1 |= (1 << 0); /*使能当前串口*/


串口发送功能
只有当上一个数据发完的时候,我们才能继续发送,因此需要用到UART1_USR2寄存器中表示UART1发送状态的只读状态位[TXDC]
UART1_USR2[3] : 0表示发送未完成 , 1表示发送已完成

void putc(unsigned char c)
{
while(((UART1->USR2 >> 3) &0X01) == 0);/* 等待上一次发送完成 */
UART1->UTXD = c & 0XFF; /* 发送数据 */
}
串口接收功能
UART1_USR2[0] : 0表示没有接收数据就绪, 1表示接收数据准备就绪

unsigned char getc(void)
{
while((UART1->USR2 & 0x1) == 0);/* 等待接收完成 */
return UART1->URXD; /* 返回接收到的数据 */
}
移植printf
上面已经介绍了串口的基本配置,如果我们需要使用printf功能,需要把uboot下的文件文件夹拷贝到工程,如下图所示。

并且需要用到一些数学库,所以,我们需要链接gcc下面的libgcc库,在makefile添加如下:
LIBPATH := -lgcc -L /opt/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/6.2.1
$(TARGET).bin : $(OBJS)
$(LD) -Timx6ul.lds -o $(TARGET).elf $^ $(LIBPATH)
如此即可使用printf。
实验
在主程序正常使用printf函数