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

    • SDK 概览与产品定位
    • 支持芯片平台与蓝牙认证
    • SDK 架构与目录分层
  • 快速开始

    • 环境搭建与编译工具链
    • 编译构建系统
    • 板级工程与配置
    • 烧录与固件升级工具
  • 应用工程

    • 应用选择与工程总览
    • SPP + BLE 数传应用框架
    • 透传与 AT 指令示例
    • BLE 广播/中心与定位示例
    • 2.4G 私有协议与 Dongle 示例
    • 云平台接入示例
    • HID 人机交互应用框架
    • HID 示例工程(键盘/鼠标/遥控器/手柄)
    • Bluetooth Mesh 应用框架
    • Mesh 模型与 Mesh DFU 固件升级
    • Mesh 音频编解码演示
  • 芯片平台与硬件抽象

    • 芯片平台总览与差异
    • 音频编解码与时钟管理
    • 外设驱动接口(ADC/IIC/SPI/PWM/LED/充电)
    • 芯片配置工具与下载支持
  • 蓝牙协议栈

    • 蓝牙控制器层(btctrler)
    • 蓝牙协议栈与 Profile(btstack)
    • 蓝牙模块选择与配置
  • 媒体与音频框架

    • 音频流框架
    • 音频编解码与 A2DP 媒体
    • 音频效果处理(EQ/频谱/变调/环绕/超低音)
    • 本地 TWS 与音频同步
  • 系统服务与运行时

    • 实时操作系统与任务调度
    • 消息事件机制
    • 电源管理与低功耗
    • 存储与配置系统
    • 设备驱动框架(USB/RTC)
  • 应用公共组件

    • 音频应用组件
    • 设备外设抽象(按键/触摸/传感器/存储)
    • 蓝牙公共模块与消息联动
    • 调试与配置组件
    • 杰理关键词唤醒(jl_kws)
  • 第三方协议与云平台接入

    • 杰理 RCSP 私有协议
    • 低功耗蓝牙 Mesh 方案(llsync_mesh)
    • Sig Mesh 方案
    • 涂鸦协议接入
    • 腾讯连连接入
    • 华为 HiLink 接入
  • 固件升级与维护

    • OTA 升级机制
    • 升级补丁与版本维护
    • 升级工具链(BLE OTA / USB Dongle OTA)
  • 文档与开发资源

    • 数据手册与架构文档
    • 协议与云平台开发文档
    • 常见问题与技术支持

板级工程与配置

AC63 BT SDK 的板级工程(Board)体系:以「芯片系列 + 项目」为单位组织的板级源文件、TCFG_* 配置宏体系,以及从板级平台数据到驱动注册、电源与唤醒初始化的完整链路。

Purpose and Scope

本文档说明 AC63 BT SDK(fw-AC63_BT_SDK)中板级工程的组织方式与配置方法,覆盖:

  • apps/hid/board/ 目录下按芯片系列(bd19 / bd29 / br23 / br25)划分的板级文件布局;
  • 板级文件三件套的职责划分:board_<chip>_<project>.c(平台数据与初始化)、board_<chip>_<project>_cfg.h(外设使能与引脚配置)、board_<chip>_<project>_global_build_cfg.h(全局编译配置);
  • 通过 CONFIG_BOARD_* 宏实现板级文件的条件编译与选择机制;
  • TCFG_* 配置宏如何映射为 power_param、uart0_data、charge_data、adkey_data、iokey_list、wk_param 等平台数据结构,并被底层驱动消费;
  • board_power_init() 电源初始化、休眠/唤醒回调与软关机处理的实现细节。

与板级工程相邻但不属于本文档范围的专题(请参见对应目录页):SDK 的编译构建系统与工程模板(见 Getting Started 其他小节)、具体外设驱动(UART/SPI/IIC/Flash 等)的驱动层实现、低功耗协议栈行为(本文只涉及板级侧的电源参数与唤醒配置)。

Overview

在嵌入式蓝牙 SDK 中,「板级工程」是连接芯片硬件能力与上层应用的适配层。AC63 BT SDK 的板级体系基于以下设计思想:

  1. 按芯片系列 + 项目双维度组织。同一颗芯片(如 AC6321A)可以承载多种项目(demo 演示、鼠标、键盘、遥控器 keyfob),每种组合对应一组板级文件,互不干扰。
  2. 条件编译驱动的选择机制。每个板级 .c 文件整体包裹在 #ifdef CONFIG_BOARD_XXX 中,编译时只展开被选中的板级文件,未选中的板级代码不参与链接,从根源上避免引脚冲突与资源浪费。
  3. 宏配置 → 平台数据结构 → 驱动消费的三层解耦。cfg.h 中定义 TCFG_* 宏(纯文本、易读、易改);板级 .c 文件把宏组装进带类型的平台数据结构(如 struct low_power_param、UART0_PLATFORM_DATA 等);驱动与系统服务只读取这些结构体,不直接感知宏名。这样硬件变更(改引脚、改波特率、关外设)只需编辑 cfg.h,无需触碰驱动代码。

以 apps/hid/board/bd19/board_ac6321a_demo.c 为例,一个板级文件通常包含:低功耗参数、串口打印参数、充电参数、AD/IO 按键映射、端口唤醒配置,以及 board_power_init()、休眠/唤醒回调、软关机处理等函数,全部由 TCFG_* 宏驱动。

Architecture

下图展示板级工程的整体架构:CONFIG_BOARD_* 宏选择板级组合,cfg.h 提供 TCFG_* 配置,板级 .c 文件将其组装为平台数据结构并注册给驱动与电源管理模块。

