杰理 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 蓝牙 SDK 中负责调试输出、断言处理和编译期调试开关的公共基础模块,覆盖 apps/common/debug/debug.c 调试输出层、各 CPU 的 asm/debug.h 调试入口以及板级构建配置与调试固件。

Purpose and Scope

本页面向 8-common-components/8.4-debug-config 目录,说明 SDK 中「调试与配置」这一公共能力的完整机制,包括:

  • 调试输出层的桩函数实现(apps/common/debug/debug.c)及其编译期开关语义;
  • 各 CPU 家族(bd19/bd29/br23/br25/br30/br34)统一的调试入口 debug_init() 与异常解析入口 exception_analyze();
  • 控制调试行为的配置宏 CONFIG_DEBUG_ENABLE、CONFIG_DEBUG_LITE_ENABLE;
  • 板级构建配置头文件与 CPU tools 目录下的调试固件(如 ota_debug.bin)。

以下内容属于兄弟页面、不在本页展开:具体板级的引脚/UART 配置(见板级 Board 配置相关页面)、OTA 升级机制(见 OTA 相关页面)、各外设驱动的配置(见对应驱动页面)。

Overview

AC63 BT SDK 的调试机制有一个鲜明特征:调试开关是编译期决定、运行期零开销的。整个 apps/common/debug/debug.c 文件被 #ifndef CONFIG_DEBUG_ENABLE 包裹——当该宏未定义(即发布版构建)时,编译器编译的是一组空壳桩函数(printf、puts、putchar、put_buf、put_u8hex、put_u16hex、put_u32hex、log_print、log_putbyte 全部为空实现),这些空函数会被优化器直接消除,不给固件增加任何代码体积与运行开销;当该宏已定义(调试版构建)时,真实调试输出实现由预编译驱动库提供(本仓库源码中不包含该分支实现)。

设计意图非常明确:

  1. 零成本发布:发布版固件不含任何调试字符串与输出路径,避免泄露调试信息、减小 flash 占用;
  2. 统一调用接口:应用层始终可以调用 printf/log_print 等标准接口,无需为调试/发布写两套代码;
  3. 断言永远生效:assert_printf 是桩文件中唯一「有实际行为」的函数——即使调试输出被关闭,它仍然调用 cpu_assert_debug(),保证断言在任何构建下都能触发 CPU 的异常处理机制,这是嵌入式安全设计的关键。

同时,每个 CPU 家族在 include_lib/driver/cpu/<cpu>/asm/debug.h 中声明 debug_init()(初始化调试通道,如 UART)与 exception_analyze()(解析异常现场),部分 CPU 还提供 ram_protect_close()(关闭 RAM 保护以便调试探针访问)。CPU tools 目录下的 ota_debug.bin、uboot.boot_debug 等调试固件则用于新板 bring-up 阶段。

Architecture

flowchart TD
    subgraph sg_Build["编译期配置层"]
        CFG["app_config.h / board_*_cfg.h<br/>CONFIG_DEBUG_ENABLE<br/>CONFIG_DEBUG_LITE_ENABLE"]
    end

    subgraph sg_Debug["公共调试组件 apps/common/debug/debug.c"]
        STUB["printf / puts / putchar<br/>put_buf / put_u8hex / put_u16hex / put_u32hex<br/>log_print / log_putbyte 桩函数"]
        ASSERT["assert_printf"]
    end

    subgraph sg_Cpu["CPU 驱动层 include_lib/driver/cpu/*/asm/debug.h"]
        INIT["debug_init()"]
        EXC["exception_analyze()"]
        PROTECT["ram_protect_close()"]
    end

    subgraph sg_HW["CPU 调试硬件"]
        HW["UART 调试通道 / 异常捕获"]
    end

    CFG -->|"未定义 CONFIG_DEBUG_ENABLE"| STUB
    CFG -->|"已定义 CONFIG_DEBUG_ENABLE"| LIB["预编译库中的真实调试实现"]
    LIB --> HW
    STUB --> ASSERT
    ASSERT -->|"无条件调用"| HW
    INIT --> HW
    EXC --> HW
    PROTECT --> HW

