杰理 SDK 文档中心
首页
首页
  • SDK 概述与入门

    • SDK 总览
    • 支持芯片与蓝牙认证
    • 工程结构导航
  • 开发环境与构建

    • 环境搭建与工具链安装
    • 编译指南与工程选择
    • 烧录与生产工具
  • BLE 透传/数传应用

    • 透传应用框架与处理模块
    • 透传与数传示例
    • 多连接与自定义服务示例
    • FindMy 与查找网络示例
  • HID 人机交互应用

    • 键盘与按键设备示例
    • 鼠标设备示例
    • 遥控器示例
    • HID 蓝牙应用模块
  • 公共 BSP 模块

    • 按键、编码器与红外输入
    • 传感器驱动
    • LED 与显示控制
    • 串口与 USB 通信
    • 存储、参数与时钟
    • 电源与温度管理
    • 消息、内存与系统配置
    • OTA 升级框架
  • 蓝牙协议栈与库

    • BLE 控制器与协议栈适配
    • 经典蓝牙 BR/EDR 支持
    • 第三方蓝牙协议
    • 设备管理框架
    • DUT 测试与射频认证
  • 构建系统与开发工具

    • Makefile 构建系统
    • 固件后处理与配置工具
    • 辅助脚本与库合并
  • 文档与硬件资料

    • AT 命令参考
    • 硬件参考资料
    • SDK 文档与在线资源

串口与 USB 通信

本文档介绍 AW33N BLE SDK 中串口(UART/LPUART)与 USB(设备/主机)两大通信子系统的实现:从硬件寄存器抽象、公共串口控制模块、端点 DMA 缓冲与中断处理,到低功耗唤醒、挂起/恢复与典型使用方式。

Purpose and Scope

本页覆盖以下内容:

  • 串口(UART):公共串口控制模块 common_uart_control(数据接收、回调注册、低功耗唤醒)、BD57 系列 UART 硬件寄存器抽象(uart_hal.h)、低功耗串口 LPUART、调试串口 uart_debug 以及外设演示(uart_demo/lpuart_demo)。
  • USB:设备控制器配置 usb_device_config.c(端点 DMA 缓冲分配、中断表、usb_isr)、USB 设备栈(usb_stack.h)、挂起/恢复(usb_suspend_resume)、USB 主机(usb_host.h/usb_storage.h)与物理层(usb_phy.h)。

以下主题属于其他目录页面的范围,本页仅在必要时引用:

  • 通过串口进行固件升级(testbox_uart_update / uart_update)属于“固件升级”类页面;
  • AT 命令透传(at_char_uart)、FindMy 传感器串口(ble_fmy_sensor_uart)、HID 鼠标(mouse_usb)等应用示例属于各自的应用页面;
  • 低功耗睡眠管理本身属于电源管理页面,本页只说明串口与睡眠的交互点。

概述

AW33N BLE SDK 面向低功耗蓝牙 SoC,通信外设被广泛用于调试、透传、升级与 USB 复合设备(HID/音频/存储)等场景。串口与 USB 在该 SDK 中的角色如下:

  • 串口是系统最基础的调试与数据通道:uart_debug 提供日志输出;common_uart_control 提供一个与具体应用解耦的“公共串口”抽象,任何模块(透传、升级、传感器数据)都可以注册接收回调;lpuart 则面向低功耗场景,可在睡眠时保持唤醒能力。
  • USB 用于将芯片作为设备接入主机(如 PC),常见配置是复合设备:端点 0 用于控制传输(Setup),端点 1 用于大容量存储(MSD),端点 2 用于 HID,端点 3 用于音频(扬声器/麦克风)。SDK 也提供主机侧栈(usb_host)用于读 U 盘等场景。

理解这两个子系统,关键是先看硬件寄存器抽象(UART 的 JL_UART_TypeDef、USB 的端点缓冲分配),再看软件如何围绕 DMA 缓冲与中断把数据搬运到应用层。

架构