flowchart TD
    subgraph sg_Build["编译期选择"]
        BuildCfg["board_*_global_build_cfg.h<br/>CONFIG_BOARD_XXX 定义"]
        BoardC["board_*_demo.c<br/>(#ifdef CONFIG_BOARD_XXX 包裹)"]
    end

    subgraph sg_Cfg["配置层 cfg.h"]
        CfgH["board_*_cfg.h<br/>TCFG_* 宏: UART/SPI/IIC/Flash/Key/Charge/低功耗"]
    end

    subgraph sg_Data["平台数据结构 (board .c)"]
        PowerParam["power_param<br/>struct low_power_param"]
        UartData["uart0_data<br/>UART0_PLATFORM_DATA"]
        ChargeData["charge_data<br/>CHARGE_PLATFORM_DATA"]
        KeyData["adkey_data / iokey_list<br/>AD 按键 / IO 按键"]
        WkParam["wk_param + port_wakeup<br/>唤醒口配置"]
    end

    subgraph sg_Init["初始化与回调"]
        BoardPowerInit["board_power_init()<br/>power_init / power_wakeup_init"]
        SleepCb["sleep_enter/sleep_exit_callback<br/>board_set_soft_poweroff"]
    end

    subgraph sg_Drv["驱动与系统服务"]
        PowerMod["电源管理 power 模块"]
        UartDrv["UART 驱动"]
        ChargeDrv["充电 chargestore 驱动"]
        KeyDrv["按键 key_driver"]
        WkupMod["唤醒 wakeup 模块"]
    end

    BuildCfg -->|"定义 CONFIG_BOARD_XXX"| BoardC
    BoardC -->|"引用"| CfgH
    CfgH -->|"TCFG_* 宏填充"| PowerParam
    CfgH -->|"TCFG_* 宏填充"| UartData
    CfgH -->|"TCFG_* 宏填充"| ChargeData
    CfgH -->|"TCFG_* 宏填充"| KeyData
    CfgH -->|"TCFG_* 宏填充"| WkParam
    PowerParam --> BoardPowerInit
    BoardPowerInit -->|"power_init()"| PowerMod
    BoardPowerInit -->|"power_wakeup_init()"| WkupMod
    BoardPowerInit -->|"power_set_callback()"| SleepCb
    UartData -->|"平台数据注册"| UartDrv
    ChargeData -->|"平台数据注册"| ChargeDrv
    KeyData -->|"平台数据注册"| KeyDrv
    WkParam --> WkupMod

架构分层解读:

  • 编译期选择层:global_build_cfg.h 决定某个板级组合是否参与编译(定义 CONFIG_BOARD_AC6321A_DEMO 等宏);板级 .c 文件以此宏作为整文件的条件编译开关。
  • 配置层(cfg.h):全部 TCFG_* 宏集中在此,是开发者日常修改的主要入口。宏使用 ENABLE_THIS_MOUDLE(1)/ DISABLE_THIS_MOUDLE(0)/ NO_CONFIG_PORT(-1)作为统一开关约定。
  • 平台数据结构层:板级 .c 文件用宏填充系统定义的结构体。这一层是「配置」与「驱动」的适配边界:结构体类型由 SDK 系统头文件定义,字段含义由驱动约定。
  • 初始化与回调层:board_power_init() 在系统启动早期被调用,完成电源参数注册、唤醒口注册、休眠/唤醒/软关机回调挂接。
  • 驱动消费层:UART、充电、按键、唤醒等模块从平台数据中读取实际硬件参数,对上层应用透明。

各芯片系列板级文件一览(apps/hid/board/):

系列代表芯片板级项目示例
bd19AC6321A / AC6323A / AC6328A / AC6328B / AC6329B/C/E/F / AC632Ndemo、mouse、stand_keyboard、keyfob
bd29AC631Ndemo
br23AC6351D / AC635Ndemo、keyboard
br25AC6363F / AC6366C / AC6368A / AC6368Bdemo、mouse、keyfob

板级文件三件套详解

每个板级组合由三个文件构成,职责边界清晰:

文件职责典型内容
board_<chip>_<project>.c板级实现:平台数据结构 + 初始化函数 + 回调低功耗参数、UART/充电平台数据、AD/IO 按键表、唤醒口、board_power_init()、休眠回调
board_<chip>_<project>_cfg.h板级配置:全部 TCFG_* 宏外设使能开关、引脚选择、速率/通道/按键值等
board_<chip>_<project>_global_build_cfg.h编译配置:芯片/板级宏定义决定 CONFIG_BOARD_XXX 是否生效

以 bd19 系列的 board_ac6321a_demo.c 为例,文件整体结构为:

#include "app_config.h"

#ifdef CONFIG_BOARD_AC6321A_DEMO

#include "system/includes.h"
#include "device/key_driver.h"
#include "asm/chargestore.h"
#include "asm/charge.h"
#include "rtc_alarm.h"
#include "asm/pwm_led.h"
#include "user_cfg.h"
#include "usb/otg.h"
#include "norflash.h"
#include "asm/power/p33.h"
#include "ex_mcu_uart.h"

#define LOG_TAG_CONST       BOARD
#define LOG_TAG             "[BOARD]"
...
void board_power_init(void);

Source: board_ac6321a_demo.c

设计意图说明:

  • #ifdef CONFIG_BOARD_AC6321A_DEMO 整文件包裹:这是板级选择机制的基石。app_config.h(经构建系统配置)定义了当前工程的板级宏,只有匹配的板级 .c 文件会被编译。由于每个板级文件都自带 LOG_TAG "[BOARD]",同一芯片多板共存时日志也能区分来源。
  • 头文件按需包含:板级文件不包含全部 SDK 头文件,而是按实际用到的平台数据结构(充电、按键、唤醒、电源等)逐个包含,降低编译耦合。
  • 前向声明 void board_power_init(void);:该函数由系统启动流程调用,板级文件只负责实现,不负责调度。

