4. Zephyr Kconfig选项裁剪TFLM算子集

任务目标

在Zephyr环境下配置UART外设,实现开发板与PC之间的字符串双向收发。通过串口终端发送字符串至开发板,开发板接收后原样回传(echo),同时开发板主动发送一条启动提示信息,以此验证串口驱动的基本收发流程。

环境与依赖

  • 硬件:支持Zephyr的开发板(以qemu_cortex_m3为例,实际板卡需适配对应DTS)
  • 软件:Zephyr SDK(≥3.2)、west工具链
  • 依赖:CONFIG_SERIAL=y(Zephyr默认启用)、CONFIG_UART_LINE_CTRL=n(本案例不使用流控)

实现原理

Zephyr的UART驱动基于struct device抽象,通过device_get_binding()获取UART设备实例。轮询模式下使用uart_poll_in()接收单字节、uart_poll_out()发送单字节。本案例采用轮询方式实现简单echo,避免引入中断与DMA的复杂度,聚焦驱动基本API调用。

完整代码

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>

/* 获取UART设备,设备树标签为uart0 */
#define UART_DEV DT_NODELABEL(uart0)

void main(void)
{
    const struct device *uart_dev;
    uint8_t rx_byte;
    int ret;

    /* 1. 获取UART设备实例 */
    uart_dev = DEVICE_DT_GET(UART_DEV);
    if (!device_is_ready(uart_dev)) {
        printk("UART device not ready\n");
        return;
    }

    /* 2. 发送启动提示 */
    const char boot_msg[] = "Zephyr UART Echo Ready!\r\n";
    for (int i = 0; boot_msg[i] != '\0'; i++) {
        uart_poll_out(uart_dev, boot_msg[i]);
    }

    /* 3. 轮询接收并回显 */
    while (1) {
        ret = uart_poll_in(uart_dev, &rx_byte);
        if (ret == 0) {
            /* 收到字节,原样回传 */
            uart_poll_out(uart_dev, rx_byte);
            /* 收到回车换行时额外输出换行,便于终端显示 */
            if (rx_byte == '\r') {
                uart_poll_out(uart_dev, '\n');
            }
        }
        k_msleep(10); /* 避免忙等,降低CPU占用 */
    }
}

构建与运行

  1. 创建项目:在Zephyr工作目录下新建uart_echo应用,将上述代码保存为src/main.c,并创建prj.conf(本案例无需额外配置,默认串口已启用)。
  2. 构建(以qemu为例):
    west build -b qemu_cortex_m3 -t run
  3. 连接PC串口:若使用真实板卡,通过USB转串口连接开发板UART0对应引脚,PC端使用minicom或PuTTY打开对应串口(波特率115200,8N1)。

验证方法

  • 启动提示:程序运行后,串口终端应显示Zephyr UART Echo Ready!。
  • 回显测试:在终端输入任意字符串(如Hello)并回车,终端应逐字符回显相同内容,且每次回车后额外输出一个换行。
  • 通过标准:若终端完整显示启动提示,且输入字符能原样返回(包括回车换行行为正常),则判定UART收发功能验证通过。

常见问题

  • 无输出:检查开发板UART引脚映射是否与uart0一致;确认终端波特率与Zephyr设备树中current-speed属性匹配(默认115200)。
  • 乱码:多为波特率不匹配或接地问题,检查串口线连接与终端设置。
  • qemu下无串口交互:qemu的UART默认映射到stdio,需在终端窗口直接输入字符测试,无需额外连接。