flowchart TD
    subgraph sg_App["应用层 (apps)"]
        Demo["uart_demo / lpuart_demo<br/>at_char_uart / ble_fmy_sensor_uart"]
        Update["testbox_uart_update / uart_update"]
        UsbApp["HID mouse / 复合设备应用"]
    end

    subgraph sg_Uart["串口子系统"]
        CommonUart["common_uart_control<br/>(公共串口控制)"]
        UartDebug["uart_debug"]
        Lpuart["lpuart (低功耗串口)"]
        UartHal["UART HAL 寄存器<br/>JL_UART_TypeDef / JL_WL_UART_TypeDef"]
    end

    subgraph sg_Usb["USB 子系统"]
        UsbDevCfg["usb_device_config<br/>(端点缓冲/中断配置)"]
        UsbStack["usb_stack / usb_device<br/>(设备栈)"]
        UsbSuspend["usb_suspend_resume"]
        UsbHost["usb_host / usb_storage<br/>(主机栈)"]
        UsbPhy["usb_phy / usb_hw<br/>(物理层)"]
    end

    subgraph sg_Hw["硬件层"]
        HwUart["UART/LPUART 外设"]
        HwUsb["USB 控制器 (DMA)"]
    end

    Demo --> CommonUart
    Demo --> UartDebug
    Update --> CommonUart
    CommonUart --> UartHal
    UartDebug --> UartHal
    Lpuart --> UartHal
    UartHal --> HwUart

    UsbApp --> UsbStack
    UsbDevCfg --> UsbStack
    UsbStack --> UsbSuspend
    UsbStack --> UsbPhy
    UsbHost --> UsbPhy
    UsbPhy --> HwUsb

架构说明:

  • 串口路径:应用(透传/升级/传感器)通过 common_uart_control 注册接收回调并使用其发送接口;该模块直接操作 HAL 寄存器层(uart_hal.h 中的 JL_UART_TypeDef/JL_WL_UART_TypeDef),最终落到 UART/LPUART 外设。调试日志则走 uart_debug。
  • USB 路径:应用配置设备描述符后,由 usb_device_config 负责端点 DMA 缓冲与中断资源分配;usb_stack 处理枚举与传输;usb_suspend_resume 处理挂起/恢复;主机侧通过 usb_host/usb_storage 访问存储设备。
  • 两条路径都依赖硬件 DMA 与中断:串口用 DMA 接收缓冲(uart_rx_ptr/uart_rx_data),USB 为每个端点预分配对齐 DMA 缓冲,中断服务 usb_isr 在 IRQ 上下文中搬运数据。

串口子系统详解

公共串口控制模块(common_uart_control)

apps/app/bsp/common/common_uart/common_uart_control.c 是整个 SDK 串口数据通道的核心抽象。它以编译宏 TCFG_COMMON_UART_ENABLE 作为总开关,为上层提供“注册接收回调 + 发送数据”的统一接口,屏蔽了具体串口实例的差异。

模块内部的数据结构与关键设计如下:

#if TCFG_COMMON_UART_ENABLE
NOT_KEEP_RAM
static uint8_t uart_rx_ptr[COMMON_UART_RX_BUF_SIZE] ALIGNED(4);

NOT_KEEP_RAM
u8 uart_rx_data[COMMON_UART_RX_BUF_SIZE];

static void (*common_uart_irq_rx_handler_callback)(uint8_t *packet, uint32_t size) = NULL;
static int common_uart_num = COMMON_UART_INDEX;

Source: common_uart_control.c

设计要点:

  • 双缓冲设计:uart_rx_ptr 是 DMA 接收指针缓冲(内部使用,ALIGNED(4) 保证 DMA 对齐),uart_rx_data 是实际数据缓冲(非 static,符号导出,便于调试/抓取)。缓冲大小统一由 COMMON_UART_RX_BUF_SIZE 决定。
  • 回调解耦:接收回调 common_uart_irq_rx_handler_callback 是函数指针,签名固定为 void (*)(uint8_t *packet, uint32_t size)。这样发送方(透传、升级、传感器)不必关心底层是哪个串口、走 DMA 还是中断,只需注册回调。
  • 串口实例选择:common_uart_num 取自 COMMON_UART_INDEX,让同一份代码可以编译到不同串口上,不同产品只需在配置头文件里改索引。