编译选择机制(CONFIG_BOARD_*)

每个板级 .c 文件的编译与否,取决于全局构建配置是否定义了对应的 CONFIG_BOARD_* 宏。global_build_cfg.h 就是存放这些选择的地方。例如 bd19 系列为每个项目(demo/mouse/keyfob 等)分别维护 board_*_global_build_cfg.h,其中定义 CONFIG_BOARD_AC6321A_DEMO 之类宏后,对应 .c 才会被编译、对应 cfg.h 才会被引用。

#ifndef CONFIG_BOARD_AC6321A_DEMO_H
#define CONFIG_BOARD_AC6321A_DEMO_H

#include "board_ac6321a_demo_global_build_cfg.h"

#ifdef CONFIG_BOARD_AC6321A_DEMO

#define CONFIG_SDFILE_ENABLE
...

Source: board_ac6321a_demo_cfg.h

注意 cfg.h 内部同样用 #ifdef CONFIG_BOARD_AC6321A_DEMO 包裹:宏定义与板级文件同步生效,保证「配置」和「实现」永远配套编译,不会出现 cfg.h 内容与 .c 内容脱节的情况。#define CONFIG_SDFILE_ENABLE 则展示了板级文件还可以直接向系统声明额外的功能使能(此处为文件系统/SD 卡支持),这类"板级级联使能"是 SDK 的常见扩展手法。

统一开关宏约定

cfg.h 顶部定义了三个语义化的开关宏,所有外设配置复用它们,保证可读性与一致性:

#define ENABLE_THIS_MOUDLE                  1
#define DISABLE_THIS_MOUDLE                 0

#define ENABLE                             1
#define DISABLE                            0

#define NO_CONFIG_PORT                      (-1)

Source: board_ac6321a_demo_cfg.h

  • ENABLE_THIS_MOUDLE / DISABLE_THIS_MOUDLE:模块级使能开关,用于 TCFG_UART0_ENABLE、TCFG_CHARGE_ENABLE 等整模块开关;
  • ENABLE / DISABLE:细粒度开关,用于组合按键 MULT_KEY_ENABLE 等子功能;
  • NO_CONFIG_PORT(-1):表示该引脚不配置,例如串口接收脚可设为 NO_CONFIG_PORT 以省脚位。

配置宏体系(cfg.h)详解

cfg.h 按外设分区块组织宏,是硬件移植的核心工作区。以下为 board_ac6321a_demo_cfg.h 中各区块及其含义。

UART 配置

#define TCFG_UART0_ENABLE                   ENABLE_THIS_MOUDLE                     //串口打印模块使能
#define TCFG_UART0_RX_PORT                  NO_CONFIG_PORT                         //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT)
#define TCFG_UART0_TX_PORT                  IO_PORTA_00                            //串口发送脚配置
#define TCFG_UART0_BAUDRATE                 1000000                                //串口波特率配置

Source: board_ac6321a_demo_cfg.h

设计意图:串口 0 同时承担调试打印功能。TCFG_UART0_RX_PORT 允许设为 NO_CONFIG_PORT,即只发不收的打印场景可释放 RX 脚。TCFG_UART0_BAUDRATE = 1000000 表明 SDK 默认调试波特率采用 1M(与官方调试工具配套)。

USB / OTG 配置

#define TCFG_PC_ENABLE                      DISABLE_THIS_MOUDLE //PC模块使能
#define TCFG_UDISK_ENABLE                   DISABLE_THIS_MOUDLE //U盘模块使能
#define TCFG_HID_HOST_ENABLE                DISABLE_THIS_MOUDLE//ENABLE_THIS_MOUDLE  //游戏盒子模式
#define TCFG_ADB_ENABLE                     DISABLE_THIS_MOUDLE//ENABLE_THIS_MOUDLE
#define TCFG_AOA_ENABLE                     DISABLE_THIS_MOUDLE//ENABLE_THIS_MOUDLE

#define TCFG_OTG_USB_DEV_EN                 (BIT(0) | BIT(1))//USB0 = BIT(0)  USB1 = BIT(1)

Source: board_ac6321a_demo_cfg.h

TCFG_OTG_USB_DEV_EN 用位掩码选择启用哪一路 USB 控制器(BIT(0)=USB0,BIT(1)=USB1),这是 SDK 中「多实例外设按位使能」的典型写法。注释中保留的 //ENABLE_THIS_MOUDLE 是官方演示「如何快速切换某功能」的惯用法——被注释的备选值便于来回切换,无需查询文档。

IIC 配置(软件/硬件双通道)

/*软件IIC设置*/
#define TCFG_SW_I2C0_CLK_PORT               IO_PORTA_09                             //软件IIC  CLK脚选择
#define TCFG_SW_I2C0_DAT_PORT               IO_PORTA_10                             //软件IIC  DAT脚选择
#define TCFG_SW_I2C0_DELAY_CNT              50                                      //IIC延时参数,影响通讯时钟频率

/*硬件IIC端口选择
  SCL         SDA
  'A': IO_PORT_DP   IO_PORT_DM
  'B': IO_PORTA_09  IO_PORTA_10
  'C': IO_PORTA_07  IO_PORTA_08
  'D': IO_PORTA_05  IO_PORTA_06
 */
#define TCFG_HW_I2C0_PORTS                  'B'
#define TCFG_HW_I2C0_CLK                    100000                                  //硬件IIC波特率

Source: board_ac6321a_demo_cfg.h

设计意图:同时提供软件 IIC(任意 GPIO 模拟,TCFG_SW_I2C0_DELAY_CNT 调节时序)与硬件 IIC(固定端口组,通过 'A'/'B'/'C'/'D' 字符宏选择 SCL/SDA 组合)。硬件 IIC 端口由芯片映射决定,因此 cfg.h 用注释直接列出可用组合,防止开发者配置到不存在的映射。

