杰理 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 工程与工具链
  • 配置系统

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

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

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

WiFi 音箱方案 (wifi_soundbox)

WiFi 智能音箱(大屏音箱 / 网络音频 / 带屏故事机)完整 SDK 方案,基于 AC792N 系列(wl83 平台)双核浮点 DSP,运行在 uC/OS 之上,集成了 WiFi 网络音频、蓝牙、音频 DSP 处理、UI 显示(LVGL)与智能语音等能力,构建目标为 ac792n_wifi_soundbox。

Purpose and Scope

本文档面向 sdk/apps/wifi_soundbox/ 目录下的 WiFi 音箱方案,系统性地说明该方案的:

  • 应用入口与系统任务/中断注册(app_main.c、app_msg.c)
  • 应用级配置体系(include/app_config.h → board/wl83/sdk_config.h → board/wl83/board_config.h)
  • 板级开发与构建配置(board/wl83/ 下的 Makefile、Code::Blocks 工程、chip_cfg、sdk_config)
  • 音频特性模块(audio/ 下的麦克风音效、场景切换、提示音表、音量同步)
  • 构建入口与工程定义(project.jlproj、make ac792n_wifi_soundbox)

同一仓库中的其他方案(WiFi 摄像头、婴儿监护器、demo 等)不在本文档范围内:

  • 对于 WiFi 摄像头方案,参见 sdk/apps/wifi_camera/ 及其对应文档页。
  • 对于 婴儿监护器方案,参见 sdk/apps/wifi_bbm/ 及其对应文档页。
  • 对于芯片平台(wl83 双核 DSP、内存与外设驱动)的通用说明,参见芯片平台相关文档页。

Overview

方案定位

根据 README.md 的描述,wifi_soundbox 方案面向 大屏智能音箱、网络音频、带屏故事机 等产品形态。它是一个典型的"带屏 + 网络 + 语音"综合方案:既具备传统蓝牙音箱的 A2DP/AVRCP 播放能力,又具备基于 WiFi 的在线音乐/网络音频能力,同时通过 LVGL 渲染 UI、通过 KWS(关键词唤醒)与智能语音提供交互。

该方案建立在 wl83 平台(AC7921A/AC7922A/AC7922C/AC7923A/AC7923B/AC7923C/AC7925A/AC7925B/AC7925C/AC7926A)之上,芯片为 双核浮点 DSP @ 320MHz,支持 wifi_camera / wifi_soundbox / wifi_bbm / demo 四种应用形态共用同一套芯片与 SDK 基础。

工程与构建入口

project.jlproj 将该工程的 SDK 类型定义为 wifi_soundbox、产品类型为 "音箱",默认编译变体指向 .\sdk\apps\wifi_soundbox\board\wl83,构建任务名为 ac792n_wifi_soundbox:

{
  "type": "音箱",
  "sdk": "wifi_soundbox",
  "singleSeries": false,
  "defaultVariant": {
    "path": ".\\sdk\\apps\\wifi_soundbox\\board\\wl83",
    "task": "ac792n_wifi_soundbox"
  }
}

Sources:

  • project.jlproj
  • project.jlproj

命令行构建方式(README.md):

make ac792n_wifi_soundbox

方案目录结构

sdk/apps/wifi_soundbox/
├── app_main.c                 # 应用主入口:中断表、系统任务表、外设/模块初始化
├── app_msg.c                  # 应用消息分发与处理
├── include/
│   └── app_config.h           # 应用级配置:音频源、资源分区、UI/音频预留区
├── audio/
│   ├── mic_effect.c           # 麦克风音效处理
│   ├── scene_switch.c         # 场景切换
│   ├── tone_table.c           # 提示音(Tone)表
│   └── vol_sync.c             # 音量同步
└── board/wl83/                # wl83 板级支持
    ├── AC792N_WIFI_SOUNDBOX.cbp  # Code::Blocks 工程文件
    ├── Makefile               # 构建脚本
    ├── board_config.h         # 板级配置(引脚/外设)
    ├── board_develop.c        # 板级初始化实现
    ├── board_develop_AC7922C.h / AC7925A.h / AC7925B.h / AC7926A.h  # 各型号板级差异
    ├── chip_cfg.h             # 芯片配置
    ├── include_dir.txt        # 头文件搜索路径清单
    ├── jlstream_node_cfg.h    # jlstream 音频节点配置
    └── sdk_config.c / sdk_config.h  # SDK 功能开关总配置

Architecture