架构说明

  • 编译期配置层:CONFIG_DEBUG_ENABLE 决定 debug.c 中编译的是桩函数还是(由预编译库提供的)真实实现;CONFIG_DEBUG_LITE_ENABLE 进一步裁剪掉 log_putbyte 字节级输出钩子,形成「精简调试模式」。这些宏一般在板级工程的构建配置(如 apps/hid/board/bd19/board_ac6321a_demo_cfg.h、board_ac6321a_demo_global_build_cfg.h)或 app_config.h 中定义。
  • 公共调试组件:唯一在发布构建中也参与编译的源码文件;其桩函数保持标准 C 函数签名,确保上层调用点不需要任何条件编译。
  • CPU 驱动层:调试硬件的初始化与异常分析按 CPU 家族分别实现(bd19、bd29、br23、br25、br30、br34 各有对应的 asm/debug.h),对外暴露统一的 debug_init() / exception_analyze() 接口。
  • 调试硬件:UART 是最常见的调试通道;cpu_assert_debug() 与 exception_analyze() 直接对接 CPU 的异常处理寄存器现场。

调试输出层实现(apps/common/debug/debug.c)

文件结构与编译开关

整个文件的结构是一个大的条件编译块:#ifndef CONFIG_DEBUG_ENABLE … #endif(第 6 行到第 63 行)。其含义是:只有当调试宏未定义时才编译这些桩函数。反之(宏已定义)时,链接器从预编译库中解析同名的真实符号,源码层无需任何改动。

#include "app_config.h"
#include "typedef.h"


#ifndef CONFIG_DEBUG_ENABLE

int putchar(int a)
{
    return a;
}

来源:debug.c

putchar 的桩实现返回传入参数本身,既满足 C 标准库对 putchar 的约定(返回写入的字符),又不会产生任何输出。puts 与 printf 返回 0,表示「成功但无输出」,调用方无需感知差异。

二进制/十六进制输出桩

void put_buf(const u8 *buf, int len)
{

}

void put_u8hex(u8 dat)
{

}

void put_u16hex(u16 dat)
{

}

void put_u32hex(u32 dat)
{

}

来源:debug.c

这组函数用于输出原始缓冲区与各宽度十六进制数值,是协议栈/驱动调试时最常用的辅助输出。发布版中它们为空函数,调用点被编译器完全消除。

分级日志接口 log_print

void log_print(int level, const char *tag, const char *format, ...)
{

}

来源:debug.c

log_print 是 SDK 的分级日志入口,level 表示日志级别(错误/警告/信息等),tag 标识日志来源模块,format 为格式化串。桩实现为空;真实实现(宏定义时)通常将日志按级别过滤并转发到 UART。level 与 tag 参数的存在说明库内真实实现支持按模块、按级别过滤,这是大型 SDK 调试的常见需求。

精简调试模式与 log_putbyte

#ifndef CONFIG_DEBUG_LITE_ENABLE
void log_putbyte(char c)
{

}
#endif /* #ifndef CONFIG_DEBUG_LITE_ENABLE */

来源:debug.c

log_putbyte 是字节级输出钩子,通常被底层驱动(如汇编级打印)调用。当定义 CONFIG_DEBUG_LITE_ENABLE 时,连这个钩子的桩都不编译——精简模式连字节级输出路径一并移除,进一步减小代码尺寸。这体现了 SDK 对 flash/ram 空间的精打细算:调试能力按需逐级裁剪。

断言处理 assert_printf

int assert_printf(const char *format, ...)
{
    cpu_assert_debug();

    return 0;
}

来源:debug.c

这是发布构建中唯一真正「做事」的函数:无论调试输出是否开启,断言触发时都会调用 cpu_assert_debug(),把 CPU 拉入异常处理流程(例如打印异常现场或进入死循环以便调试器抓取)。这是刻意的安全设计——断言不能因为关闭了日志就被静默吞掉。cpu_assert_debug() 由预编译驱动库提供,具体行为(停机、复位或进入调试模式)因 CPU 而异。