硬件 SPI 配置(多实例)

#define TCFG_HW_SPI1_ENABLE                 ENABLE_THIS_MOUDLE
//A组IO:    DI: PB2     DO: PB1     CLK: PB0
//B组IO:    DI: PC3     DO: PC5     CLK: PC4
#define TCFG_HW_SPI1_PORT                   'A'
#define TCFG_HW_SPI1_BAUD                   2000000L
#define TCFG_HW_SPI1_MODE                   SPI_MODE_BIDIR_1BIT
#define TCFG_HW_SPI1_ROLE                   SPI_ROLE_MASTER

#define TCFG_HW_SPI2_ENABLE                 ENABLE_THIS_MOUDLE
//A组IO:    DI: PB8     DO: PB10    CLK: PB9
//B组IO:    DI: PA13    DO: DM      CLK: DP
#define TCFG_HW_SPI2_PORT                   'A'
#define TCFG_HW_SPI2_BAUD                   2000000L
#define TCFG_HW_SPI2_MODE                   SPI_MODE_BIDIR_1BIT
#define TCFG_HW_SPI2_ROLE                   SPI_ROLE_MASTER

Source: board_ac6321a_demo_cfg.h

SPI1/SPI2 共用同一套 _PORT/_BAUD/_MODE/_ROLE 参数模板,注释同样给出各端口组的引脚映射。SPI_MODE_BIDIR_1BIT 与 SPI_ROLE_MASTER 表明 SDK 以主模式、双向 1 线方式驱动片外 SPI 器件(如 Flash)。

Flash 配置

#define TCFG_CODE_FLASH_ENABLE              DISABLE_THIS_MOUDLE
#define TCFG_FLASH_DEV_SPI_HW_NUM           1// 1: SPI1    2: SPI2
#define TCFG_FLASH_DEV_SPI_CS_PORT          IO_PORTB_06
#define TCFG_NORFLASH_DEV_ENABLE            DISABLE_THIS_MOUDLE

Source: board_ac6321a_demo_cfg.h

TCFG_FLASH_DEV_SPI_HW_NUM 选择挂载 Flash 的硬件 SPI 实例(1=SPI1),TCFG_FLASH_DEV_SPI_CS_PORT 指定片选脚——片选脚是 GPIO 而非 SPI 专用脚,因此单独配置。

按键配置(IO 键 / AD 键)

#define KEY_NUM_MAX                         10
#define KEY_NUM                             3

#define MULT_KEY_ENABLE                     DISABLE       //是否使能组合按键消息, 使能后需要配置组合按键映射表
//...
#define TCFG_IOKEY_ENABLE                   DISABLE_THIS_MOUDLE //是否使能IO按键
#define TCFG_IOKEY_POWER_CONNECT_WAY        ONE_PORT_TO_LOW    //按键一端接低电平一端接IO
#define TCFG_IOKEY_POWER_ONE_PORT           IO_PORTB_01        //IO按键端口
//...
#define TCFG_ADKEY_ENABLE                   ENABLE_THIS_MOUDLE //是否使能AD按键
#define TCFG_ADKEY_PORT                     IO_PORTB_01         //AD按键端口(需要注意选择的IO口是否支持AD功能)
#define TCFG_ADKEY_AD_CHANNEL               AD_CH_PB1
#define TCFG_ADKEY_EXTERN_UP_ENABLE         ENABLE_THIS_MOUDLE //是否使用外部上拉

Source: board_ac6321a_demo_cfg.h

  • KEY_NUM_MAX / KEY_NUM:按键表容量与按键数量上限;
  • IO 键:TCFG_IOKEY_*_CONNECT_WAY 描述按键接法(一端接低电平 ONE_PORT_TO_LOW),*_ONE_PORT 指定引脚;
  • AD 键:一个 ADC 通道经分压电阻可扩展出多个键值(TCFG_ADKEY_AD_CHANNEL 与端口需匹配,注释列出所有可用 AD 通道),TCFG_ADKEY_EXTERN_UP_ENABLE 决定是否外接上拉。

平台数据结构(board .c)详解

cfg.h 的宏最终在板级 .c 文件中被组装为带类型的平台数据结构。以下逐一说明。

低功耗参数 power_param

const struct low_power_param power_param = {
    .config         = TCFG_LOWPOWER_LOWPOWER_SEL,          //0:sniff时芯片不进入低功耗  1:sniff时芯片进入powerdown
    .btosc_hz       = TCFG_CLOCK_OSC_HZ,                   //外接晶振频率
    .delay_us       = TCFG_CLOCK_SYS_HZ / 1000000L,        //提供给低功耗模块的延时(不需要需修改)
    .btosc_disable  = TCFG_LOWPOWER_BTOSC_DISABLE,         //进入低功耗时BTOSC是否保持
    .vddiom_lev     = TCFG_LOWPOWER_VDDIOM_LEVEL,          //强VDDIO等级,可选:2.0V  2.2V  2.4V  2.6V  2.8V  3.0V  3.2V  3.6V
    .vddiow_lev     = TCFG_LOWPOWER_VDDIOW_LEVEL,          //弱VDDIO等级,可选:2.1V  2.4V  2.8V  3.2V
    .osc_type       = TCFG_LOWPOWER_OSC_TYPE,
    .lpctmu_en      = TCFG_LP_TOUCH_KEY_ENABLE,
    .vd13_cap_en    = TCFG_VD13_CAP_EN,
};

Source: board_ac6321a_demo.c