回调注册接口(内部调用,供各模块在初始化时绑定):

void common_uart_regiest_receive_callback(void *rx_cb)
{
    common_uart_irq_rx_handler_callback = rx_cb;
}

Source: common_uart_control.c

紧随其后(第 78–80 行注释处)是“发送数据到串口”的发送入口,与接收回调配套使用:上层把整包数据交给该模块,由模块负责搬运到硬件发送路径。

低功耗唤醒交互

串口与电源管理的关键交互点也在这个文件中。默认 COMMON_UART_RX_POWERLOW_ENABLE 为 0、LPUART_RX_ENABLE 为 0(低功耗串口接收默认关闭);当开启后,行为如下(源码注释原话):

串口接收到数据后禁止系统进休眠,但第一包数据会丢,需要在发送正式数据前发送一个空包,并在 UART_POWERLOW_TIMEOUT 时间内发出后续的有效包。

#define COMMON_UART_RX_POWERLOW_ENABLE     0 //低功耗状态下配置串口唤醒
#define LPUART_RX_ENABLE                   0 //低功耗串口使能

#if COMMON_UART_RX_POWERLOW_ENABLE
#include "asm/power/power_wakeup.h"
#define UART_POWERLOW_TIMEOUT 500 //unit: ms
static u16 uart_pl_timer = 0;   //用于计时进入休眠
static void uart_rx_wakeup_timeout_callback(void *priv)
{
    sleep_run_check_enalbe(1, SLEEP_EN_TYPE_UART);
    uart_pl_timer = 0;
}

static void uart_rx_wakeup_callback(P33_IO_WKUP_EDGE edge)
{
    sleep_run_check_enalbe(0, SLEEP_EN_TYPE_UART);
    if (uart_pl_timer == 0) {
        uart_pl_timer = sys_timeout_add(NULL, uart_rx_wakeup_timeout_callback, UART_POWERLOW_TIMEOUT);
    } else {
        sys_timer_modify(uart_pl_timer, UART_POWERLOW_TIMEOUT);
    }
}

static struct _p33_io_wakeup_config uart_rx_wakeup_config = {
    .pullup_down_mode = PORT_INPUT_PULLUP_10K,
    .gpio = COMMON_UART_RX_PIN,
    .edge = FALLING_EDGE,
    .filter = PORT_FLT_DISABLE,
    .callback = uart_rx_wakeup_callback,
};
#endif

Source: common_uart_control.c

机制说明:

  • 串口 RX 引脚(COMMON_UART_RX_PIN)配置为 P33 端口下降沿唤醒源,空闲时系统可休眠;一旦出现下降沿(起始位),uart_rx_wakeup_callback 被调用,通过 sleep_run_check_enalbe(0, SLEEP_EN_TYPE_UART) 禁止系统进入休眠,防止接收中途掉电。
  • 同时启动/刷新一个 500 ms 的超时定时器(UART_POWERLOW_TIMEOUT):应用须在该窗口内继续发来有效数据并消费完;超时后 uart_rx_wakeup_timeout_callback 重新允许睡眠,回到低功耗状态。
  • 由于唤醒本身要消耗时间,唤醒后的第一包数据会丢失——这是硬件级约束,因此协议设计上要求“先发空包唤醒,再发有效包”,这也是串口低功耗方案的经典 trade-off。

UART 硬件寄存器抽象(uart_hal.h)

apps/include_lib/cpu/bd57/periph/uart_hal.h 定义了 BD57 系列 UART 控制器的寄存器映射,是所有 UART 驱动(含 DMA 收发)直接操作的对象:

typedef struct {
    __RW __u16 TX_CON0;   /* 发送控制 0 */
    __RW __u16 TX_CON1;   /* 发送控制 1 */
    __RW __u16 RX_CON0;   /* 接收控制 0 */
    __RW __u16 RX_CON1;   /* 接收控制 1 */
    __RW __u16 CON2;      /* 控制 2 */
    __RW __u16 BAUD;      /* 波特率 */
    __RW __u8  BUF;       /* 数据寄存器 */
    __RW __u32 OTCNT;     /* 溢出计数 */
    __RW __u32 TXADR;     /* 发送 DMA 地址 */
    __WO __u16 TXCNT;     /* 发送计数 */
    __RW __u32 RXSADR;    /* 接收 DMA 起始地址 */
    __RW __u32 RXEADR;    /* 接收 DMA 结束地址 */
    __RW __u32 RXCNT;     /* 接收计数 */
    __RO __u16 HRXCNT;    /* 硬件接收计数 */
    __RO __u16 RX_ERR_CNT;/* 接收错误计数 */
} JL_UART_TypeDef;

typedef struct {
    __RW __u16 CON0;
    __RW __u16 CON1;
    __RW __u16 CON2;
    __RW __u16 BAUD;
    __RW __u8  BUF;
} JL_WL_UART_TypeDef;

Source: uart_hal.h

值得注意的设计:

  • 完整 DMA 收发寄存器组:TXADR/TXCNT 是发送 DMA 的地址与计数;RXSADR/RXEADR 定义接收 DMA 的环形区间;HRXCNT 实时反映硬件已收字节数;OTCNT 与 RX_ERR_CNT 记录溢出与错误,驱动可据此做丢包统计与恢复。这与 common_uart_control.c 中 ALIGNED(4) 的 DMA 缓冲是配套的——寄存器层直接操作内存地址,驱动只需维护环形缓冲的起止地址。
  • 两种寄存器集:JL_UART_TypeDef 是标准 UART 全功能寄存器集;JL_WL_UART_TypeDef 是精简版(无线/低功耗串口变体),仅保留 CON0/CON1/CON2/BAUD/BUF,对应 lpuart 场景——低功耗串口省去了 DMA 寄存器,由硬件内部完成收发缓冲。

调试串口与演示程序

  • apps/app/bsp/cpu/uart_debug.c(配套头文件 apps/include_lib/cpu/bd57/uart_debug.h):调试串口驱动,负责日志通道的初始化与输出,是 LOG_TAG "[common_uart]" 等日志宏的底层载体。
  • apps/app/bsp/cpu/periph_demo/uart_demo.c 与 lpuart_demo.c:外设演示工程,展示了普通 UART 与 LPUART 的初始化、收发与中断用法,是开发者移植到新产品时的最小参考。
  • 类型与依赖:apps/include_lib/cpu/uart.h、apps/include_lib/cpu/uart_depend.h、apps/include_lib/cpu/bd57/uart_types.h 提供 UART 驱动的公共 API 与依赖注入(如波特率表、引脚配置结构)。

串口接收核心流程

sequenceDiagram
    participant Hw as UART 硬件 (DMA)
    participant Irq as 串口中断服务
    participant Ctl as common_uart_control
    participant App as 应用模块 (透传/升级/传感器)
    participant Pwr as 电源管理 (可选)

    Note over Hw,Pwr: 低功耗模式: RX 下降沿唤醒
    Hw->>Pwr: P33 下降沿唤醒 (COMMON_UART_RX_PIN)
    Pwr->>Pwr: 禁止休眠, 启动 500ms 超时定时器
    Hw->>Irq: DMA 接收完成/数据到达中断
    Irq->>Ctl: 搬运 uart_rx_ptr/uart_rx_data
    Ctl->>App: 调用 common_uart_irq_rx_handler_callback(packet, size)
    App->>App: 解析并处理数据包
    App->>Ctl: 调用发送接口回包
    Note over Pwr: 超时后重新允许休眠

流程要点:硬件 DMA 把数据写入对齐缓冲 → 中断服务更新指针并回调 → 应用在回调中处理;回包经发送接口写回硬件。低功耗模式下,唤醒、禁止休眠、超时恢复三个动作由电源管理回调链保证数据包在窗口内被完整接收。

USB 子系统详解

设备控制器配置(usb_device_config.c)

apps/app/bsp/common/usb/device/usb_device_config.c 负责 USB 设备控制器的资源规划:为每个端点预分配 DMA 缓冲、维护中断向量表,并提供 usb_isr 中断入口。文件开头的资源定义是整个配置的核心:

#define EP0_DMA_SIZE    (64+4)
#define HID_DMA_SIZE    (64+4)
#define AUDIO_DMA_SIZE  (SPK_FRAME_LEN + MIC_FRAME_LEN + 4 * 2)
#define MSD_DMA_SIZE    ((64+4)*2)

#define     MAX_EP_TX   5
#define     MAX_EP_RX   5
static usb_interrupt usb_interrupt_tx[USB_MAX_HW_NUM][MAX_EP_TX];// SEC(.usb_g_bss);
static usb_interrupt usb_interrupt_rx[USB_MAX_HW_NUM][MAX_EP_RX];// SEC(.usb_h_bss);
static usb_interrupt usb_sof_interrupt_tx[USB_MAX_HW_NUM][MAX_EP_TX];
static usb_interrupt usb_mtx_interrupt[USB_MAX_HW_NUM][MAX_EP_RX];
static usb_interrupt usb_mrx_interrupt[USB_MAX_HW_NUM][MAX_EP_RX];

NOT_KEEP_RAM
static u8 ep0_dma_buffer[EP0_DMA_SIZE]     __attribute__((aligned(4)));
NOT_KEEP_RAM
static u8 ep1_msd_dma_buffer[2][MSD_DMA_SIZE]  __attribute__((aligned(4)));
NOT_KEEP_RAM
static u8 ep2_hid_dma_buffer[HID_DMA_SIZE]  __attribute__((aligned(4)));
NOT_KEEP_RAM
static u8 ep3_spk_dma_buffer[AUDIO_DMA_SIZE]   __attribute__((aligned(4)));
NOT_KEEP_RAM
static u8 ep3_mic_dma_buffer[AUDIO_DMA_SIZE]   __attribute__((aligned(4)));

Source: usb_device_config.c

设计意图解读:

  • 复合设备端点规划:EP0 是控制端点(Setup/枚举,64+4 字节,4 字节为 DMA 描述符开销);EP1 是 MSD(大容量存储,双缓冲 2× 用于乒乓传输);EP2 是 HID(64+4,标准 64 字节全速中断包);EP3 分扬声器(SPK,OUT)与麦克风(MIC,IN)两个方向,大小由音频帧长 SPK_FRAME_LEN/MIC_FRAME_LEN 决定。
  • 多硬件单元支持:所有中断表与缓冲都带 USB_MAX_HW_NUM 维度,说明 SDK 支持多个 USB 控制器实例(如双 USB 口),配置层按索引隔离。
  • 中断源细分:除常规 TX/RX 中断外,还单独维护 SOF 中断(usb_sof_interrupt_tx)与 MTX/MRX(主模式收发,即主机侧)中断向量,设备模式与主机模式共用同一套资源表。
  • 内存分段:DMA 缓冲标 NOT_KEEP_RAM(不常驻 RAM,节省低功耗唤醒后的保留内存),中断表放在 .usb_g_bss/.usb_h_bss 段;__attribute__((aligned(4))) 保证 DMA 对齐。

端点缓冲查询接口根据端点号与方向返回对应的 DMA 缓冲,供传输层读写:

__attribute__((always_inline_when_const_args))
void *usb_get_ep_buffer(const usb_dev usb_id, u32 ep)
{
    u8 *ep_buffer = NULL;
    u32 _ep = ep & 0xf;
    if (ep & USB_DIR_IN) {
        switch (_ep) {
        case 0: ep_buffer = ep0_dma_buffer;      break;
        case 1: ep_buffer = ep1_msd_dma_buffer[0]; break;
        case 2: ep_buffer = ep2_hid_dma_buffer;  break;
        case 3: ep_buffer = ep3_mic_dma_buffer;  break;
        }
    } else {
        switch (_ep) {
        case 0: ep_buffer = ep0_dma_buffer;      break;
        case 1: ep_buffer = ep1_msd_dma_buffer[1]; break;
        case 2: ep_buffer = NULL;                break;
        case 3: ep_buffer = ep3_spk_dma_buffer;  break;
        }
    }
    return ep_buffer;
}

Source: usb_device_config.c