CPU 调试入口(include_lib/driver/cpu/*/asm/debug.h)

每个 CPU 家族在预编译驱动库的头文件中声明统一的调试接口。以 bd19 为例:

void ram_protect_close(void);
void debug_init();
void exception_analyze();

来源:debug.h (bd19)

各 CPU 的声明位置一致(bd29/br23/br25/br30/br34 的 asm/debug.h 中 debug_init() 与 exception_analyze() 均位于第 5-7 行或 14-15 行附近),汇总如下:

接口声明位置职责
void debug_init(void)全部 CPU(bd19/bd29/br23/br25/br30/br34)初始化调试通道(如调试 UART 引脚与波特率),应在系统启动早期调用
void exception_analyze(void)全部 CPU在异常/断言触发后解析 CPU 寄存器现场,输出崩溃信息(函数名、PC、栈等)
void ram_protect_close(void)bd29/br23/br25/br30/br34关闭 RAM 写保护,允许调试器/下载工具访问受保护内存区域

来源:debug.h (bd29)、debug.h (br25)

设计意图:把「硬件相关的调试初始化」和「与应用无关的异常分析」收敛到驱动库,应用层只依赖 debug_init()/exception_analyze() 两个稳定符号,便于跨 CPU 移植。ram_protect_close() 的存在说明 SDK 默认开启了 RAM 保护(防止野指针破坏关键数据),调试阶段需要显式关闭后才能用仿真器读写内存——这是量产安全与调试便利之间的一个折中。

核心编译流程

flowchart TD
    Start([编译应用工程]) --> Config{"CONFIG_DEBUG_ENABLE<br/>是否已定义?"}
    Config -->|"未定义 → 发布版"| Stub["编译 apps/common/debug/debug.c 桩函数<br/>printf/puts/log_print 等全部为空"]
    Config -->|"已定义 → 调试版"| Lib["链接预编译库中的真实调试实现<br/>(UART 输出 / 分级日志过滤)"]
    Stub --> Opt["优化器消除空函数调用<br/>固件零调试开销"]
    Lib --> Init["启动早期调用 debug_init()<br/>初始化调试 UART"]
    Init --> Out["log_print / printf 输出到调试通道"]
    Stub --> Assert["assert_printf 无条件调用 cpu_assert_debug()"]
    Lib --> Assert
    Assert --> Exc["exception_analyze() 解析异常现场<br/>输出崩溃信息"]
    Out --> Exc

流程说明

  1. 编译期分叉:预处理器依据 CONFIG_DEBUG_ENABLE 选择桩函数还是真实实现。这一步发生在编译期,因此运行时不存在任何分支判断。
  2. 发布版路径:桩函数被编译后,优化器将空函数调用内联消除,调试字符串(若在 #if 之外仍存在格式化代码)也随之消失,发布固件不携带调试信息。
  3. 调试版路径:应用在启动早期调用 debug_init() 打开调试通道;此后 log_print/printf 等按级别过滤后输出。
  4. 断言路径(两条路径共用):assert_printf 无论构建类型都调用 cpu_assert_debug(),随后可配合 exception_analyze() 定位崩溃点。这也是本组件最核心的运行时行为。

调试固件(cpu/*/tools)

每个 CPU 家族的 tools 目录都提供了用于调试的固件变体,例如:

  • cpu/bd19/tools/ota_debug.bin、cpu/bd29/tools/ota_debug.bin、cpu/br23/tools/ota_debug.bin、cpu/br23/tools/ota_all_debug.bin、cpu/br23/tools/ota_nor_debug.bin、cpu/br25/tools/ota_debug.bin、cpu/br30/tools/ota_debug.bin 等——带调试输出的 OTA 引导/升级固件;
  • cpu/bd19/tools/uboot.boot_debug、cpu/br23/tools/uboot.boot_debug 等——带调试信息的 boot 固件;
  • cpu/br25/tools/uboot_lrc.boot_debug、cpu/br30/tools/br30c_ota_debug.bin 等——针对特定封装/容量的变体。

这些 .bin/.boot_debug 文件是烧录到板端用于 bring-up 与问题定位的调试版本固件,生产环境应改用对应的正式版本。它们的命名规律(_debug 后缀、uboot/ota 前缀)与 ota_all/ota_nor/ota_lrc 等容量/介质变体可以辅助确认某块板子该烧哪个调试固件。