下图展示了 wifi_soundbox 方案的整体分层架构:从编译期配置(.cbp / Makefile / sdk_config)到应用层(app_main、app_msg),再到音频/网络/蓝牙/显示等子系统,最终落到 wl83 芯片与 RTOS 之上。

flowchart TD
    subgraph sg_Build["构建与配置层"]
        CBP["AC792N_WIFI_SOUNDBOX.cbp<br/>Code::Blocks 工程"]
        MK["board/wl83/Makefile<br/>make ac792n_wifi_soundbox"]
        JL["project.jlproj<br/>sdk=wifi_soundbox, type=音箱"]
        APP_CFG["include/app_config.h<br/>应用资源与音频源配置"]
        SDK_CFG["board/wl83/sdk_config.h<br/>SDK 功能开关"]
        BRD_CFG["board/wl83/board_config.h<br/>板级外设配置"]
    end

    subgraph sg_App["应用层"]
        APP_MAIN["app_main.c<br/>中断表 + task_info_table + 模块初始化"]
        APP_MSG["app_msg.c<br/>消息分发"]
    end

    subgraph sg_Feature["特性模块 (audio/)"]
        MIC["mic_effect.c<br/>麦克风音效"]
        SCENE["scene_switch.c<br/>场景切换"]
        TONE["tone_table.c<br/>提示音表"]
        VOL["vol_sync.c<br/>音量同步"]
    end

    subgraph sg_Subsys["子系统 (apps/common + include_lib)"]
        NET["WiFi / 网络音频<br/>(net_event, pjsip, net_music)"]
        BT["蓝牙<br/>(bt_event, a2dp_dec, rcsp)"]
        AUDIO["音频 DSP<br/>(dac, aec, mic_effect, jlstream)"]
        UI["UI 显示<br/>(LVGL / freetype / rlottie)"]
        VOICE["智能语音<br/>(kws, smart_voice, audio_vad)"]
    end

    subgraph sg_Platform["平台层 (wl83)"]
        RTOS["uC/OS + 系统任务<br/>(app_core, sys_event, systimer...)"]
        DSP["双核浮点 DSP @ 320MHz"]
        FLASH[("Flash / SDNAND 资源分区")]
    end

    JL --> MK
    CBP --> MK
    APP_CFG --> SDK_CFG --> BRD_CFG
    MK --> APP_MAIN
    APP_MAIN --> APP_MSG
    APP_MAIN --> MIC
    APP_MAIN --> SCENE
    APP_MAIN --> TONE
    APP_MAIN --> VOL
    APP_MSG --> NET
    APP_MSG --> BT
    APP_MAIN --> AUDIO
    APP_MAIN --> UI
    APP_MAIN --> VOICE
    NET --> RTOS
    BT --> RTOS
    AUDIO --> RTOS
    UI --> RTOS
    VOICE --> RTOS
    RTOS --> DSP
    APP_CFG --> FLASH

架构说明:

  • 构建与配置层是整个方案的"入口开关":.cbp 工程通过 -DCONFIG_WIFI_SOUNDBOX_PROJECT_ENABLE 等宏把 SDK 编译成音箱形态;app_config.h → sdk_config.h → board_config.h 的三级配置链从"应用需求"逐级落到"芯片外设"。
  • 应用层只负责两件事:注册中断与任务(app_main.c),以及把事件(按键/蓝牙/设备/网络)分发给各功能模块(app_msg.c)。
  • 特性模块是方案独有的差异化能力:麦克风音效、场景切换、提示音表与音量同步,直接服务于"音箱"的产品体验。
  • 子系统全部来自 apps/common 与 include_lib(蓝牙协议栈 BTStack、网络栈 pjlib/pjsip、LVGL 等),方案通过条件编译宏决定启用哪些子系统。
  • 平台层最终由 uC/OS 调度这些任务到 wl83 双核 DSP 上运行,Flash/SDNAND 分区由 app_config.h 的资源预留宏定义。

应用入口与系统任务(app_main.c)

app_main.c 是方案的运行起点,它承载了三类静态定义:中断注册表、系统任务表、以及由系统框架调用的初始化函数。理解这个文件就等于理解整个方案的"调度骨架"。

中断注册表(irq_info_table)

方案通过 irq_info_table[] 显式声明中断号、优先级(0-7)以及注册到哪个 CPU 核:

const struct irq_info irq_info_table[] = {
    //中断号   //优先级0-7   //注册的cpu(0或1)
#ifdef CONFIG_IPMASK_ENABLE
    //不可屏蔽中断方法:支持写flash,但中断函数和调用函数和const要全部放在内部ram
#if 0 //如下,SPI1使用不可屏蔽中断设置
    { IRQ_SPI1_IDX,      7,   1    },//中断强制注册到cpu0/1
#endif
#endif

    { IRQ_BT_TIMEBASE_IDX,  5,  0 },
    { IRQ_BLE_RX_IDX,       5,  0 },
    { IRQ_BLE_EVENT_IDX,    5,  0 },
    { IRQ_BT_CLKN_IDX,      5,  0 },
    { IRQ_BREDR_IDX,        5,  0 },

#if CPU_CORE_NUM == 1
    { IRQ_SOFT5_IDX,        6,  0 }, //此中断强制注册到cpu0
    { IRQ_SOFT4_IDX,        6,  1 }, //此中断强制注册到cpu1
    { -2,                  -2, -2 }, //如果加入了该行, 那么只有该行之前的中断注册到对应核, 其他所有中断强制注册到CPU0
#endif
    { -1,                  -1, -1 },
};

Source: app_main.c

设计意图分析:

  • 蓝牙相关中断(IRQ_BT_TIMEBASE_IDX、IRQ_BLE_RX_IDX、IRQ_BLE_EVENT_IDX、IRQ_BT_CLKN_IDX、IRQ_BREDR_IDX)统一注册到 CPU0、优先级 5,保证蓝牙基带时序的确定性——蓝牙协议对时基中断的抖动极其敏感,必须固定核并给予较高优先级。
  • 当 CPU_CORE_NUM == 1 时,IRQ_SOFT5_IDX 强制到 CPU0、IRQ_SOFT4_IDX 强制到 CPU1,用于核间软中断通信;哨兵行 { -2, -2, -2 } 之后的所有中断全部强制注册到 CPU0,这是为了在单核运行模式下把关键中断收敛到一个核上,避免中断分布导致不可预期的竞争。
  • 表尾 { -1, -1, -1 } 是数组终止标记。

系统任务表(task_info_table)

app_main.c 为每个系统任务预先静态分配 TCB、栈与消息队列(静态分配避免了运行时 malloc 的不确定性,这对音频实时性至关重要):

/*创建使用 os_task_create_static 或者task_create 接口的 静态任务堆栈*/
#define SYS_TIMER_STK_SIZE 512
#define SYS_TIMER_Q_SIZE 256
static u8 sys_timer_tcb_stk_q[sizeof(StaticTask_t) + SYS_TIMER_STK_SIZE * 4 + sizeof(struct task_queue) + SYS_TIMER_Q_SIZE] ALIGNE(4);

#define APP_CORE_STK_SIZE 2048
#define APP_CORE_Q_SIZE 1024
static u8 app_core_tcb_stk_q[sizeof(StaticTask_t) + APP_CORE_STK_SIZE * 4 + sizeof(struct task_queue) + APP_CORE_Q_SIZE] ALIGNE(4);

Source: app_main.c

随后 task_info_table[] 以"任务名 + 优先级 + 栈大小 + 队列大小 + 静态内存块"的形式注册全部任务:

const struct task_info task_info_table[] = {
    { "app_core",            15,     APP_CORE_STK_SIZE,      APP_CORE_Q_SIZE,    app_core_tcb_stk_q  },
    { "sys_event",           29,     SYS_EVENT_STK_SIZE,                   0,    sys_event_tcb_stk_q },
    { "systimer",            14,     SYSTIMER_STK_SIZE,                    0,    systimer_tcb_stk_q  },
    { "sys_timer",            9,     SYS_TIMER_STK_SIZE,    SYS_TIMER_Q_SIZE,    sys_timer_tcb_stk_q },
    { "thread_fork_kill",    25,     256,      0 },
    { "dlog",                 1,     256,    128 },
    ...
    { "jlstream",            23,     768,    128 },
    { "a2dp_dec",            24,     768,      0 },
    /* file dec任务不打断jlstream任务运行,故优先级低于jlstream */
    { "file_dec",            24,     768,      0 },
    ...
    /* 麦克风音效任务优先级要高 */
    { "mic_effect",          26,     768,      0 },
    /* 为了防止dac buf太大,通话一开始一直解码,导致编码输入数据需要很大的缓存,这里提高编码的优先级 */
    { "audio_enc",           26,     768,    128 },
    { "aec",                 26,     768,    128 },
    ...
    { "dac",                 22,     256,    128 },
    { "kws",                  3,     256,     64 },
    { "smart_voice",         11,     512,    128 },
    ...
    { "usb_msd",              1,     512,    128 },
    { "uda_main",             2,    7000,      0 },
    { "update",              21,     512,     32 },
    ...
#if RCSP_MODE
    {"rcsp",                 17,     768,    128 },
    ...
#endif
};