要点:usb_id 参数目前仅用于区分硬件单元(缓冲是全局静态的);EP0 双向共用同一缓冲;EP1 按方向使用双缓冲的两个成员(IN 用 [0],OUT 用 [1]);EP2 HID 仅支持 IN 方向(OUT 返回 NULL);EP3 按方向区分 SPK/MIC。该函数标注 always_inline_when_const_args,在编译期参数已知时会被内联,减少传输热路径上的调用开销。

中断处理(usb_isr)

配置层同时提供统一中断入口:

void usb_isr(const usb_dev usb_id)
{
    /* JL_PORTA->OUT |= BIT(7); */
    u32 intr_usb, intr_usbe;
    u32 intr_tx, intr_txe;
    u32 intr_rx, intr_rxe;
    ...
}

Source: usb_device_config.c

usb_isr 按“总中断使能 → TX → RX”分组读取中断状态(intr_usb/intr_usbe、intr_tx/intr_txe、intr_rx/intr_rxe),分别派发到 usb_interrupt_tx/usb_interrupt_rx 向量表,最终回调到设备栈注册的处理函数。它运行在 IRQ 上下文,因此处理函数必须短小、不做阻塞操作。

设备栈、挂起恢复与主机侧

围绕 usb_device_config.c 的外围模块:

  • 设备栈:apps/include_lib/device/usb/device/usb_stack.h 与 apps/app/bsp/common/usb/device/usb_device.c 实现 USB 设备枚举、标准请求(SETUP)处理与描述符管理(usb/device/descriptor.h)。usb_device_config.c 顶部包含的 usb_stack.h、usb_suspend_resume.h、fusb_pll_trim.h 表明设备初始化链路为:usb_device.c → 配置层分配资源 → 物理层(fusb_hal/usb_hw,含 PLL 校准 fusb_pll_trim)。
  • 挂起/恢复:apps/app/bsp/common/usb/device/usb_suspend_resume.c(头文件 apps/include_lib/device/usb/device/usb_suspend_resume.h)处理总线 SUSPEND/RESUME 事件,配合 usb_config.h 中的电源策略,在总线空闲时进入低功耗、检测到恢复信号时重新启动时钟——这与串口的低功耗唤醒是同一套电源管理框架下的两个实例。
  • 主机栈:apps/include_lib/device/usb/host/usb_host.h 与 usb_storage.h 提供主机模式(HOST),可枚举外部设备并访问 U 盘(Mass Storage)。主模式复用了配置层中 usb_mtx_interrupt/usb_mrx_interrupt 主收发中断向量。
  • 公共定义与物理层:usb_config.h(全局开关与参数)、usb_common_def.h/usb_std_class_def.h(标准 USB 类型与类定义)、usb_phy.h(物理层接口)、apps/include_lib/cpu/bd57/usb_hw.h 与 fusb_hal.h(芯片 USB 硬件寄存器与 PHY HAL)。

USB 设备枚举与传输流程

sequenceDiagram
    participant Host as USB 主机 (PC)
    participant Hw as USB 控制器 + PHY
    participant Isr as usb_isr (IRQ)
    participant Cfg as usb_device_config
    participant Stack as usb_stack / usb_device
    participant App as 应用 (HID/音频/MSD 回调)

    Host->>Hw: 复位/枚举 (SETUP)
    Hw->>Isr: 中断 (intr_usb/intr_txe)
    Isr->>Cfg: 查询中断向量表
    Cfg->>Stack: 派发到 usb_interrupt_tx/rx 处理
    Stack->>Stack: 解析 SETUP (usb_setup_t)
    Stack->>Cfg: usb_get_ep_buffer(ep) 取缓冲
    Stack->>App: 调用类驱动回调 (HID/音频/MSD)
    App->>Stack: 填充数据 (如 HID 报告)
    Stack->>Cfg: 写端点 DMA 缓冲
    Cfg->>Hw: 触发 IN 传输 (TXCNT/TXADR)
    Hw-->>Host: 数据上传