设计意图:低功耗参数与芯片电源域强相关。config 字段决定 sniff 期间是否进入 powerdown(0/1 两档);vddiom_lev/vddiow_lev 分别配置强/弱 VDDIO 电压等级,直接决定休眠电流与 IO 驱动能力——这是蓝牙低功耗产品的核心调参项。delay_us 用系统主频宏自动推导(TCFG_CLOCK_SYS_HZ / 1000000L),避免手动换算引入误差。

UART 平台数据(宏生成结构体)

#if TCFG_UART0_ENABLE
UART0_PLATFORM_DATA_BEGIN(uart0_data)
    .tx_pin = TCFG_UART0_TX_PORT,                             //串口打印TX引脚选择
    .rx_pin = TCFG_UART0_RX_PORT,                             //串口打印RX引脚选择
    .baudrate = TCFG_UART0_BAUDRATE,                          //串口波特率

    .flags = UART_DEBUG,                                      //串口用来打印需要把改参数设置为UART_DEBUG
UART0_PLATFORM_DATA_END()
#endif //TCFG_UART0_ENABLE

Source: board_ac6321a_demo.c

UART0_PLATFORM_DATA_BEGIN/END 是 SDK 的宏生成器:自动为串口 0 生成带实例名的平台数据结构并注册到 UART 框架。.flags = UART_DEBUG 将串口 0 标记为调试口,系统 log_info/putchar 即走此口。整段由 TCFG_UART0_ENABLE 条件编译——配置关掉后平台数据不复存在,串口驱动完全不感知。

充电平台数据

#if TCFG_CHARGE_ENABLE
CHARGE_PLATFORM_DATA_BEGIN(charge_data)
    .charge_en              = TCFG_CHARGE_ENABLE,              //内置充电使能
    .charge_poweron_en      = TCFG_CHARGE_POWERON_ENABLE,      //是否支持充电开机
    .charge_full_V          = TCFG_CHARGE_FULL_V,              //充电截止电压
    .charge_full_mA         = TCFG_CHARGE_FULL_MA,             //充电截止电流
    .charge_mA              = TCFG_CHARGE_MA,                  //充电电流
/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出
 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的充电,需要根据实际情况设置该值大小*/
    .ldo5v_off_filter      = 100,
    .ldo5v_on_filter       = 50,
    .ldo5v_keep_filter     = 220,
    .ldo5v_pulldown_lvl    = CHARGE_PULLDOWN_200K,            //下拉电阻档位选择
    .ldo5v_pulldown_keep   = 1,
    .ldo5v_pulldown_en     = 1,
CHARGE_PLATFORM_DATA_END()
#endif//TCFG_CHARGE_ENABLE

Source: board_ac6321a_demo.c

充电配置是所有 TWS/耳机/遥控器产品的核心。ldo5v_* 系列字段解决「充电仓检测」这一经典难题:注释明确说明过滤时间公式 (filter*2 + 20)ms,以及不同充电仓行为(充满直接掉到 0V vs. 先掉 0V 再升压)需要不同的过滤值;ldo5v_pulldown_* 配置 LDOIN 检测所需的下拉电阻档位(如 CHARGE_PULLDOWN_200K)与维持策略。这些注释直接沉淀了硬件调试经验,是板级工程文档化的最佳实践。

AD 按键平台数据

const struct adkey_platform_data adkey_data = {
    .enable = TCFG_ADKEY_ENABLE,                              //AD按键使能
    .adkey_pin = TCFG_ADKEY_PORT,                             //AD按键对应引脚
    .ad_channel = TCFG_ADKEY_AD_CHANNEL,                      //AD通道值
    .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE,              //是否使用外接上拉电阻
    .ad_value = {                                             //根据电阻算出来的电压值
        TCFG_ADKEY_VOLTAGE0,
        TCFG_ADKEY_VOLTAGE1,
        ...
    },
    .key_value = {                                             //AD按键各个按键的键值
        TCFG_ADKEY_VALUE0,
        TCFG_ADKEY_VALUE1,
        ...
    },
};

Source: board_ac6321a_demo.c

AD 按键的本质是「电阻分压 → ADC 采样 → 电压档位 → 键值」的查表映射:ad_value[] 是从分压电阻网络算出的各档位电压,key_value[] 是对应键值,两者按数组下标一一对应。开发者改硬件电阻网络时只需同步更新 TCFG_ADKEY_VOLTAGEx / TCFG_ADKEY_VALUEx 宏组,驱动逻辑零改动。

唤醒口配置 wk_param

struct port_wakeup vbat_port = {
    .edge               = BOTH_EDGE,                      //唤醒方式选择,可选:上升沿\下降沿\双边沿
    .both_edge          = 1,
    .filter             = PORT_FLT_16ms,
    .iomap              = IO_VBTCH_DET,                      //唤醒口选择
};

const struct wakeup_param wk_param = {
#if TCFG_ADKEY_ENABLE || TCFG_IOKEY_ENABLE
    .port[1]    = &port0,
#endif
#if TCFG_TEST_BOX_ENABLE
    .port[2] = &port1,
#endif
#if TCFG_CHARGE_ENABLE
    .aport[0] = &charge_port,
    .aport[1] = &vbat_port,
    .aport[2] = &ldoin_port,
#endif
};

Source: board_ac6321a_demo.c

唤醒配置分两类:数字口唤醒(port[],边沿触发 + 滤波)与模拟口唤醒(aport[],充电检测/电池检测/插入检测)。PORT_FLT_16ms 表示 16ms 硬件滤波,用于抑制机械抖动与电源噪声。wk_param 的成员同样由 TCFG_* 宏决定是否挂接——配置关掉的外设不会注册唤醒源,避免「未使用的引脚被意外唤醒」这类低功耗陷阱。

核心初始化流程(board_power_init 与电源管理)

