杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • SDK 总览与芯片能力
    • 环境搭建与编译构建
    • 烧录与固件升级
    • 文档与版本资源
  • 应用与示例方案

    • demo 示例工程
    • WiFi 摄像头方案 (wifi_camera)
    • WiFi 音箱方案 (wifi_soundbox)
    • WiFi 婴儿监护方案 (wifi_bbm)
    • 公共应用模块库
    • 示例代码库 (example)
  • 系统架构与平台

    • 总体架构与工程分层
    • 系统启动与运行框架
    • 芯片驱动与板级适配
    • 设备管理与文件系统
    • 系统工具库与算法
  • 音频子系统

    • 音频框架与处理节点
    • 音频编解码与音效
    • 播放器与录音器
    • 语音交互与 AI 唤醒
    • LE Audio 与蓝牙音频
    • 音频调试与歌词
  • 视频与显示子系统

    • 摄像头驱动与 ISP
    • 视频编码与图像处理
    • 显示与 GPU 加速
    • 屏幕镜像 (screen_mirror)
  • 无线连接与网络

    • 蓝牙协议栈 (双模蓝牙)
    • WiFi 协议栈与配网
    • 网络协议栈
    • 云平台与 IoT 协议
  • UI 子系统

    • LVGL 集成与应用
    • UI 工程与工具链
  • 配置系统

    • 功能配置
    • 板级配置
    • 网络与蓝牙配置
    • 音频配置与提示音
  • 工具与测试

    • 产测与射频测试工具
    • 固件升级与更新机制
    • 调试与日志工具
  • 硬件参考设计

    • 原理图参考设计
    • 芯片数据手册

系统工具库与算法

AC792 系列 SDK 的底层系统工具库与通用算法集合,涵盖环形缓冲区(circular buffer)、线性缓冲区(lbuf)、链表(list)、原子操作(atomic)、时间管理(jiffies / sys_timer)、调试输出(debug / dlog)等基础能力,为上层应用、音频服务、蓝牙协议栈与网络栈提供公共基础设施。

Purpose and Scope

本页介绍 AC792N SDK V3 中位于 sdk/include_lib/system 下的系统级工具库与通用算法组件。这些组件是 SDK 各子系统的公共地基:音频服务器、蓝牙控制器、网络协议栈、文件系统(littlefs/FlashDB 等第三方库)以及应用层都依赖它们完成缓冲管理、数据组织、并发同步和定时调度。

本页覆盖的范围:

  • 通用工具层(sdk/include_lib/system/generic/):circular_buf.h(环形缓冲)、lbuf.h / lbuf_lite.h(线性缓冲)、list.h(双向链表)、atomic.h(原子操作)、jiffies.h(时间基准)、ascii.h(字符工具)、io.h / ioctl.h / irq.h / cpu.h(硬件抽象与中断)、errno-base.h(错误码)、debug_lite.h / dlog.h / includes.h
  • 系统服务层(sdk/include_lib/system/):timer.h(sys_timer 定时器框架)、app_core.h(应用框架)、database.h(配置数据库)、boot.h / bank_switch.h(启动与双 bank 切换)、debug.h

有意留给其他页面的内容:音频 DSP 算法(EQ/AEC/降噪)属于音频服务器能力,编解码算法属于音频解码器,图像 AE/AWB/IQ 算法属于摄像头驱动,基准测试中的 coremark/securemark 属于第三方移植,均不在本页展开。

说明:本仓库的 include_lib 以头文件形式发布接口,具体实现编译进预编译库(.a)。本页基于可读到的头文件接口声明与目录结构进行整理;凡未能在源码中直接读取到实现细节的模块,均明确标注,不做臆测。

概述