Source: app_main.c

关键任务与设计意图:

任务优先级栈职责与设计意图
app_core152048应用主循环,消费 APP_CORE_Q_SIZE=1024 的消息队列,处理按键/蓝牙/网络/设备事件
sys_event29512系统事件分发(最高优先级之一),保证系统事件不被音频任务饿死
jlstream23768jlstream 音频流(网络流/文件流)解码搬运
a2dp_dec24768蓝牙 A2DP 解码;注释明确"file_dec 不打断 jlstream 运行,故优先级低于 jlstream"——这是为了在网络音频播放时优先保证流的连续性
mic_effect26768麦克风音效,注释明确"麦克风音效任务优先级要高"——保证人声处理的实时性
audio_enc / aec26768音频编码与回声消除,注释解释了"提高编码优先级以避免 DAC 缓冲过大"的设计权衡
dac22256DAC 输出
kws3256关键词唤醒(低优先级,功耗友好)
smart_voice11512智能语音
uda_main27000升级主任务(大栈,因为升级流程涉及文件系统与网络栈)
update / dw_update21512升级辅助任务
rcsp17768杰理 RCSP 私有协议(APP 控制/OTA/文件传输),条件编译 RCSP_MODE

优先级数值越小优先级越低(uC/OS 约定,dlog=1 最低,sys_event=29 最高)。音频链路任务集中在 22-26 区间、系统事件 29、应用 15,形成"系统事件 > 音频实时链路 > 应用逻辑 > 低优先级杂务"的调度层级。

核心数据流与运行流程

事件驱动模型

app_main.c 同时包含 event/key_event.h、event/bt_event.h、event/device_event.h、event/net_event.h 四类事件头文件,说明方案的运行模型是 事件驱动 + 消息队列:外设中断/协议栈回调产生事件,sys_event 任务将事件投递到 app_core 的消息队列,app_msg.c 负责分发处理。

sequenceDiagram
    participant HW as 外设/协议栈<br/>(按键/蓝牙/WiFi/USB)
    participant ISR as 中断服务程序<br/>(irq_info_table 注册)
    participant SE as sys_event 任务<br/>(优先级29)
    participant AC as app_core 任务<br/>(优先级15, Q=1024)
    participant AM as app_msg.c<br/>消息分发
    participant MOD as 功能模块<br/>(mic_effect/scene/tone/vol_sync...)

    HW->>ISR: 硬件中断 (BT/BLE/网络/按键)
    ISR->>SE: 产生系统事件
    SE->>AC: 投递到 app_core 消息队列
    AC->>AM: 取出消息
    AM->>MOD: 按事件类型分发 (key/bt/device/net)
    MOD-->>AM: 处理结果
    AM-->>AC: 继续取下一个消息

音频数据流

方案的核心是音频:网络音频/文件解码/BT A2DP → DAC 输出;麦克风 → AEC 回声消除 → mic_effect 音效 → 编码/上行。任务优先级设计(dac=22、jlstream=23、file_dec/a2dp_dec=24、audio_enc/aec/mic_effect=26)确保实时链路不被低优先级任务打断。

flowchart LR
    subgraph sg_In["输入源"]
        S1["网络流 (jlstream)"]
        S2["本地文件 (file_dec)"]
        S3["蓝牙 A2DP (a2dp_dec)"]
        S4["麦克风 (aud_capture)"]
    end
    subgraph sg_Proc["处理"]
        P1["aec 回声消除"]
        P2["mic_effect 音效"]
        P3["audio_enc 编码"]
        P4["dac 输出"]
        P5["scene_switch 场景切换"]
    end
    subgraph sg_Out["输出"]
        O1["扬声器 (DAC)"]
        O2["上行/通话"]
        O3["vol_sync 音量同步"]
    end
    S1 --> P4
    S2 --> P4
    S3 --> P4
    S4 --> P1 --> P2 --> P3
    P4 --> O1
    P3 --> O2
    P5 --> P4
    P4 --> O3

注:以上任务与模块关系依据 app_main.c 中的任务表及注释整理;音频节点拓扑的最终定义位于 board/wl83/jlstream_node_cfg.h 与 audio_config.h。

配置体系

三级配置链