板级工程的最终落点是 board_power_init()——系统启动早期由框架调用,把板级配置注册进电源管理模块。以下为 bd19 系列的实现:

void board_power_init(void)
{
    log_info("Power init : %s", __FILE__);

    power_init(&power_param);

    //< close short key reset
    /* power_mclr(0); */
    //< close long key reset
    /* power_pin_reset(0); */

    power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff);

//    wl_audio_clk_on();

    power_keep_dacvdd_en(0);

    power_wakeup_init(&wk_param);

    aport_edge_wkup_set_callback(aport_wakeup_callback);
    port_edge_wkup_set_callback(port_wakeup_callback);
}

Source: board_ac6321a_demo.c

执行顺序与设计意图:

  1. log_info("Power init : %s", __FILE__):打印板级文件名,便于确认当前编译进的是哪块板——多板工程排查的首个调试点;
  2. power_init(&power_param):注册低功耗参数(sniff 低功耗策略、VDDIO 等级、晶振频率等);
  3. 被注释的 power_mclr(0) / power_pin_reset(0):默认关闭短按复位与长按复位功能,避免按键误触复位——若产品需要按键复位可取消注释;
  4. power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff):挂接休眠进入/退出/软关机三个回调,且第一个参数复用低功耗选择宏,保证「不进入低功耗的模式不挂回调」;
  5. power_keep_dacvdd_en(0):低功耗时不保持 DACVDD,进一步省电(需确认硬件无外部依赖);
  6. power_wakeup_init(&wk_param):注册全部唤醒源(数字口 + 模拟口);
  7. aport_edge_wkup_set_callback / port_edge_wkup_set_callback:挂接模拟口/数字口边沿唤醒回调,把唤醒事件分发给充电检测(charge_wakeup_isr / ldoin_wakeup_isr)等处理函数。

休眠与软关机回调

void sleep_exit_callback(u32 usec)
{
    putchar('>');
    APP_IO_DEBUG_0(A, 5);
}

void sleep_enter_callback(u8  step)
{
    /* 此函数禁止添加打印 */
    if (step == 1) {
        putchar('<');
        APP_IO_DEBUG_1(A, 5);
        /*dac_power_off();*/
    } else {
        close_gpio();
    }
}

void board_set_soft_poweroff(void)
{
    log_info("%s", __FUNCTION__);
    mask_io_cfg();

#if TCFG_TEST_BOX_ENABLE
    power_wakeup_index_disable(2);
#endif

    close_gpio();
}

Source: board_ac6321a_demo.c

  • sleep_enter_callback 按 step 分阶段执行:step == 1 只做轻量动作(打印 '<' 与 IO 翻转,用于逻辑分析仪观测),后续步骤才 close_gpio() 关闭全部 GPIO。注释「此函数禁止添加打印」是因为进入深度休眠后打印本身可能触发外设活动,破坏休眠时序。
  • board_set_soft_poweroff 是软关机路径:先 mask_io_cfg() 屏蔽 IO 配置,测试盒模式(TCFG_TEST_BOX_ENABLE)下还需禁用对应唤醒索引,最后 close_gpio() 将 IO 全部置为高阻——确保关机后无漏电通路。
  • APP_IO_DEBUG_* 宏默认被注释为空操作,仅保留给调试期放开使用,避免生产代码携带多余 IO 翻转。

启动到驱动注册的完整时序

sequenceDiagram
    participant Boot as 系统启动/框架
    participant BoardC as board_*.c<br/>(CONFIG_BOARD_XXX 选中)
    participant CfgH as board_*_cfg.h<br/>(TCFG_* 宏)
    participant Power as 电源管理模块
    participant Uart as UART 驱动
    participant Charge as chargestore 驱动
    participant Key as key_driver
    participant Wkup as 唤醒模块

    Note over Boot,CfgH: 编译期: CONFIG_BOARD_* 决定 .c/.h 是否参与编译
    Boot->>BoardC: 调用 board_power_init()
    BoardC->>CfgH: 读取 TCFG_* 宏
    BoardC->>Power: power_init(&power_param)
    BoardC->>Power: power_set_callback(... 休眠/软关机回调)
    BoardC->>Wkup: power_wakeup_init(&wk_param)
    BoardC->>Wkup: 注册 port/aport 唤醒回调
    BoardC-->>Uart: uart0_data 平台数据 (UART0_PLATFORM_DATA_BEGIN)
    BoardC-->>Charge: charge_data 平台数据 (CHARGE_PLATFORM_DATA_BEGIN)
    BoardC-->>Key: adkey_data / iokey_list 平台数据
    Power-->>Boot: 电源参数就绪
    Note over Power,Wkup: 运行期: 按键/充电/唤醒事件经回调<br/>分发到对应驱动处理

该时序揭示板级工程在系统生命周期中的位置:它是启动早期第一个被调用的应用侧适配层,其产物(平台数据结构)在后续驱动初始化时被消费;运行期的低功耗、唤醒、充电检测等事件也经由板级注册的回调进入系统处理。

使用示例

示例 1:为一块新板子启用串口打印并调整波特率

修改 board_<chip>_<project>_cfg.h 中的 UART 区块:

#define TCFG_UART0_ENABLE                   ENABLE_THIS_MOUDLE                     //串口打印模块使能
#define TCFG_UART0_RX_PORT                  NO_CONFIG_PORT                         //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT)
#define TCFG_UART0_TX_PORT                  IO_PORTA_00                            //串口发送脚配置
#define TCFG_UART0_BAUDRATE                 1000000                                //串口波特率配置

Source: board_ac6321a_demo_cfg.h

示例 2:调整低功耗与唤醒策略

低功耗参数在 board_<chip>_<project>.c 中定义,由 TCFG_LOWPOWER_* 宏驱动:

const struct low_power_param power_param = {
    .config         = TCFG_LOWPOWER_LOWPOWER_SEL,          //0:sniff时芯片不进入低功耗  1:sniff时芯片进入powerdown
    .btosc_hz       = TCFG_CLOCK_OSC_HZ,                   //外接晶振频率
    .delay_us       = TCFG_CLOCK_SYS_HZ / 1000000L,        //提供给低功耗模块的延时(不需要需修改)
    .btosc_disable  = TCFG_LOWPOWER_BTOSC_DISABLE,         //进入低功耗时BTOSC是否保持
    .vddiom_lev     = TCFG_LOWPOWER_VDDIOM_LEVEL,          //强VDDIO等级,可选:2.0V  2.2V  2.4V  2.6V  2.8V  3.0V  3.2V  3.6V
    .vddiow_lev     = TCFG_LOWPOWER_VDDIOW_LEVEL,          //弱VDDIO等级,可选:2.1V  2.4V  2.8V  3.2V
    .osc_type       = TCFG_LOWPOWER_OSC_TYPE,
    .lpctmu_en      = TCFG_LP_TOUCH_KEY_ENABLE,
    .vd13_cap_en    = TCFG_VD13_CAP_EN,
};

Source: board_ac6321a_demo.c

示例 3:自定义软关机动作

软关机时默认将 IO 全部置为高阻;需要在关机前保存状态或驱动特定外设时,修改 board_set_soft_poweroff():

void board_set_soft_poweroff(void)
{
    log_info("%s", __FUNCTION__);
    mask_io_cfg();

#if TCFG_TEST_BOX_ENABLE
    power_wakeup_index_disable(2);
#endif

    close_gpio();
}

Source: board_ac6321a_demo.c

配置选项速查

以下为 board_ac6321a_demo_cfg.h 中经核实的核心配置宏(不同芯片/项目板的宏集合以此为基础增减):

配置宏类型默认值(demo 板)说明
TCFG_UART0_ENABLEintENABLE_THIS_MOUDLE串口打印模块使能
TCFG_UART0_RX_PORTIONO_CONFIG_PORT串口 RX 脚,打印场景可省
TCFG_UART0_TX_PORTIOIO_PORTA_00串口 TX 脚
TCFG_UART0_BAUDRATEint1000000调试波特率
TCFG_PC_ENABLEintDISABLE_THIS_MOUDLEPC 透传模块使能
TCFG_UDISK_ENABLEintDISABLE_THIS_MOUDLEU 盘模块使能
TCFG_HID_HOST_ENABLEintDISABLE_THIS_MOUDLEHID Host(游戏盒子)使能
TCFG_ADB_ENABLEintDISABLE_THIS_MOUDLEADB 使能
TCFG_AOA_ENABLEintDISABLE_THIS_MOUDLEAOA(Android Open Accessory)使能
TCFG_OTG_USB_DEV_ENintBIT(0) | BIT(1)启用的 USB 控制器位掩码
TCFG_SW_I2C0_CLK_PORTIOIO_PORTA_09软件 IIC CLK 脚
TCFG_SW_I2C0_DAT_PORTIOIO_PORTA_10软件 IIC DAT 脚
TCFG_SW_I2C0_DELAY_CNTint50软件 IIC 延时(影响时钟频率)
TCFG_HW_I2C0_PORTSchar'B'硬件 IIC 端口组(A/B/C/D)
TCFG_HW_I2C0_CLKint100000硬件 IIC 波特率
TCFG_HW_SPI1_ENABLEintENABLE_THIS_MOUDLESPI1 使能
TCFG_HW_SPI1_PORTchar'A'SPI1 端口组
TCFG_HW_SPI1_BAUDlong2000000LSPI1 波特率
TCFG_HW_SPI1_MODEenumSPI_MODE_BIDIR_1BITSPI1 工作模式
TCFG_HW_SPI1_ROLEenumSPI_ROLE_MASTERSPI1 主从角色
TCFG_HW_SPI2_*—同 SPI1SPI2 同构参数组
TCFG_CODE_FLASH_ENABLEintDISABLE_THIS_MOUDLE代码 Flash 使能
TCFG_FLASH_DEV_SPI_HW_NUMint1Flash 挂载的硬件 SPI(1/2)
TCFG_FLASH_DEV_SPI_CS_PORTIOIO_PORTB_06Flash 片选脚
TCFG_NORFLASH_DEV_ENABLEintDISABLE_THIS_MOUDLENOR Flash 设备使能
KEY_NUM_MAXint10按键表容量上限
KEY_NUMint3实际按键数量
MULT_KEY_ENABLEintDISABLE组合按键消息使能
TCFG_IOKEY_ENABLEintDISABLE_THIS_MOUDLEIO 按键使能
TCFG_IOKEY_*_CONNECT_WAYenumONE_PORT_TO_LOWIO 键接法
TCFG_IOKEY_*_ONE_PORTIO各键不同IO 键引脚
TCFG_ADKEY_ENABLEintENABLE_THIS_MOUDLEAD 按键使能
TCFG_ADKEY_PORTIOIO_PORTB_01AD 键引脚
TCFG_ADKEY_AD_CHANNELenumAD_CH_PB1AD 通道(须与引脚匹配)
TCFG_ADKEY_EXTERN_UP_ENABLEintENABLE_THIS_MOUDLE外接上拉使能
TCFG_CHARGE_ENABLEint见板文件内置充电使能
TCFG_LOWPOWER_LOWPOWER_SELint见板文件sniff 低功耗模式选择
TCFG_LOWPOWER_VDDIOM_LEVELenum见板文件强 VDDIO 等级
TCFG_LOWPOWER_VDDIOW_LEVELenum见板文件弱 VDDIO 等级
TCFG_LOWPOWER_OSC_TYPEenum见板文件低功耗振荡器类型
TCFG_TEST_BOX_ENABLEint见板文件测试盒模式(影响唤醒配置)

