当前文档版本为 v0.8.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

Driver: UART FIFO

1 功能概述

本例程演示了 Zephyr UART (Serial) Driver 的基本使用方法。

2 环境要求

  • PAN1080 EVB 一块

  • USB-TypeC 线一条(用于供电和查看串口打印 Log)

  • 硬件接线:

    • 使用 USB 线,将 PC USB 与 EVB USB-TypeC(USB->UART)相连

    • 根据 EVB 核心板芯片的封装不同,使用杜邦线将 EVB 底板上的:

      • TX0 与 P00 相连, RX0 与 P01 相连(若 EVB 板芯片为 QFN32 或 LQFP64 封装)

      • TX0 与 P30 相连, RX0 与 P31 相连(若 EVB 板芯片为 QFN48 封装)

    • 另准备一个 USB 转串口模块,将其:

      • RX 连到芯片 P06 (UART1-Tx) 引脚,TX 连到芯片 P07 (UART1-Rx) 引脚(若 EVB 板芯片为 QFN32 或 LQFP64 封装)

      • RX 连到芯片 P14 (UART1-Tx) 引脚,TX 连到芯片 P15 (UART1-Rx) 引脚(若 EVB 板芯片为 QFN48 封装)

  • PC 软件: 串口调试助手(UartAssist)或终端工具(SecureCRT)

3 编译和烧录

例程位置:zephyr\samples_panchip\drivers\uart\uart_fifo

使用 ZAL 工具可以对其进行编译、烧录、打开 VS Code 调试等操作。关于 ZAL 工具的详细介绍请参考:Zephyr APP Launcher 工具介绍

4 演示说明

  1. 首先在 PC 上打开 2 个串口终端:

    • 第一个选择与芯片 P00/P01 (UART0) 相连的串口号,波特率配置为 921600,用于显示 Log 打印

    • 第二个选择与芯片 P06/P07 (UART1) 相连的串口号,波特率配置为 115200,用作待测 UART 交互

  2. 成功编译烧录程序后,按 EVB 板上的复位按钮,执行芯片复位,可以看到第一个串口终端打印了如下的 Log:

    *** Booting Zephyr OS build zephyr-v2.7.0  ***
    Start uart fifo demo..
    UART configure done, exit main thread.
    
  3. 然后向第二个串口终端发送 1234567890asdfghjklzxcvbnm\n 并回车,可以看到接收界面随后显示了 1234567890asdfghjklzxcvbnm,说明例程成功从 UART1 Rx 引脚接收到了数据,并转发到 UART1 Tx 引脚,最终发送到 PC 终端。

    image

    UART FIFO 例程演示

5 开发说明

5.1 使能 UART Driver

  • 确认 CONFIG_UART=y,以将 UART Driver 正确加入编译

  • 确认 Devicetree 或 DTS Overlay 配置文件中 UART 模块的:

    • status 属性值为 okay,以确保系统在启动阶段能正确初始化 UART 模块

    • pinctrl-0 属性中正确配置了 pinmux 引脚参数

    /* pan108xxb5_evb.dts */
    ...
    &uart0 {
    	current-speed = <921600>;
    	pinctrl-0 = <&p0_0_uart0_tx &p0_1_uart0_rx>;
    	status = "okay";
    };
    
    &uart1 {
    	current-speed = <115200>;
    	pinctrl-0 = <&p0_6_uart1_tx &p0_7_uart1_rx>;
    	status = "okay";
    };
    ...
    

5.2 确认 UART 初始化成功

const struct device *uart0 = DEVICE_DT_GET(DT_NODELABEL(uart0));

if (!device_is_ready(uart0)) {
    printk("uart devices not ready\n");
    return;
}

5.3 配置 UART 通信参数

  • 配置串口的波特率、校验位、停止位、数据位和流控:

    #define BAUDRATE			115200
    
    const struct uart_config uart_cfg = {
    	.baudrate = BAUDRATE,
    	.parity = UART_CFG_PARITY_NONE,
    	.stop_bits = UART_CFG_STOP_BITS_1,
    	.data_bits = UART_CFG_DATA_BITS_8,
    	.flow_ctrl = UART_CFG_FLOW_CTRL_NONE
    };
    
  • 串口配置读取与设置:

    uart_config_get(uart0, &uart_cfg_check);
    if(uart_cfg_check.baudrate != BAUDRATE) {
        uart_configure(uart0, &uart_cfg);
    }
    

5.4 UART中断回调和使能

  • 中断回调注册:

    uart_irq_callback_set(uart0, uart_fifo_callback);
    
  • 使能UART TRX:

    uart_irq_tx_enable(uart0);
    uart_irq_rx_enable(uart0);
    
  • TX的逻辑处理:

    static void tx_isr(const struct device *dev)
    {
    	static uint8_t tx_index = 0;
    	int len;
    
    	if(tx_index >= data_len) {
    		uart_irq_tx_disable(dev);
    		uart_irq_rx_enable(dev);
    		tx_index = 0;
    	} else {
    		len = uart_fifo_fill(dev, fifo_data + tx_index, (data_len - tx_index));
    		tx_index += len;
    		if(tx_index >= BUFFER_SIze) {
    			tx_index = 0;
    		}
    	}
    }
    

    将tx的数据写到fifo中,直到所有的数据都写完,然后关闭tx,使能rx,等待数据接收。fifo的最大深度为16。

  • RX的逻辑处理:

    static void rx_isr(const struct device *dev)
    {
    	static uint8_t rx_index = 0;
    
    	uart_fifo_read(dev, fifo_data + rx_index, 1);
    	if ((fifo_data[rx_index] == '\n') || (fifo_data[rx_index] == '\r')) {
    		uart_irq_rx_disable(dev);
    		data_len = rx_index + 1;
    		rx_index = 0;
    		uart_irq_tx_enable(dev);
    	} else {
    		rx_index ++;
    		if(rx_index >= BUFFER_SIze) {
    			rx_index = 0;
    		}
    	}
    }
    

    将串口工具发过来的数据保存到“fifo_data”,每次接收一个数据,直到出现换行符,停止接收。然后将接收的数据原封不动的发送给串口工具。

6 RAM/Flash资源使用情况

Memory region         Used Size  Region Size  %age Used
FLASH:       18176 B       256 KB      6.93%
SRAM:        4232 B        64 KB      6.46%