Usage Examples

示例 1:发布版桩函数的完整形态(桩文件整体结构)

#ifndef CONFIG_DEBUG_ENABLE

int putchar(int a)
{
    return a;
}

int puts(const char *out)
{
    return 0;
}

int printf(const char *format, ...)
{
    return 0;
}
...
int assert_printf(const char *format, ...)
{
    cpu_assert_debug();

    return 0;
}

#endif

来源:debug.c

这是理解本组件最关键的一段代码:整个调试输出层的「发布形态」就是一组空壳。应用层代码无需任何条件编译即可调用 printf 等标准接口——发布版自动变为无操作,调试版自动输出,这就是该设计带来的最大便利。

示例 2:断言在发布版中的实际行为

int assert_printf(const char *format, ...)
{
    cpu_assert_debug();

    return 0;
}

来源:debug.c

即使 CONFIG_DEBUG_ENABLE 未定义,assert_printf 仍会调用 cpu_assert_debug()。若你的应用发现发布版在某个断言处「卡死」,这并非死机,而是断言保护机制在起作用——此时应借助 exception_analyze() 或调试器读取异常现场。

示例 3:CPU 调试接口声明(以 bd19 为例)

void ram_protect_close(void);
void debug_init();
void exception_analyze();

来源:debug.h (bd19)

应用在 board_init 或系统启动早期应调用 debug_init();崩溃回调/异常向量中应调用 exception_analyze() 输出现场信息。ram_protect_close() 只在调试器需要访问受保护 RAM 时使用,量产代码不应调用。

示例 4:板级配置头文件(配置宏的载体)

板级工程通过 board_*_cfg.h 与 board_*_global_build_cfg.h 组织构建配置,例如 bd19 平台的演示板:

  • board_ac6321a_demo_cfg.h —— 板级硬件/外设配置;
  • board_ac6321a_demo_global_build_cfg.h —— 全局构建开关(调试宏通常在此类文件中定义)。

说明:本页探索阶段未逐行读取这两个头文件的具体宏内容;CONFIG_DEBUG_ENABLE 的具体定义位置以实际板级工程为准(可能位于 app_config.h 或板级 *_global_build_cfg.h)。

Configuration Options

配置宏取值默认行为说明
CONFIG_DEBUG_ENABLE定义/未定义未定义(发布形态)未定义时编译 apps/common/debug/debug.c 中的全部桩函数;定义时使用预编译库中的真实调试输出实现
CONFIG_DEBUG_LITE_ENABLE定义/未定义未定义精简调试模式。定义后连 log_putbyte 字节级输出钩子都被裁剪,进一步减小代码体积;通常与 CONFIG_DEBUG_ENABLE 配合用于资源受限场景