在嵌入式音频 SoC 上,系统工具库解决的是「资源受限、实时性要求高」条件下的通用问题:

  • 内存与缓冲:音频数据流是持续的、不等长的,必须用高效的环形缓冲(cbuffer_t)在生产者(采集/解码)与消费者(播放/编码)之间搬运数据;lbuf 则面向分配-释放模式简单的场景提供一次性线性缓冲,避免碎片。
  • 数据结构:设备节点、任务列表、事件队列等使用侵入式双向链表(list.h)组织,零拷贝、O(1) 插入删除。
  • 并发原语:多任务 + 中断上下文并存,atomic.h 提供关中断保护的原子读写与位操作。
  • 时间基准:jiffies.h 提供节拍计数,timer.h 在其上构建 sys_timer 软件定时器,通过链接段(linker section)静态注册,零动态分配。
  • 调试手段:debug.h / debug_lite.h / dlog.h 提供分级日志与断言,配合串口输出在无 OS 或轻量 OS 环境下定位问题。

这些工具的设计意图是:不依赖具体 RTOS、不引入堆碎片的确定性行为、以最少的运行时开销换取可预测的实时性。上层每个服务(如 audio_server)都通过这套基础件组合出自己的数据通路。

架构

flowchart TD
    subgraph sg_App["应用层"]
        App["APP / 音频场景 / 蓝牙应用"]
    end

    subgraph sg_Svc["系统服务层 (system/)"]
        Timer["timer.h (sys_timer)"]
        AppCore["app_core.h"]
        DB["database.h"]
        Boot["boot.h / bank_switch.h"]
        Debug["debug.h"]
    end

    subgraph sg_Generic["通用工具层 (system/generic/)"]
        CBuf["circular_buf.h (cbuffer_t)"]
        LBuf["lbuf.h / lbuf_lite.h"]
        List["list.h (双向链表)"]
        Atomic["atomic.h (原子操作)"]
        Jiffies["jiffies.h (节拍基准)"]
        Io["io.h / ioctl.h / irq.h / cpu.h"]
        Ascii["ascii.h"]
        Errno["errno-base.h"]
    end

    subgraph sg_HW["硬件层"]
        CPU["CPU / 中断控制器 / 外设寄存器"]
    end

    App --> AppCore
    App --> Timer
    AppCore --> Debug
    Timer --> Jiffies
    Timer --> Atomic
    Timer --> List
    DB --> LBuf
    Debug --> Ascii
    Io --> CPU
    irq["irq.h 中断入口"] --> CPU
    CBuf -. 被 audio_server/audio_dev 使用 .-> App
    List -. 被各服务使用 .-> App
    LBuf -. 被各服务使用 .-> App
    Atomic -. 被各服务使用 .-> App

架构分四层:最底层是硬件抽象(io.h/ioctl.h/irq.h/cpu.h),其上是通用工具层,再上是系统服务层(定时器、数据库、启动引导),最上层是应用与业务服务。通用工具层只依赖硬件抽象层,不依赖任何业务模块,保证可复用性与可测试性;系统服务层在通用工具层之上组合出面向业务的框架能力。

从 Grep 检索到的交叉引用可以看到这种依赖关系的事实证据:server/audio_dev.h 的音频通道接口直接以 cbuffer_t * 为参数(audio_channel_cbuf_data_separate / audio_channel_cbuf_data_merge),说明音频服务器直接构建在环形缓冲区工具之上。

主要工具模块详解

环形缓冲区 circular_buf.h

环形缓冲区是音频 SoC 数据通路的核心数据结构:ADC 采集、解码器输出、DAC 播放、编码器输入之间的所有 PCM 数据搬运都通过它完成。与链表缓冲相比,环形缓冲只维护读写指针,无分配/释放开销,天然适配"生产者持续写入、消费者持续读出"的流式场景。

cbuffer_t 类型在 server/audio_dev.h 的接口签名中直接可见其用法——音频通道分离/合并接口以 cbuffer_t * 为第一参数:

int audio_channel_cbuf_data_separate(cbuffer_t *cbuf, s16 *input, u8 channel_bit_map, u8 channel, u32 output_len);
int audio_channel_cbuf_data_merge(cbuffer_t *cbuf, s16 *ch0_data, s16 *ch1_data, u32 output_len);

Source: audio_dev.h