注:TCFG_CHARGE_*、TCFG_LOWPOWER_*、TCFG_ADKEY_VOLTAGE*/VALUE* 等宏定义于 cfg.h 的后续区块(本页读取片段之外),其取值方式与上表同类宏一致。

失败模式、边界情况与并发/时序注意点

基于板级源码的实际实现,以下问题在移植与调试中最常见:

失败模式根因板级应对手段
引脚冲突/外设不工作多块板级文件同时编译或引脚配置与硬件不符CONFIG_BOARD_* 条件编译保证同时只有一块板生效;cfg.h 注释直接列出各端口组可用映射
休眠电流偏大VDDIO 等级、下拉电阻或唤醒源配置不当power_param.vddiom/vddiow_lev 分级可调;ldo5v_pulldown_* 与 power_keep_dacvdd_en(0) 关闭无关电源域
无法唤醒/误唤醒唤醒边沿、滤波时间或唤醒源未注册port_wakeup 配置 edge/filter;wk_param 成员按 TCFG_* 条件注册,未使能外设不挂唤醒源
充电仓检测异常LDOIN 拔插滤波值不匹配仓体行为ldo5v_off/on/keep_filter 按注释公式 (filter*2+20)ms 调整
软关机漏电IO 未置高阻board_set_soft_poweroff() 内 mask_io_cfg() + close_gpio()
打印异常/无日志调试口配置与工具不匹配TCFG_UART0_BAUDRATE 与 UART_DEBUG 标志需配套

时序/并发注意点:

  • sleep_enter_callback 明确标注「此函数禁止添加打印」,说明休眠临界区不允许任何可能唤醒外设的操作;回调执行顺序(step 分级)不可重排。
  • board_set_soft_poweroff() 中 power_wakeup_index_disable(2) 必须在 close_gpio() 之前执行——先摘除唤醒源再关 IO,否则关闭 IO 的动作可能触发边沿中断造成竞态。
  • wk_param 的 port[] 与 aport[] 下标由条件编译决定(port[1]、port[2] 在不同配置下含义不同),新增唤醒源时必须与 power_wakeup_index_disable() 的索引约定保持一致。
  • 板级平台数据结构多为 const(如 power_param、adkey_data),运行期只读,天然避免多线程写竞争;可变状态集中在回调与电源模块内部管理。

性能与运维注意点

  • 编译期裁剪:TCFG_* 模块开关直接决定平台数据是否生成,未使能模块的驱动代码不链接,同时节省 ROM 与启动初始化时间。
  • 调试口复用:UART_DEBUG 标志让串口 0 兼任打印口,量产时可通过配置切换为普通功能口,无需改驱动。
  • 日志分级:板级文件启用 LOG_ERROR/DEBUG/INFO,默认关闭 LOG_DUMP;排查低功耗时序时可放开 LOG_DUMP_ENABLE 观察更细粒度日志,量产前应恢复。
  • 电源参数是硬件强相关项:vddiom_lev/vddiow_lev/晶振频率改动前必须核对芯片数据手册与原理图,错误配置可能导致休眠唤醒异常或 IO 电平不达标。

扩展点:如何新增一块板级工程

  1. 复制模板:以同系列最近的板级文件为模板,复制 board_<chip>_<project>.c、board_<chip>_<project>_cfg.h、board_<chip>_<project>_global_build_cfg.h 三件套;
  2. 定义板级宏:在 global_build_cfg.h 中定义新的 CONFIG_BOARD_<NEW>,并确保同一时间只定义一个板级宏(或由构建脚本选择);
  3. 修改 cfg.h:按硬件原理图配置 TCFG_* 引脚、速率、使能开关;引脚映射以 cfg.h 注释为准;
  4. 调整 .c 平台数据:power_param 低功耗参数、wk_param 唤醒源、按键表按实际电路修改;
  5. 接入启动:确认系统启动流程会调用新板的 board_power_init()(若框架按板级宏分发,则无需改动);
  6. 验证:先确认 log_info("Power init : %s", __FILE__) 打印的是新板文件名,再逐项验证打印、按键、充电、休眠唤醒。

测试与验证要点

板级层没有独立单元测试,验证依赖硬件实测与日志观测:

  • 编译选择验证:启动日志中的板级文件名(log_info("Power init : %s", __FILE__))是「当前编译进哪块板」的直接证据;
  • 休眠波形验证:APP_IO_DEBUG_* 宏放开后可用逻辑分析仪观测 '<'/'>' 时刻的 IO 翻转,确认进出休眠的时序;
  • 唤醒源验证:port_wakeup_callback/aport_wakeup_callback 中保留的注释日志可放开,确认充电/按键/插入事件的唤醒分发路径;
  • 充电参数验证:ldo5v_*_filter 需配合真实充电仓实测拔插判定时间(公式 (filter*2+20)ms)。

Related Links

  • 板级工程源文件目录(apps/hid/board)
  • board_ac6321a_demo.c(bd19 板级实现示例)
  • board_ac6321a_demo_cfg.h(bd19 板级配置示例)
  • board_ac6321a_demo_global_build_cfg.h(编译选择配置)
  • 同系列其他板级示例:apps/hid/board/bd19/board_ac6328a_keyfob.c、apps/hid/board/br23/board_ac6351d_keyboard.c、apps/hid/board/br25/board_ac6366c_demo.c 等
  • 相关专题(见对应目录页):SDK 构建与工程模板(Getting Started)、UART/SPI/IIC/Flash 驱动、低功耗协议栈
Prev
编译构建系统
Next
烧录与固件升级工具