要点:枚举阶段的 SETUP 包走 EP0 的 usb_setup_t 结构(usb_config_var_t 成员),传输阶段按端点号经 usb_get_ep_buffer 取缓冲,由类驱动(HID/音频/MSD)填充数据后经 DMA 上传。整个路径在中断上下文完成,配置层只负责“缓冲分配 + 中断分发”,具体协议逻辑全部在 usb_stack 与类驱动中。

配置选项

串口与 USB 的行为主要通过板级/产品配置头文件中的宏控制(app_config.h、usb_config.h 及各产品配置)。以下是从源码中直接确认的关键配置项:

配置宏类型默认值/来源说明
TCFG_COMMON_UART_ENABLE开关由产品配置决定common_uart_control 模块总开关,关闭后整个公共串口代码不编译
COMMON_UART_RX_BUF_SIZE整数产品配置串口接收 DMA 缓冲大小,同时决定 uart_rx_ptr 与 uart_rx_data 的长度
COMMON_UART_INDEX整数产品配置使用的串口实例编号(common_uart_num)
COMMON_UART_RX_PIN引脚枚举产品配置串口接收引脚,低功耗唤醒源
COMMON_UART_RX_POWERLOW_ENABLE开关0是否使能低功耗状态下串口唤醒(含 P33 下降沿唤醒配置)
LPUART_RX_ENABLE开关0是否使能低功耗串口接收(对应 JL_WL_UART_TypeDef 精简寄存器集)
UART_POWERLOW_TIMEOUT整数(ms)500唤醒后禁止休眠的超时窗口,超时后恢复允许睡眠
USB_MAX_HW_NUM整数usb_config.h支持的 USB 硬件单元数量,决定中断表与缓冲数组的维度
MAX_EP_TX / MAX_EP_RX整数5每单元最大端点数(TX/RX 各 5)
EP0_DMA_SIZE整数64+4控制端点 DMA 缓冲大小(数据 + 描述符开销)
HID_DMA_SIZE整数64+4HID 端点缓冲大小
MSD_DMA_SIZE整数(64+4)*2MSD 端点缓冲大小(双缓冲)
AUDIO_DMA_SIZE整数SPK_FRAME_LEN + MIC_FRAME_LEN + 4*2音频端点缓冲大小,随音频帧长变化
USB_SETUP_SIZE整数usb_config.hSETUP 包缓冲大小(usb_config_var_t.usb_setup_buffer)

配置值来源:common_uart_control.c、usb_device_config.c

API 参考

common_uart_regiest_receive_callback(void *rx_cb)

注册公共串口接收回调。上层模块(透传、升级、传感器)在初始化时调用,之后每次收到完整数据包都会回调。

参数:

  • rx_cb (void *): 回调函数指针,实际签名为 void (*)(uint8_t *packet, uint32_t size),packet 指向 uart_rx_data 中的数据,size 为本次包长。

返回: 无。

说明: 源码注释标注“内部调用”,回调直接保存在全局函数指针 common_uart_irq_rx_handler_callback 中,重复注册会覆盖旧回调。

Source: common_uart_control.c

void *usb_get_ep_buffer(const usb_dev usb_id, u32 ep)

按 USB 硬件单元、端点号与方向返回对应的 DMA 缓冲。

参数:

  • usb_id (usb_dev): USB 硬件单元索引(当前缓冲为全局静态,主要用于区分单元)。
  • ep (u32): 端点号,低 4 位为端点编号,USB_DIR_IN 位表示 IN 方向。

返回: 指向对齐 DMA 缓冲的指针;EP2 OUT 方向返回 NULL(HID 仅支持 IN)。

说明: 标记为 always_inline_when_const_args,常量参数时编译期内联,用于传输热路径。

Source: usb_device_config.c

void usb_isr(const usb_dev usb_id)

USB 控制器统一中断入口,读取并派发 USB/TX/RX 中断到 usb_interrupt_tx/usb_interrupt_rx 向量表。运行于 IRQ 上下文。

Source: usb_device_config.c