配置方式:以上宏为编译期开关,需要在包含 app_config.h 之前生效(debug.c 第一行即 #include "app_config.h")。建议在板级 *_global_build_cfg.h 或工程构建脚本中统一定义,避免散落在各处导致构建不一致。

调试/发布切换实践:

场景推荐配置
量产发布不定义 CONFIG_DEBUG_ENABLE(默认即发布形态,零开销)
常规开发调试定义 CONFIG_DEBUG_ENABLE
时序敏感/资源紧张同时定义 CONFIG_DEBUG_ENABLE + CONFIG_DEBUG_LITE_ENABLE
新板 bring-up定义 CONFIG_DEBUG_ENABLE 并烧录对应 CPU 的 ota_debug.bin 引导

API Reference

以下接口均基于实际源码核实(发布构建桩实现位于 apps/common/debug/debug.c,调试构建真实实现由预编译库提供;驱动入口位于各 CPU 的 asm/debug.h)。

输出接口(发布版桩实现)

int putchar(int a)

  • 描述:输出单字符。发布版直接返回入参,无副作用,用于满足 C 库字符输出契约。
  • 参数:a (int) — 待输出字符。
  • 返回:传入的字符 a。

int puts(const char *out)

  • 描述:输出字符串(含换行)。发布版为空操作。
  • 参数:out (const char*) — 以 \0 结尾的字符串。
  • 返回:固定 0(表示成功)。

int printf(const char *format, ...)

  • 描述:格式化输出。发布版为空操作;调试版经预编译库输出到调试通道。
  • 参数:format (const char*) — 格式化串;... — 可变参数。
  • 返回:固定 0。

void put_buf(const u8 *buf, int len)

  • 描述:按缓冲区整体输出(通常为十六进制转储)。
  • 参数:buf (const u8*) — 数据指针;len (int) — 字节数。

void put_u8hex(u8 dat) / void put_u16hex(u16 dat) / void put_u32hex(u32 dat)

  • 描述:按 8/16/32 位宽度输出十六进制数值,便于直接观察寄存器与字段值。

void log_print(int level, const char *tag, const char *format, ...)

  • 描述:分级日志入口。调试版按 level 过滤(错误/警告/信息级别),tag 标识来源模块。
  • 参数:level (int) — 日志级别;tag (const char*) — 模块标签;format (const char*) — 格式化串。

void log_putbyte(char c)

  • 描述:字节级输出钩子(供底层驱动使用)。定义 CONFIG_DEBUG_LITE_ENABLE 时该桩不编译。
  • 参数:c (char) — 待输出字节。

断言接口

int assert_printf(const char *format, ...)

  • 描述:断言输出。发布版与调试版行为一致:均调用 cpu_assert_debug() 触发 CPU 异常处理,随后返回 0。
  • 参数:format (const char*) — 断言信息格式化串。
  • 返回:固定 0。
  • 行为:触发 cpu_assert_debug()(由预编译驱动库实现,通常进入异常/停机状态)。

CPU 驱动入口(声明于 include_lib/driver/cpu/*/asm/debug.h)

void debug_init(void)

  • 描述:初始化调试通道(调试 UART 等),应在系统启动早期调用一次。
  • 声明位置:bd19 见 debug.h L14,br25 见 debug.h L35。

void exception_analyze(void)

  • 描述:解析异常/断言触发后的 CPU 寄存器现场,输出崩溃信息用于定位问题。

void ram_protect_close(void)

  • 描述:关闭 RAM 写保护(仅 bd29/br23/br25/br30/br34 声明)。调试阶段供仿真器/下载工具访问受保护内存;量产代码不应调用。

Failure Modes, Edge Cases & Concurrency

以下分析均基于已核实的源码行为(桩函数语义、编译开关、断言路径)与嵌入式系统的一般约束,推理部分已明确标注。

断言在发布版中「卡死」的误判

  • 现象:发布版固件在特定条件下停止响应。
  • 根因:assert_printf 即使在没有调试输出的构建中也调用 cpu_assert_debug()(见 debug.c L56-L61)。这通常是断言保护触发而非随机死机。
  • 处置:通过调试器读取异常现场,或调用 exception_analyze() 解析;不要简单禁用断言来「修复」。

调试输出与实时性的冲突

  • 定义 CONFIG_DEBUG_ENABLE 后,printf/log_print 的 UART 输出会阻塞/占用 CPU 时间,可能破坏对时序敏感的蓝牙协议栈行为(丢包、断连、超时)。
  • 建议:时序相关路径(如中断、协议回调)避免高频打印;使用 CONFIG_DEBUG_LITE_ENABLE 精简输出路径;调试完成后务必切换回发布构建验证。

调试宏不一致导致的构建问题

  • debug.c 第一行 #include "app_config.h",宏必须在包含该头文件前全局生效。若某些编译单元定义了 CONFIG_DEBUG_ENABLE 而另一些没有,会出现符号重复或符号缺失(桩函数与库函数同名冲突)的链接错误。
  • 建议:宏统一在板级 *_global_build_cfg.h 或工程级构建脚本定义,保证全工程一致。

未初始化调试通道时的静默丢失

  • 调试版构建若未在启动早期调用 debug_init()(或调用了 ram_protect_close() 而未开 UART),printf 输出会被静默丢弃——不会报错,排查时容易误判为「打印函数失效」。

并发/中断上下文打印

  • 桩函数没有锁或原子性保护;调试版真实实现的中断安全性由预编译库决定。在中断上下文与主循环同时打印时,理论上可能交错输出。嵌入式调试场景通常容忍该现象,但若输出用于协议分析,应在单一任务中集中打印。

边界:log_putbyte 的裁剪

  • 定义 CONFIG_DEBUG_LITE_ENABLE 时 log_putbyte 桩不编译(debug.c L49-L54)。若应用或驱动代码直接调用 log_putbyte 且构建为精简模式,将产生链接错误——这是刻意的「编译期强制约束」,提示你在精简模式下不要依赖字节级钩子。

Performance & Operational Considerations

  • 发布版零开销:全部调试函数在编译期被替换为空实现并被优化器消除,不占 flash、不占栈、无运行分支。这是本组件最重要的性能特性。
  • 调试版成本:UART 输出速率(波特率)决定吞吐上限;log_print 的级别过滤在库内完成,过滤开销极低,但格式化(printf 类)在低主频 MCU 上是主要成本,应避免高频调用。
  • 固件选择:bring-up 使用 ota_debug.bin/uboot.boot_debug 等调试固件(见 cpu/bd19/tools 等目录);发布前必须切换为正式固件,防止调试通道与额外输出影响产测与功耗。
  • 故障排查流程:异常触发 → cpu_assert_debug() 停机 → 调试器附加或 exception_analyze() 输出现场 → 依据 PC/栈回溯定位。建议所有量产固件保留断言(不要关闭 assert_printf 的 cpu_assert_debug() 调用)。

Extension Points

  • 自定义输出通道:调试版真实实现位于预编译库,直接修改受限制;应用层可通过 log_print(level, tag, ...) 约定模块标签,配合库内过滤实现按模块开关日志,无需改库。
  • 新 CPU 移植:新增 CPU 家族需在 include_lib/driver/cpu/<cpu>/asm/debug.h 提供 debug_init() 与 exception_analyze()(对齐现有 bd19/br25 等声明),并在驱动库中实现 cpu_assert_debug() 与真实调试输出;apps/common/debug/debug.c 无需改动。
  • 精简模式扩展:CONFIG_DEBUG_LITE_ENABLE 提供了一档「最小调试」形态,若需要更细的裁剪粒度,可参照 log_putbyte 的条件编译模式,将更多底层输出钩子纳入条件编译。
  • 调试固件扩展:cpu/*/tools 下调试固件命名规律清晰(ota_*_debug.bin、uboot*.boot_debug),新板型可参考同类固件生成对应的调试变体用于 bring-up。

Tests

本次探索未在仓库中找到针对 apps/common/debug/debug.c 或调试配置的单元测试/自动化测试文件。该模块的验证主要依赖:

  • 构建验证:分别以定义/不定义 CONFIG_DEBUG_ENABLE 编译,确认链接成功且行为符合预期(发布版无输出、调试版有输出);
  • 板级验证:烧录 ota_debug.bin 调试固件,确认 UART 日志输出与断言触发路径(cpu_assert_debug → exception_analyze)工作正常;
  • 断言验证:构造一个触发 assert_printf 的场景(如空指针/越界),确认发布版同样进入异常处理流程。

若后续版本补充了测试,建议覆盖:宏组合矩阵(4 种开关组合的编译结果)、桩函数返回契约(putchar 回显、puts/printf 返回 0)、断言路径对 cpu_assert_debug 的调用。

Related Links

  • 源码:apps/common/debug/debug.c(本组件核心实现)
  • 源码:include_lib/driver/cpu/bd19/asm/debug.h(CPU 调试入口示例)
  • 源码:include_lib/driver/cpu/br25/asm/debug.h(br25 调试入口)
  • 配置:apps/hid/board/bd19/board_ac6321a_demo_cfg.h(板级配置示例)
  • 配置:apps/hid/board/bd19/board_ac6321a_demo_global_build_cfg.h(全局构建开关示例)
  • 固件目录:cpu/bd19/tools、cpu/br23/tools、cpu/br25/tools、cpu/br30/tools(调试引导/OTA 固件)
  • 兄弟页面:板级 Board 配置(引脚、外设、时钟);OTA 升级机制;异常处理与看门狗组件(若目录中存在)
Prev
蓝牙公共模块与消息联动
Next
杰理关键词唤醒(jl_kws)