方案通过"应用配置 → SDK 配置 → 板级配置"三级头文件链完成从产品需求到硬件引脚的落地:

  1. include/app_config.h — 应用级配置:音频采样源、资源分区、UI/音频预留区(产品生命周期最大情况定义)
  2. board/wl83/sdk_config.h — SDK 功能开关:蓝牙、网络、RCSP、LE Audio 等模块级使能
  3. board/wl83/board_config.h — 板级配置:引脚复用、外设(DAC/ADC/IIS/USB/Flash)、板型差异

app_config.h 首先定义音频编码采样源枚举,并声明解码播放走 DAC:

#define AUDIO_ENC_SAMPLE_SOURCE_MIC         0
#define AUDIO_ENC_SAMPLE_SOURCE_PLNK0       1
#define AUDIO_ENC_SAMPLE_SOURCE_PLNK1       2
#define AUDIO_ENC_SAMPLE_SOURCE_IIS0        3
#define AUDIO_ENC_SAMPLE_SOURCE_IIS1        4
#define AUDIO_ENC_SAMPLE_SOURCE_LINEIN      5

#define CONFIG_AUDIO_DEC_PLAY_SOURCE        "dac"

#include "sdk_config.h"
#include "board_config.h"

Source: app_config.h

设计意图: 编码采样源枚举允许同一套编码框架(audio_enc 任务)灵活切换输入——麦克风、两个 P-Link 端口、两路 IIS、LineIn——音箱产品的通话/录音/伴奏场景都依赖这个抽象。

功能开关的级联覆盖

app_config.h 还演示了"上层关闭功能时自动收紧下层"的级联覆盖模式:

#ifndef CONFIG_BT_ENABLE
#undef TCFG_APP_BT_EN
#define TCFG_APP_BT_EN                          0
#endif
#ifndef CONFIG_NET_ENABLE
#undef TCFG_APP_NET_MUSIC_EN
#define TCFG_APP_NET_MUSIC_EN                   0
#endif
#if !defined TCFG_PC_ENABLE || !TCFG_PC_ENABLE
#undef TCFG_APP_PC_EN
#define TCFG_APP_PC_EN                          0
#endif

Source: app_config.h

设计意图: 当 SDK 级宏(CONFIG_BT_ENABLE、CONFIG_NET_ENABLE)被关闭时,应用层对应功能自动失效,避免"SDK 未编译蓝牙但应用仍尝试初始化蓝牙"的编译/运行错误。这是典型的防御性配置设计——功能开关只在最底层(sdk_config)定义一次真值,上层全部以"未定义即禁用"的规则级联。

Flash / SDNAND 资源分区

app_config.h 中针对 CONFIG_SDFILE_EXT_ENABLE(SDNAND 扩展文件系统)定义了详细的分区参数,包括 16MB Flash 容量、HFS/HFAT/FAT1 三段布局及簇大小自适应计算(CONFIG_SDNAND_HFAT_CLUSTER_SIZE 依据分区长度在 0x1~0x40 之间取档,保证簇大小与分区规模匹配、减少内部碎片)。

同时,文件头部注释清晰描述了 Flash 尾部预留区布局:末尾 4K 保留给配置存储(禁止覆盖),其前依次是 UI 资源包(CONFIG_UI_PACKRES_LEN)与音频资源包(CONFIG_AUDIO_PACKRES_LEN):

/*
#------------------------------|
#  (其他预留区配置项)          |
#------------------------------|<----CONFIG_UI_PACKRES_ADR - CONFIG_AUDIO_PACKRES_LEN = CONFIG_AUDIO_PACKRES_ADR
#  (CONFIG_AUDIO_PACKRES_LEN)  |
#------------------------------|<----__FLASH_SIZE__ - 0x1000 - CONFIG_UI_PACKRES_LEN = CONFIG_UI_PACKRES_ADR
#  (CONFIG_UI_PACKRES_LEN)     |
#------------------------------|<----__FLASH_SIZE__ - 0x1000
#  (4K Reserved)               |
#------------------------------+<----__FLASH_SIZE__
*/

Source: app_config.h

设计意图: 预留区地址由 __FLASH_SIZE__ 从尾部倒推计算,而不是从头部顺序分配——这样 UI/音频资源包扩容时不需要搬动前面的固件分区,只需调整长度宏即可,适合产品生命周期内 UI 资源反复增删的迭代节奏。

构建系统与工程编译宏

Code::Blocks 工程(AC792N_WIFI_SOUNDBOX.cbp)