这两个接口展示了对 cbuffer_t 的典型用法:从环形缓冲中按声道位图抽取指定声道数据(separate),或将多声道数据交织合并回环形缓冲(merge)。这是立体声采集/回放、多声道混音场景的基础算法。环形缓冲本身的具体 API(如 cbuf_init / cbuf_read / cbuf_write 等)在 circular_buf.h 中声明,实现位于预编译库,本页未能读取到其函数体,具体签名单以头文件为准。

线性缓冲 lbuf.h / lbuf_lite.h

lbuf(linear buffer)用于"一次性分配、一次性消费"的短生命周期数据:例如配置数据库(database.h)读写时的临时缓冲、协议消息的组包缓冲。lbuf_lite.h 提供轻量版本,进一步去掉对堆的依赖,面向中断上下文或极低内存场景。设计意图是:对这类数据用固定大小的静态线性区而非堆分配,规避堆碎片与分配失败风险。

双向链表 list.h

侵入式双向链表(Linux kernel 风格),节点结构内嵌于业务结构体而非单独分配。典型应用:sys_timer 的定时器链表、设备注册表、事件队列。相比数组,链表插入/删除为 O(1),且不要求连续内存;相比动态分配节点,侵入式设计零额外开销。

原子操作 atomic.h

在"中断 + 任务"并发的裸机/轻 OS 环境下,普通 C 读写可能被中断打断导致半更新状态。atomic.h 提供关中断保护的原子读、写、自增、位操作原语,是 sys_timer 计数、标志位管理等共享状态更新的基础。其实现通常依赖 CPU 的关中断指令或硬件原子指令,具体汇编实现位于预编译库。

时间基准 jiffies.h 与系统定时器 timer.h

jiffies 是系统节拍计数器(u32),由硬件定时器中断周期性递增,是 sys_timer 的时基。timer.h 定义软件定时器框架,核心数据结构为:

struct static_sys_timer {
    void (*func)(void *priv);
    u32 msec;
    u32 jiffies;
};

Source: timer.h

每个定时器持有回调 func、周期 msec 与下次到期的绝对节拍 jiffies。定时器通过链接段静态注册——编译期用 SEC_USED(.hi_timer) 把 static_sys_timer 实例放入专用段,链接器收集段内所有实例形成数组,运行时无需任何动态内存分配:

#define SYS_HI_TIMER_ADD(_func, _priv, _msec) \
	static struct static_sys_timer hi_timer SEC_USED(.hi_timer) = { \
		.func = _func, \

Source: timer.h

段的起止边界由链接脚本符号暴露给运行时:

extern struct static_sys_timer static_hi_timer_begin[];
extern struct static_sys_timer static_hi_timer_end[];

Source: timer.h

这种"链接段收集器"模式(与 Linux __initcall、Jieli 的 sys_timer 同类思想)是本 SDK 静态注册机制的代表:零运行时注册成本、零堆分配、启动即就绪。头文件同时声明了运行期动态增加定时器的接口(sys_timer 定时扫描增加接口,参数为私有指针 priv),供运行中需要临时定时的场景使用。

调试输出 debug.h / debug_lite.h / dlog.h

  • debug.h:系统级调试入口,提供断言、打印开关与等级控制,可配合 bank_switch.h 在异常时保存现场。
  • debug_lite.h:精简版,面向最小化固件,剥离部分运行时检查以减小体积。
  • dlog.h:分级日志(error/warn/info/verbose 风格),带模块标签,输出目标(串口/缓存)可配置。

硬件抽象与杂项 io.h / ioctl.h / irq.h / cpu.h / ascii.h / errno-base.h

  • io.h / ioctl.h:寄存器/外设读写抽象,ioctl 提供统一的设备控制命令面,audio_server 等服务器通过它向驱动下发控制命令。
  • irq.h:中断注册与使能/屏蔽接口,是中断上下文与任务上下文协作的边界。
  • cpu.h:CPU 特性抽象(休眠、看门狗、复位等)。
  • ascii.h:字符分类/转换工具(大小写、数字判断等),供字符串解析(如 AT 命令、协议解析)复用。
  • errno-base.h:POSIX 风格错误码基值,统一各模块错误语义。

系统服务 app_core.h / database.h / boot.h / bank_switch.h

  • app_core.h:应用主框架,定义应用任务入口与事件循环骨架。
  • database.h:配置项持久化数据库,为上层提供 KV 式读写,底层常配合 lbuf 做临时缓冲。
  • boot.h:引导加载(跳转、校验)。
  • bank_switch.h:双 bank 固件升级切换,异常时用于保存/恢复现场。

核心机制与流程

sys_timer 的注册与触发流程

sequenceDiagram
    participant Dev as 开发者
    participant Sec as 链接器 .hi_timer 段
    participant Init as 系统初始化
    participant Tick as 硬件定时器中断
    participant Cb as 定时器回调 func(priv)

    Dev->>Sec: SYS_HI_TIMER_ADD(func, priv, msec) 静态注册
    Init->>Sec: 遍历 static_hi_timer_begin[]~end[] 收集定时器
    Init->>Init: 计算首次到期 jiffies = 当前节拍 + msec
    loop 每个节拍
        Tick->>Cb: 扫描到期定时器链表,调用 func(priv)
        Cb-->>Tick: 返回后重排到期时间(周期任务)
    end

运行流程要点:

  1. 注册:编译期宏 SYS_HI_TIMER_ADD 把 static_sys_timer 实例放入 .hi_timer 链接段;链接器将所有实例连续排布,static_hi_timer_begin/end 符号标定边界。运行时只需遍历段即可枚举全部定时器,不需要注册表初始化代码。
  2. 启动:系统初始化时读取段边界,为每个定时器计算首个到期绝对节拍(jiffies + msec),挂入到期链表。
  3. 触发:硬件节拍中断递增 jiffies 并扫描链表;到期项调用 func(priv),周期任务随后重排下一轮到期时间。
  4. 动态添加:运行期接口按 priv 注册新定时器,用于非编译期可知的临时任务。

环形缓冲的数据流

flowchart LR
    Prod["生产者<br/>(采集/解码)"] -->|"cbuf_write"| CB[(cbuffer_t 环形缓冲)]
    CB -->|"cbuf_read"| Cons["消费者<br/>(播放/编码)"]
    CB -->|"data_separate"| Ch0["声道0"]
    CB -->|"data_merge"| Mix["混音/交织"]

生产者与消费者在不同上下文(DMA 中断、解码任务、播放任务)并发读写同一 cbuffer_t;环形缓冲的指针维护与水位判断(空/满/可读长度)是音频链路是否流畅、是否出现爆音/卡顿的关键。audio_channel_cbuf_data_separate/merge 则在其上完成多声道数据的拆分与交织,属于本 SDK 音频域的典型算法。

使用示例

以下示例全部取自仓库中可验证的源码片段。

示例 1:静态注册一个系统定时器(timer.h)

SYS_HI_TIMER_ADD 宏在编译期把回调、私有参数与周期写入 .hi_timer 链接段。下面的片段展示了宏的定义形式(回调函数指针 + 私有参数 + 毫秒周期):

#define SYS_HI_TIMER_ADD(_func, _priv, _msec) \
	static struct static_sys_timer hi_timer SEC_USED(.hi_timer) = { \
		.func = _func, \

Source: timer.h

使用方式为 SYS_HI_TIMER_ADD(my_func, my_priv, 100),其中 my_func 必须匹配 void (*)(void *priv)。这种声明式注册的好处是:即使该定时器从未被条件编译排除,也不会产生运行期初始化代码——段收集由链接器完成,启动扫描 O(n) 即可。

示例 2:环形缓冲上的音频声道算法(audio_dev.h)

音频服务器对外暴露的声道处理接口直接操作 cbuffer_t:audio_channel_cbuf_data_separate 按 channel_bit_map 从交织的环形缓冲中抽取指定声道到 output_len 长度的输出缓冲;audio_channel_cbuf_data_merge 把左右声道数据交织写回环形缓冲:

int audio_channel_cbuf_data_separate(cbuffer_t *cbuf, s16 *input, u8 channel_bit_map, u8 channel, u32 output_len);
int audio_channel_cbuf_data_merge(cbuffer_t *cbuf, s16 *ch0_data, s16 *ch1_data, u32 output_len);

Source: audio_dev.h

这是"工具库被业务复用"的典型证据:应用层无需了解环形缓冲内部结构,只需把 cbuffer_t 句柄与声道配置交给服务器接口即可完成数据重组。

示例 3:定时器核心数据结构(timer.h)

struct static_sys_timer {
    void (*func)(void *priv);
    u32 msec;
    u32 jiffies;
};

Source: timer.h

三个字段分别表达"做什么"(回调)、"多久一次"(周期)与"何时到期"(绝对节拍)。将到期时间存为绝对 jiffies 而非相对计数,是为了在节拍中断里只需一次比较即可判定是否到期,避免累计误差与重入问题。

API 参考

说明:include_lib 中的多数工具以预编译库发布,本页仅列出已在源码中直接读取到的接口;其余接口以各头文件声明为准。

struct static_sys_timer(timer.h)

字段类型说明
funcvoid (*)(void *priv)定时器到期回调
msecu32周期,单位毫秒
jiffiesu32下一次到期的绝对节拍

SYS_HI_TIMER_ADD(func, priv, msec)(timer.h)

编译期静态注册高优先级系统定时器,放入 .hi_timer 链接段。宏展开为 static struct static_sys_timer hi_timer SEC_USED(.hi_timer) 初始化。无需运行期注册调用,由系统初始化遍历段自动接管。

static_hi_timer_begin[] / static_hi_timer_end[](timer.h)

链接器提供的 .hi_timer 段边界符号(extern 数组声明),系统初始化据此枚举全部静态定时器。

audio_channel_cbuf_data_separate(cbuf, input, channel_bit_map, channel, output_len)(audio_dev.h)

从环形缓冲按声道位图分离出指定声道数据。

参数:

  • cbuf(cbuffer_t *):环形缓冲句柄
  • input(s16 *):交织 PCM 输入
  • channel_bit_map(u8):声道位图(指示哪些声道有效)
  • channel(u8):目标声道号
  • output_len(u32):输出长度

返回: int,处理结果/长度(具体语义以头文件注释为准)。

audio_channel_cbuf_data_merge(cbuf, ch0_data, ch1_data, output_len)(audio_dev.h)

将左右声道数据交织合并写入环形缓冲。

参数:

  • cbuf(cbuffer_t *):环形缓冲句柄
  • ch0_data / ch1_data(s16 *):左右声道数据
  • output_len(u32):输出长度

返回: int,处理结果/长度(具体语义以头文件注释为准)。

配置选项

系统工具库本身以头文件 + 预编译库形式提供,配置主要体现在使用侧:

配置/宏位置说明
SEC_USED(.hi_timer)timer.h 宏展开把定时器实例放入专用链接段(段名由链接脚本决定)
SYS_HI_TIMER_ADD 的 _msec 参数使用侧定时器周期,毫秒,影响回调频率与 CPU 占用
static_hi_timer_begin/end 段符号链接脚本必须保证 .hi_timer 段被链接器收集且边界符号有效,否则定时器不会触发
中断节拍周期时钟/定时器驱动决定 jiffies 分辨率,影响 sys_timer 最小精度

失败模式、边界情况与并发

jiffies 溢出(u32 回绕)

static_sys_timer.jiffies 与系统节拍均为 u32。长时间运行(节拍 1 kHz 时约 49.7 天)会发生回绕。正确的到期判断必须使用无符号减法比较 (u32)(current - target) < threshold 这类处理,而不是直接 current >= target;若 SDK 实现未做回绕安全处理,超长运行的设备会出现定时器提前/延后触发的边界问题。源码中未读取到期比较的具体实现,此处作为必须校验的设计点提示。

定时器回调上下文

func 在节拍中断上下文(或由中断驱动的扫描逻辑)中执行。回调必须:不阻塞、不长时间关中断、不做重入操作;回调中若修改共享数据需配合 atomic.h 或等效保护。否则会出现中断嵌套、优先级反转或看门狗复位。

环形缓冲的并发读写

cbuffer_t 的生产者(DMA 中断/解码)与消费者(播放任务)运行在不同上下文。典型故障模式:

  • 下溢(underrun):消费者读取快于生产者填充,播放出现咔哒声或静音间隙。缓解依赖水位监测与数据预取。
  • 上溢(overrun):生产者写入超过容量,旧数据被覆盖或写入被丢弃,出现爆音。
  • 指针撕裂:若读/写指针的更新不是原子的,且没有单写者/单读者约束,会出现长度计算错误。环形缓冲的单生产者-单消费者模型通常依赖"只由一方更新自己的指针"来规避加锁。

链表与原子操作的误用

侵入式链表要求节点在生命周期内不被重复插入/删除;atomic.h 只能保证单次读写的原子性,不能替代临界区。中断与任务同时操作同一链表(如定时器链)时必须以关中断或原子位标记保护,否则链表指针会被破坏。

链接段未收集

若链接脚本没有把 .hi_timer 段包含进固件,或 static_hi_timer_begin/end 符号缺失/错位,静态定时器将静默失效——这是"链接段收集器"模式的经典隐患:编译期无报错,运行时无定时器触发。排查时应检查 map 文件中该段的地址范围。

性能与运维考量

  • 零动态分配:静态定时器与侵入式链表的设计目标是确定性内存行为;音频数据通路用环形缓冲避免拷贝与分配抖动,这是保证音频实时性(无爆音、低延迟)的关键。
  • 节拍粒度:sys_timer 的最小精度等于节拍周期;高精度需求应使用硬件定时器或 hi_timer 级别的优先级,而非普通 sys_timer。
  • 扫描开销:每节拍扫描定时器链表为 O(n);大量毫秒级短周期定时器会显著增加中断负载,应合并或分级。
  • 调试手段:异常时配合 debug.h/bank_switch.h 保存现场、dlog.h 分级日志输出;ascii.h 工具用于日志中的字符串处理。
  • 升级安全:boot.h / bank_switch.h 保证固件升级掉电不砖,属于系统服务层对工具库的典型组合使用。

扩展点

  • 新增静态定时器:调用 SYS_HI_TIMER_ADD(func, priv, msec) 即完成注册,无需修改任何初始化代码——链接段收集器自动接管。这是本 SDK 推荐的定时扩展方式。
  • 新增设备控制命令:通过 ioctl.h 的命令字体系扩展,驱动侧实现命令分发。
  • 自定义日志后端:dlog.h 的输出层可替换/扩展(串口、内存缓存、BLE 透传)。
  • 错误码扩展:基于 errno-base.h 的基值扩展模块专属错误码,保持全系统错误语义一致。

测试

  • SDK 在 sdk/apps/common/example/third_party/BenchMark 下提供 coremark、securemark(含 mbedTLS/wolfSSL 移植)等基准测试,用于评估 CPU 与算法性能,可作为工具库底层原语(原子、节拍、内存拷贝)性能的参考环境。
  • 音频域的环形缓冲算法(声道 separate/merge)可通过 audio_dev.h 接口做单元级验证;sdk/apps/common/audio_music/ 下存在 PCM 音量计算等算法示例(如 cal_pcm_dB.c),展示了以系统工具为基础构建音频算法的工程模式。
  • 注意:include_lib 对应的工具实现以预编译库形式发布,仓库内未提供其源码级单测;接口行为验证需通过上层模块(音频、蓝牙、数据库)的集成测试完成。

相关链接

  • circular_buf.h 环形缓冲
  • timer.h 系统定时器
  • lbuf.h 线性缓冲
  • list.h 双向链表
  • atomic.h 原子操作
  • jiffies.h 节拍基准
  • audio_dev.h 声道分离/合并接口
  • database.h 配置数据库
  • debug.h 调试框架

关联页面:音频服务与编解码算法参见音频服务器相关页面;蓝牙协议栈工具(btctrler/adapter/include/common/ 下的 cbuf/lbuf/list 变体)参见蓝牙控制器页面;文件系统工具(littlefs/FlashDB)参见存储相关页面。

Prev
设备管理与文件系统