故障模式、边界情况与并发

  • 低功耗首包丢失(已知硬件约束):串口唤醒后第一包数据可能丢失,源码明确要求“发送正式数据前先发送一个空包,并在 UART_POWERLOW_TIMEOUT(500 ms)内发出后续有效包”。协议设计必须容忍首包丢失或采用“空包唤醒”握手。
  • 唤醒超时与休眠竞态:uart_rx_wakeup_callback 用 sys_timeout_add/sys_timer_modify 维护 500 ms 窗口,若应用处理慢于窗口,系统会重新允许休眠,导致后续数据丢失。接收回调中应快速搬走数据,避免长时间占用。
  • DMA 缓冲对齐与大小:串口与 USB 的 DMA 缓冲都要求 ALIGNED(4),且大小必须覆盖最大包(USB 端点缓冲含 4 字节 DMA 描述符开销,如 64+4)。若产品修改端点或帧长(如加大音频 SPK_FRAME_LEN),必须同步调整 AUDIO_DMA_SIZE 等宏,否则 DMA 越界。
  • EP2 OUT 无缓冲:usb_get_ep_buffer 对 EP2 OUT 返回 NULL,HID 类驱动若向该方向发送会得到空指针,需在驱动层规避(HID 中断传输本身是 IN-only)。
  • IRQ 上下文约束:usb_isr 与串口中断都在中断上下文运行,回调必须短小、禁止阻塞/休眠调用,否则会拉长中断关闭窗口,影响 BLE 协议栈时序。
  • 多 USB 硬件单元隔离:中断表按 USB_MAX_HW_NUM 分组,但端点缓冲是全局静态的;若同时启用多个单元,需确认缓冲复用策略,避免两个控制器争用同一缓冲。

性能与运维注意事项

  • DMA 搬运为主:串口接收用 DMA 环形缓冲(RXSADR/RXEADR),USB 端点预分配 DMA 缓冲,CPU 仅在中断时搬运/解析,吞吐量受限于外设时钟与总线频率而非 CPU。
  • 内联优化热路径:usb_get_ep_buffer 常量参数内联,减少每次传输的调用开销;驱动开发时应保持端点号以常量传入。
  • 内存布局:NOT_KEEP_RAM 缓冲不常驻,进入低功耗后由系统回收,唤醒后再初始化;uart_rx_data 为非 static 导出符号,便于调试器查看。
  • 调试手段:日志宏(LOG_TAG "[common_uart]"、"[USB]")可开 LOG_DUMP_ENABLE/LOG_DEBUG_ENABLE 抓取收发数据;uart_debug 提供独立调试通道,排查问题时可先确认调试串口是否正常。

扩展点

  • 串口接收回调:common_uart_regiest_receive_callback 是串口数据进入应用层的唯一入口,新业务(透传协议、传感器上报)只需注册回调并按包解析,无需改动驱动。
  • 串口实例选择:通过 COMMON_UART_INDEX/COMMON_UART_RX_PIN/COMMON_UART_RX_BUF_SIZE 可在不改代码的情况下把公共串口挪到任意 UART/LPUART 引脚与实例。
  • USB 复合设备:usb_device_config.c 的端点-缓冲映射表是扩展新类别的锚点——新增端点需同步增加 DMA 缓冲、中断向量与 usb_get_ep_buffer 分支;类协议逻辑在 usb_stack 之上实现,参考 HID 鼠标示例 apps/demo/hid/examples/mouse_dual/mouse_usb.c。
  • 主机模式:usb_host/usb_storage 复用同一配置层的主收发中断(usb_mtx_interrupt/usb_mrx_interrupt),可扩展 U 盘以外的设备类。

相关文件

  • common_uart_control.c / common_uart_control.h
  • uart_hal.h / lpuart.h / uart_debug.c
  • usb_device_config.c / usb_device.c / usb_suspend_resume.c
  • usb_config.h / usb_stack.h / usb_host.h

相关链接

  • 固件升级(串口升级通道 testbox_uart_update):见“固件升级”目录页
  • AT 命令透传(at_char_uart):见“AT 命令”目录页
  • FindMy 传感器串口(ble_fmy_sensor_uart):见“FindMy”目录页
  • HID 鼠标与 USB 复合设备应用:见“HID 设备”目录页
  • 低功耗睡眠与电源管理:见“电源管理”目录页
Prev
LED 与显示控制
Next
存储、参数与时钟