方案以 Code::Blocks 工程文件描述编译参数。编译器为 pi32v2_r3_empty_compiler,输出 sdk.elf(../../../../cpu/wl83/tools/sdk.elf),优化级别 -Oz(尺寸优先)、开启 LTO(-flto)、-ffunction-sections / -fdata-sections 便于链接期裁剪。工程通过 -D 宏直接定义了方案形态:

<Add option="-DCONFIG_RELEASE_ENABLE" />
<Add option="-DCONFIG_CPU_WL83" />
<Add option="-DMAX_AUDIO_ADC_CHANNEL_NUM=2" />
<Add option="-DCONFIG_UCOS_ENABLE" />
<Add option="-DCONFIG_THREAD_ENABLE" />
<Add option="-D__GCC_PI32V2__" />
<Add option="-DCONFIG_NEW_ECC_ENABLE" />
<Add option="-DCONFIG_WIFI_SOUNDBOX_PROJECT_ENABLE" />
<Add option="-DVM_MAX_PAGE_ALIGN_SIZE_CONFIG=64*1024" />
<Add option="-DVM_MAX_SECTOR_ALIGN_SIZE_CONFIG=64*1024" />
<Add option="-DVM_ITEM_MAX_NUM=256" />
<Add option="-DPJ_LINUX=1" />
<Add option="-DPJ_M_I386=1" />
<Add option="-DRLOTTIE_COMMIT_HASH=&quot;492fbb753924ae7cad27072a2b6ddedde88dc4bd&quot;" />
<Add option="-DFREETYPE_COMMIT_HASH=&quot;ef54557bda3b17da1b7e42e8e207efd1842bcc05&quot;" />
<Add option="-DFT2_BUILD_LIBRARY" />
<Add option="-DLVGL_COMMIT_HASH=&quot;release/v8.4_2409c8dfc6b8d9ae3f7970e1c333e743e0fd2911&quot;" />

Source: AC792N_WIFI_SOUNDBOX.cbp

编译宏含义:

宏含义
CONFIG_WIFI_SOUNDBOX_PROJECT_ENABLE方案标识宏:把 SDK 编译为 wifi_soundbox 音箱形态,是区分于 wifi_camera / wifi_bbm 的关键
CONFIG_CPU_WL83目标芯片平台 wl83
CONFIG_UCOS_ENABLE / CONFIG_THREAD_ENABLE启用 uC/OS 与线程接口(对应 task_info_table 的调度)
MAX_AUDIO_ADC_CHANNEL_NUM=2最多 2 路 ADC 音频采样通道
CONFIG_NEW_ECC_ENABLE启用新版 ECC(Flash 坏块/纠错管理)
VM_MAX_PAGE_ALIGN_SIZE_CONFIG=64*1024、VM_MAX_SECTOR_ALIGN_SIZE_CONFIG=64*1024、VM_ITEM_MAX_NUM=256虚拟机(VM,掉电保存的参数存储)页/扇区对齐与条目上限
PJ_LINUX=1 / PJ_M_I386=1pjlib(SIP/网络协议栈)以 Linux 兼容模式编译
LVGL_COMMIT_HASH / FREETYPE_COMMIT_HASH / RLOTTIE_COMMIT_HASHUI 渲染依赖的第三方库版本锁定(LVGL v8.4、FreeType、Rlottie 动效)

工程同时引入了完整的三方依赖头文件路径:蓝牙(btstack、btctrler)、网络(pjsip、pjmedia、pjnath)、米家(mijia)、支付宝(alipay)、RCSP(杰理私有协议,含 rcsp_update 升级、file_transfer 文件传输、external_flash 等子模块)、USB(device/host)、更新(update)。

Source: AC792N_WIFI_SOUNDBOX.cbp

特性模块(audio/)

方案差异化的音频体验由 audio/ 目录四个模块提供:

文件职责说明
mic_effect.c麦克风音效与 mic_effect 任务(优先级 26)配套,提供人声美化/混响等处理
scene_switch.c场景切换在不同音频场景(音乐/通话/提示音)间切换 DAC 通路与处理链
tone_table.c提示音表定义按键音/状态提示音的音符与时长表
vol_sync.c音量同步在蓝牙音量、网络音量、本地音量之间同步,保证多音源切换时音量一致

这些模块由 app_main.c 引用(#include "mic_effect.h"、#include "audio_config.h"),并与 app_msg.c 的消息分发协同:例如按键事件触发 tone_table 播放提示音,蓝牙事件触发 vol_sync 同步音量,通话事件触发 scene_switch 切换场景。

配置选项速查

配置项(宏)位置默认/取值说明
CONFIG_WIFI_SOUNDBOX_PROJECT_ENABLE.cbp定义方案标识,启用音箱形态
CONFIG_CPU_WL83.cbp定义wl83 平台
MAX_AUDIO_ADC_CHANNEL_NUM.cbp2ADC 采样通道数上限
VM_MAX_PAGE_ALIGN_SIZE_CONFIG.cbp64*1024VM 页对齐大小
VM_MAX_SECTOR_ALIGN_SIZE_CONFIG.cbp64*1024VM 扇区对齐大小
VM_ITEM_MAX_NUM.cbp256VM 条目上限
CONFIG_AUDIO_DEC_PLAY_SOURCEapp_config.h"dac"解码播放输出设备
AUDIO_ENC_SAMPLE_SOURCE_*app_config.h0-5编码采样源:MIC/PLNK0/PLNK1/IIS0/IIS1/LINEIN
TCFG_APP_BT_ENapp_config.h1/0蓝牙功能(受 CONFIG_BT_ENABLE 级联控制)
TCFG_APP_NET_MUSIC_ENapp_config.h1/0网络音乐(受 CONFIG_NET_ENABLE 级联控制)
TCFG_APP_PC_ENapp_config.h1/0PC 模式(受 TCFG_PC_ENABLE 级联控制)
CONFIG_SDFILE_EXT_ENABLEapp_config.h条件定义启用 SDNAND 扩展文件系统与分区
__FLASH_SIZE__app_config.h16*1024*1024Flash 总容量(SDNAND 模式)
CONFIG_UI_PACKRES_LEN / CONFIG_AUDIO_PACKRES_LENapp_config.h按产品定义UI/音频资源包长度(预留区倒推)
TCFG_LOCAL_TWS_ENABLEsdk_config.h0/1本地 TWS 双音箱
TCFG_LE_AUDIO_STREAM_ENABLEsdk_config.h0/1LE Audio 流(wireless_trans.h)
THIRD_PARTY_PROTOCOLS_SEL & MULTI_BOX_ADV_ENsdk_config.h位掩码多音箱广播(multi_box_adv)
RCSP_MODE / RCSP_FILE_OPTsdk_config.h0/1RCSP 协议及文件传输/升级
TEE_ENABLEsdk_config.h0/1TEE 安全核任务(tee_core0/1)

表中 sdk_config.h 项依据 app_main.c 的条件编译引用(app_main.c)整理;board/wl83/sdk_config.h 为最终真值定义处。

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

任务调度与优先级倒置风险

  • task_info_table 中音频任务(dac=22、jlstream=23、mic_effect/audio_enc/aec=26)优先级高于应用任务 app_core=15。若应用层在回调中执行阻塞操作(如 Flash 擦写、文件系统 IO),会延迟音频任务——源码通过注释明确"file_dec 不打断 jlstream"、"提高编码优先级避免 DAC 缓冲过大",说明设计者已按实时性排序优先级;扩展时新增任务应遵循"音频链路 > 应用逻辑 > 低优先级杂务"的层级,避免在 app_core 或更低优先级任务中做长阻塞。
  • kws=3(关键词唤醒)与 smart_voice=11 优先级很低,这是功耗优先的设计:唤醒监听只在空闲时运行;若产品需要"随时唤醒",需评估唤醒延迟是否可接受。

中断与任务并发

  • 蓝牙中断全部固定 CPU0(优先级 5),CPU_CORE_NUM == 1 时哨兵行 { -2, -2, -2 } 之后的中断强制收敛到 CPU0。扩展提示:若新增外设中断(如 SPI 触摸屏),需在 irq_info_table 中显式声明核与优先级,否则按哨兵规则默认注册到 CPU0,可能与蓝牙中断产生竞争。
  • 单核模式下 IRQ_SOFT5/IRQ_SOFT4 分别注册到 CPU0/CPU1 用于核间通信,核间共享数据必须使用系统提供的临界区/信号量原语,不要直接跨核访问静态缓冲区。

资源边界

  • app_core 消息队列仅 1024 字节,高频率事件(如持续按键、网络状态抖动)可能造成队列溢出丢消息;sys_event 等无队列任务依赖事件优先级抢占,阻塞其处理会引发系统事件堆积。
  • Flash 尾部 4K 为配置存储保留区,禁止覆盖(app_config.h 注释明确说明);UI/音频资源包长度按"产品生命周期最大情况"定义,改小长度宏会压缩预留区,需确认不会与固件分区重叠。

条件编译的级联风险

app_config.h 采用"未定义即禁用"的级联规则(CONFIG_BT_ENABLE → TCFG_APP_BT_EN 等)。注意:#ifndef CONFIG_BT_ENABLE 的判断意味着"只要该宏被定义(即使为 0),应用开关就保持原值"——修改 sdk_config.h 时若以 #define CONFIG_BT_ENABLE 0 方式关闭功能,应用层开关不会被自动清零,需要同步修改应用配置。

性能与运维考量

  • 编译期优化:-Oz(尺寸优先)+ LTO + -ffunction-sections/-fdata-sections 面向 Flash 容量敏感的音箱产品;-Wframe-larger-than=2560 告警阈值提示栈帧过大的函数(配合 task_info_table 的静态栈,避免栈溢出越界到相邻任务)。
  • 静态资源预分配:所有关键任务(app_core、sys_event、systimer、sys_timer)的 TCB/栈/队列均为静态数组,运行时零动态分配,保证长时间运行的稳定性——这对音箱这类 7x24 待机产品至关重要。
  • 升级链路:uda_main(7000 字节大栈)、update、dw_update、rcsp(RCSP 升级/文件传输)等任务构成 OTA 能力;升级过程中 update/dw_update 与音频任务并发,若升级失败需回滚,依赖 Flash ECC(CONFIG_NEW_ECC_ENABLE)与 VM 配置存储。

扩展点

  1. 新增音频场景:在 audio/scene_switch.c 的场景枚举中扩展,并在 app_msg.c 的事件分发中接入触发条件;同步调整 jlstream_node_cfg.h 的音频节点拓扑。
  2. 新增音源:app_config.h 的 AUDIO_ENC_SAMPLE_SOURCE_* 枚举已预留 PLNK0/1、IIS0/1、LINEIN 等输入,编码侧无需改动,只需在板级(board_config.h/board_develop.c)使能对应输入通路。
  3. 自定义提示音:修改 audio/tone_table.c 的音符-时长表,无需改动播放框架。
  4. 新增产品型号:board/wl83/ 下已存在 board_develop_AC7922C.h、board_develop_AC7925A.h、board_develop_AC7925B.h、board_develop_AC7926A.h 等多型号差异头文件,新型号以相同模式增加板级头文件并在 board_develop.c 中按芯片型号条件编译。
  5. 接入第三方协议:工程已预置 mijia(米家)、alipay(支付宝)、RCSP 等协议头文件路径,通过 THIRD_PARTY_PROTOCOLS_SEL 位掩码(如 MULTI_BOX_ADV_EN 多音箱广播)按位启用。

测试与验证

  • 构建验证:make ac792n_wifi_soundbox 产出 cpu/wl83/tools/sdk.elf(.cbp 中 output 定义),配合工程工具链完成编译/烧录。
  • 功能验证建议覆盖:蓝牙 A2DP 播放与音量同步(vol_sync)、网络音频播放(jlstream 优先级验证)、通话回声消除(aec)、麦克风音效(mic_effect)、按键提示音(tone_table)、场景切换(scene_switch)、RCSP OTA 升级链路。
  • 压力测试关注点:app_core 队列(1024 字节)在连续按键/网络事件下的丢包情况;Flash 尾部 4K 配置区的掉电写保护;多任务并发下的栈边界(-Wframe-larger-than 告警对应函数)。

Related Links

  • sdk/apps/wifi_soundbox/app_main.c — 方案入口:中断表、任务表与初始化
  • sdk/apps/wifi_soundbox/include/app_config.h — 应用配置:音频源、资源分区、预留区布局
  • sdk/apps/wifi_soundbox/board/wl83/AC792N_WIFI_SOUNDBOX.cbp — Code::Blocks 工程与编译宏
  • sdk/apps/wifi_soundbox/board/wl83/Makefile — 构建脚本
  • sdk/apps/wifi_soundbox/board/wl83/sdk_config.h — SDK 功能开关总配置
  • sdk/apps/wifi_soundbox/board/wl83/board_config.h — 板级外设配置
  • sdk/apps/wifi_soundbox/app_msg.c — 消息分发
  • README.md — SDK 总览(wl83 平台、各方案构建命令)
  • project.jlproj — 工程定义(sdk=wifi_soundbox、默认变体)
Prev
WiFi 摄像头方案 (wifi_camera)
Next
WiFi 婴儿监护方案 (wifi_bbm)