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

    • SDK 概览与 AC791N 芯片平台
    • 环境搭建与编译指南
    • 烧录与固件升级
    • 工程结构导览
  • 产品方案应用

    • WiFi 摄像头方案
    • WiFi IPC 可视对讲方案
    • WiFi 故事机方案
    • 扫码枪 HID 方案
    • 开发板示例工程
  • 公共应用组件

    • 语音识别 ASR 引擎
    • LLM 与 AI 语音助手接入
    • 摄像头传感器驱动
    • UI 显示框架与驱动
    • USB 主机与设备栈
    • 文件系统与存储管理
    • 系统服务与外设管理
    • 生产测试与射频工具
  • 蓝牙协议栈

    • 经典蓝牙 BR/EDR
    • BLE 低功耗蓝牙
    • 蓝牙 Mesh 网络
    • 蓝牙扩展协议(RCSP/广播/无线麦克风)
  • WiFi 与网络协议栈

    • WiFi 驱动与网络模式
    • lwIP TCP/IP 协议栈
    • 网络安全与加密库
    • 应用层网络协议
    • 流媒体与音视频传输
    • 云平台接入 SDK
    • P2P 远程访问与设备互联
  • 芯片平台与驱动

    • wl82 平台与硬件加速
    • 外设驱动框架
    • 平台配置与固件打包工具
  • 媒体与音频引擎

    • 音频编解码与音源
    • 音效处理引擎
    • 视频与图像处理
  • 操作系统与运行时

    • 实时操作系统与 POSIX 层
    • C/C++ 运行时库
  • 开发资源与文档

    • 文档与规格书
    • 公共示例工程
    • UI 资源工程与打包
    • SDK 辅助工具与脚本

WiFi 故事机方案

基于杰理 AC791N 系列(wl82 平台,双核浮点 DSP @ 320MHz)的儿童故事机/智能音箱参考方案,提供本地音乐播放、WiFi 网络音频、蓝牙、FM、AI 语音交互等完整能力,源码位于 apps/wifi_story_machine/,编译目标为 ac791n_wifi_story_machine。

Purpose and Scope

本文档介绍 apps/wifi_story_machine/ 方案的整体架构与实现,覆盖:

  • 应用入口 app_main.c 的启动流程、中断/任务表设计
  • 核心音乐应用 app_music.c(基础版)的播放模式、提示音系统、内容分类机制
  • DUI 语音 SDK 版本 app_music_dui.c 与腾讯音乐版本 app_music_tencent.c 的差异
  • wl82 平台板级配置(board/wl82/)与多板型适配

不涉及的内容:WiFi 协议栈底层(lwip/tcpip、wifi_connect)、蓝牙协议栈细节、音频编解码器实现、IPC 摄像头方案(见 WiFi IPC 方案 相关页面)、扫码盒方案等,这些属于独立的子系统页面。

概述

WiFi 故事机方案是杰理 AC79NN SDK 中「WiFi 音频方案」的产品级参考实现,面向儿童故事机、智能音箱、网络音频播放三类典型产品形态。方案的核心设计思路是:

  1. 单入口多应用调度:app_main() 通过 intent/action 机制启动 app_music 应用,由应用层按编译宏(CONFIG_DUI_SDK_ENABLE、CONFIG_TVS_SDK_ENABLE、CONFIG_NET_ENABLE 等)切换不同产品变体。
  2. 全场景音频覆盖:同一框架内支持本地存储(Flash/SD 卡/U 盘)音乐、WiFi 网络下载播放、蓝牙 A2DP、FM 收音、AI 语音(ASR/翻译/识图)、闹钟/提醒等模式。
  3. 分层任务体系:通过 task_info_table 静态声明全部系统任务(音频服务、编码器、WiFi、蓝牙、UI),配合中断表实现 CPU0/CPU1 双核负载分配。
  4. 提示音统一管理:local_prompt_table 将 60+ 种应用场景枚举映射到 MP3 提示音文件,为配网、蓝牙、AI 等流程提供一致的用户反馈。

该方案编译命令为 make ac791n_wifi_story_machine,支持 AC7911B / AC7912A / AC7913A / AC7915A / AC7915B / AC7916A 等芯片型号。

架构

flowchart TD
    subgraph sg_App["应用层 apps/wifi_story_machine/"]
        app_main["app_main.c<br/>入口 / 中断表 / 任务表"]
        app_music["app_music.c<br/>基础版音乐应用"]
        app_dui["app_music_dui.c<br/>DUI 语音版本"]
        app_tx["app_music_tencent.c<br/>腾讯音乐版本"]
    end

    subgraph sg_Svc["系统服务层"]
        audio_srv["audio_server / audio_mix"]
        encoder["speex/mp3/opus/amr 编码器"]
        wifi_svc["WiFi 任务<br/>tasklet / RtmpMlmeTask / RtmpCmdQTask"]
        bt_svc["BT 任务<br/>btstack / btctrler"]
        net_svc["网络服务<br/>net_download / ai_server / config_network"]
        ui_svc["UI 服务<br/>ui / lcd_task / te_task"]
    end

    subgraph sg_Platform["平台层 board/wl82/"]
        board_cfg["board_7911B.c / 7911D / 7912D / 7913A<br/>板级配置与 *_cfg.h"]
    end

    subgraph sg_Dev["硬件资源"]
        dev_flash["Flash / SD 卡 / U 盘"]
        dev_wifi["WiFi 射频"]
        dev_bt["蓝牙射频"]
        dev_audio["音频 DAC / 功放 / MIC"]
        dev_lcd["LCD 屏 / LED"]
    end

    app_main -->|"start_app(ACTION_MUSIC_PLAY_MAIN)"| app_music
    app_music -->|"CONFIG_DUI_SDK_ENABLE"| app_dui
    app_music -->|"腾讯音乐宏"| app_tx
    app_music --> audio_srv
    app_music --> encoder
    app_music --> wifi_svc
    app_music --> bt_svc
    app_music --> net_svc
    app_music --> ui_svc
    app_main --> board_cfg
    board_cfg --> dev_flash
    wifi_svc --> dev_wifi
    bt_svc --> dev_bt
    audio_srv --> dev_audio
    ui_svc --> dev_lcd

架构说明

  • 应用层:app_main.c 是唯一入口,负责系统级初始化(中断表、任务表、默认事件处理),随后把控制权交给 app_music 应用。app_music.c 为不含云端 SDK 的基础版;编译期宏 CONFIG_DUI_SDK_ENABLE 会选择 app_music_dui.c(杰理 DUI 语音交互 SDK 版),腾讯音乐定制版由 app_music_tencent.c 承载。三者共享 app_music.h 定义的数据结构与事件接口。
  • 系统服务层:音频服务、编码器、WiFi/BT 协议栈任务、网络下载/AI 服务、UI 服务均由任务表统一创建,应用通过系统事件(sys_event)与这些服务通信。
  • 平台层:board/wl82/ 下每个 board_xxx.c 对应一款芯片/板型,配套 board_xxx_cfg.h 声明外设配置(如 board_7911B_dui_cfg.h 为 DUI 版、board_7911B_develop_cfg.h 为开发板版本)。

应用启动与任务系统

入口流程 app_main()

app_main() 是方案的应用级入口,位于 app_main.c。它构造一个 struct intent 并把 action 设为 ACTION_MUSIC_PLAY_MAIN 后调用 start_app(),从而把主界面切换到音乐播放应用:

void app_main()
{
    struct intent it;

    puts("------------- wifi_story_machine app main-------------\n");

    init_intent(&it);
    it.name = "app_music";
    it.action = ACTION_MUSIC_PLAY_MAIN;
    start_app(&it);

#if defined CONFIG_BT_ENABLE && !defined CONFIG_WIFI_ENABLE
    extern void bt_ble_module_init(void);
    bt_ble_module_init();
#endif
}

Source: app_main.c

设计意图:通过 intent/action 机制解耦「系统入口」与「具体应用」。故事机产品默认落到音乐主界面;当编译配置为「仅蓝牙、无 WiFi」的变体时(CONFIG_BT_ENABLE && !CONFIG_WIFI_ENABLE),额外初始化 BLE 模块,保证低配产品也能使用蓝牙功能。

中断表 irq_info_table

方案为双核(CPU0/CPU1)设计了中断注册表,指定每个中断运行在哪个核、优先级如何,用于把实时性要求高的中断与业务逻辑隔离:

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

Source: app_main.c

设计意图:CONFIG_IPMASK_ENABLE 开启「不可屏蔽中断」模式,用于必须写 Flash 且不容打断的场合(要求中断函数及其依赖全部位于内部 RAM);CPU_CORE_NUM == 1 时通过哨兵行 {-2, -2, -2} 把表中此前的中断按指定核注册,其余全部强制到 CPU0,避免单核产品上出现跨核调度问题。

任务表 task_info_table

task_info_table 以静态数组形式声明了整个系统运行所需的全部任务(优先级、栈大小、消息队列),由 OS 在启动阶段统一创建。关键任务分组如下:

分组任务名优先级栈大小说明
应用核心app_core152048应用主任务,带 1024 字消息队列
事件sys_event29512系统事件分发
定时器systimer / sys_timer14 / 9256 / 512系统时钟与软件定时器
音频服务audio_server / audio_mix16 / 28512音频播放服务与混音
编码器speex_encoder ~ adpcm_encoder 等 12 个12~14256~1536各类语音/音频编码器
回声/降噪echo_deal111024回声消除
UACuac_play0/1、uac_record0/126512USB 音频设备
RCSPrcsp / dev_mg4 / 3768 / 512杰理 RCSP 私有协议与设备管理(RCSP_MODE)
WiFitcpip_thread、tasklet、RtmpMlmeTask、RtmpCmdQTask、wl_rx_irq_thread16/10/17/17/7256~1400WiFi 协议栈与收发任务(CONFIG_WIFI_ENABLE)
蓝牙btctrler、btstack、btencry19/18/14512~1024蓝牙控制器/协议栈(CONFIG_BT_ENABLE,双核下加 #C0 前缀指定核)
视频video_server、net_video_server、jpg_dec 等10~20256~1024视频/图片解码服务(预留给带屏/摄像头变体)
UIui、lcd_task_0/1、te_task8~21768~1024LCD 显示与触摸(CONFIG_UI_ENABLE)

Source: app_main.c

关键静态任务堆栈(app_core、wifi_tasklet、wifi_cmdq、wifi_mlme、wifi_rx 等)以静态数组预分配,配合 ALIGE(4) 对齐,避免运行时堆分配碎片化——这对嵌入式长期运行稳定性至关重要。WiFi 收发任务(tasklet 优先级 10)的优先级刻意可调,注释明确指出"通过调节任务优先级平衡 WIFI 收发占据总 CPU 的比重",这是双核音频 + WiFi 并发场景下的性能调优入口。

默认事件处理 app_default_event_handler

当所有活跃应用的 sys_event 处理函数都返回 false 时,系统回调默认处理器:

void app_default_event_handler(struct sys_event *event)
{
    switch (event->type) {
    case SYS_KEY_EVENT:
        break;
    case SYS_TOUCH_EVENT:
        break;
    case SYS_DEVICE_EVENT:
        break;
    case SYS_NET_EVENT:
        break;
    case SYS_BT_EVENT:
#if (RCSP_MODE)
        if (event->from == BT_EVENT_FROM_BLE_RCSP_UPDATE) {
            struct bt_event *e = (struct device_event *)event->payload;
            JL_rcsp_update_msg_deal(NULL, e->event, e->args);
        }
#endif
        break;
    default:
        ASSERT(0, "unknow event type: %s\n", __func__);
        break;
    }
}

Source: app_main.c

设计意图:事件处理采用「应用优先、系统兜底」的链式模型——app_music 等应用先消费事件,未消费的按键/触摸/设备/网络/蓝牙事件落到默认处理器。其中 RCSP 模式下 BLE 通道收到的 OTA 升级消息在此统一分发(JL_rcsp_update_msg_deal),保证升级协议消息在任何应用状态下都不会丢失。

核心音乐应用 app_music

编译变体选择

app_music.c 整体被 #if (!defined CONFIG_DUI_SDK_ENABLE) && (!defined CONFIG_TVS_SDK_ENABLE) 包裹,即:

  • 基础版(无云端 SDK):app_music.c 生效
  • DUI 语音版:定义 CONFIG_DUI_SDK_ENABLE,编译 app_music_dui.c
  • 腾讯音乐版:app_music_tencent.c(腾讯小微/QQ 音乐集成)

Source: app_music.c、app_music_dui.c

三个变体共享同一套 app_music_hdl 状态结构与 local_music_dec_ops 解码器接口,产品化时只需切换编译宏即可换用不同云端能力,应用框架与硬件驱动无需改动。

提示音系统 local_prompt_table

方案内置一张「场景枚举 → 提示音文件」映射表,覆盖电源、蓝牙、WiFi 配网、AI 交互、OTA、设备绑定等全部关键用户场景(约 60 项)。示例片段:

static const struct {
    APP_LOCAL_PROMPT_TYPE_E prompt_type;
    const char *file_name;
} local_prompt_table[] = {
    {APP_LOCAL_PROMPT_POWER_ON,                "PowerOn.mp3"},
    {APP_LOCAL_PROMPT_POWER_OFF,               "PowerOff.mp3"},
    {APP_LOCAL_PROMPT_PLAY_DOMAIN_MUSIC,       "004.mp3"},
    {APP_LOCAL_PROMPT_PLAY_DOMAIN_STORY,       "005.mp3"},
    {APP_LOCAL_PROMPT_PLAY_DOMAIN_SINOLOGY,    "006.mp3"},
    {APP_LOCAL_PROMPT_PLAY_DOMAIN_ENGLISH,     "007.mp3"},
    {APP_LOCAL_PROMPT_WIFI_CONNECTING,         "NetConnting.mp3"},
    {APP_LOCAL_PROMPT_WIFI_CONNECT_SUCCESS,    "NetCfgSucc.mp3"},
    {APP_LOCAL_PROMPT_WIFI_CONNECT_FAIL,       "NetCfgFail.mp3"},
    {APP_LOCAL_PROMPT_WIFI_CONFIG_START,       "NetCfgEnter.mp3"},
    {APP_LOCAL_PROMPT_OTA_UPGRADE_START,       "OtaInUpdate.mp3"},
    {APP_LOCAL_PROMPT_ALARM,                   "reminder.mp3"},
    {APP_LOCAL_PROMPT_SCHEDULE,                "schedule.mp3"},
    {APP_LOCAL_PROMPT_ENTER_AUX_MUSIC_MODE,    "LineinMusic.mp3"},
    {APP_LOCAL_PROMPT_ENTER_BT_EMITTER_MODE,   "EmitterOn.mp3"},
};

Source: app_music.c

设计意图:提示音资源集中管理,文件存放在本地文件系统(Flash),由 app_music_play_voice_prompt() 统一播放;产品定制时只需替换 MP3 资源或调整映射,无需改动业务逻辑。DUI 版(app_music_dui.c)保留了同样结构的提示音表,仅音量/按键屏蔽策略不同。

内容分类:儿歌 / 故事 / 国学 / 英语

故事机的核心体验是「按内容领域点播」。方案把本地存储目录按领域分类,dir_name_chars 存放各分类目录名的 GBK 编码字节,dir_name_chars_english 存放英文别名:

static const u8 dir_name_chars[][8] = {
    { 0x3F, 0x51, 0x4C, 0x6B, 0x00, 0x00 },   //儿歌
    { 0x45, 0x65, 0x8B, 0x4E, 0x00, 0x00 },   //故事
    { 0xFD, 0x56, 0x66, 0x5B, 0x00, 0x00 },   //国学
    { 0xF1, 0x82, 0xED, 0x8B, 0x00, 0x00 },   //英语
};

static const char *dir_name_chars_english[] = {
    "CHILD",  //儿歌
    ...
};

Source: app_music.c

设计意图:以固定目录名约定(儿歌/故事/国学/英语 + 英文别名)实现内容管理——用户把音频文件拷入对应目录即可被故事机自动识别为对应领域,播放领域内容时播放对应的领域提示音(004.mp3~007.mp3)。这种「目录即分类」的设计降低了内容生产与用户使用的门槛。

音量管理策略

基础版与 DUI 版采用不同的音量策略,体现两种产品定位:

配置项基础版 app_music.cDUI 版 app_music_dui.c说明
VOLUME_STEP55每次按键音量步进
MIN_VOLUME_VALUE00最小音量
MAX_VOLUME_VALUE10080最大音量(DUI 版限 80 保护听力)
INIT_VOLUME_VALUE6015开机默认音量(DUI 版默认较低)
CONFIG_STORE_VOLUME定义未定义基础版掉电保存音量
CONFIG_PLAY_PROMPT_DISABLE_KEY10播放提示音时是否屏蔽按键

Source: app_music.c、app_music_dui.c

设计意图:儿童产品的音量上限、默认音量都比通用音箱保守(80 vs 100、15 vs 60),体现安全设计考量;提示音播放期间屏蔽按键(基础版)可防止用户在提示音播放时误操作打断反馈。

解码缓冲区配置

#if defined CONFIG_NO_SDRAM_ENABLE
#define DEC_BUF_LEN      6 * 1024
#else
#define DEC_BUF_LEN      12 * 1024
#endif

Source: app_music.c

设计意图:解码缓冲区大小根据是否外挂 SDRAM 自动切换(6KB 无 SDRAM / 12KB 有 SDRAM),是内存受限场景下「以空间换流畅度」的典型权衡——无 SDRAM 的低成本板型牺牲部分抗抖动能力换取 BOM 成本下降。

核心流程

系统启动 → 音乐播放主界面

sequenceDiagram
    participant Boot as 系统启动/OS
    participant Main as app_main()
    participant Action as action 框架
    participant Music as app_music 应用
    participant Audio as audio_server
    participant Net as 网络服务 (WiFi/下载)

    Boot->>Main: 创建 init 任务并调用 app_main()
    Main->>Main: 注册中断表 irq_info_table
    Main->>Main: 注册任务表 task_info_table
    Boot->>Boot: 创建全部系统任务 (audio/wifi/bt/ui...)
    Main->>Action: init_intent(&it) + start_app(&it)
    Action->>Music: 切换到 app_music (ACTION_MUSIC_PLAY_MAIN)
    Music->>Music: 初始化 app_music_hdl 状态
    Music->>Audio: 打开音频设备 / 设置初始音量
    Music->>Music: 播放 PowerOn.mp3 提示音
    alt WiFi 已配网
        Music->>Net: 连接路由器 / 恢复网络播放
    else 首次开机
        Music->>Music: 播放 NetEmpty.mp3 提示进入配网
    end
    Music-->>Boot: 主界面就绪,等待按键/事件

事件处理链

系统事件(按键、设备插拔、网络状态、蓝牙状态)的分发遵循「应用优先 → 默认兜底」链:

flowchart TD
    Evt["sys_event<br/>(key/device/net/bt/touch)"] --> AppHandler{"app_music 事件<br/>处理函数返回?"}
    AppHandler -->|"true (已消费)"| Done1["流程结束"]
    AppHandler -->|"false (未消费)"| Default["app_default_event_handler<br/>系统兜底"]
    Default -->|"SYS_BT_EVENT + RCSP"| Rcsp["JL_rcsp_update_msg_deal<br/>BLE OTA 升级消息"]
    Default -->|"其他"| Done2["丢弃/记录"]

Source: app_main.c

板级适配 board/wl82/

方案在 apps/wifi_story_machine/board/wl82/ 下提供多款板型配置,实现「一套应用、多板复用」:

文件芯片/板型说明
board_7911B.c + board_7911B_develop_cfg.hAC7911B开发板配置
board_7911B_dui_cfg.hAC7911BDUI 语音 SDK 专用配置
board_7911B0/7911B8/7911BA/7911BB_cfg.hAC7911B不同封装/型号子配置
board_7911D.c + board_7911D_cfg.hAC7911D7911D 板型
board_7912AB/7912D_cfg.h、board_7912D.cAC7912A/D7912 系列
board_7913A.c + board_7913A6_cfg.hAC7913A7913A 板型
AC791N_WIFI_STORY_MACHINE.cbp—Code::Blocks 工程文件

Source: apps/wifi_story_machine/board/wl82/

板级头文件声明外设引脚、Flash/PSRAM 大小、电源管理参数等硬件相关配置;board_7911B_dui_cfg.h 与 board_7911B_develop_cfg.h 的分离表明:同一颗芯片可因产品软件形态(DUI 语音 vs 基础功能)使用不同的板级配置,编译时通过工程选择对应头文件即可。

使用示例

示例 1:切换播放模式(本地 → 网络)

app_music.c 中通过 app_music_play_mode_switch_notify() 等接口在各播放模式间切换,网络播放依赖 network_download/net_download.h 与 ai_server:

#ifdef CONFIG_NET_ENABLE
#include "network_download/net_download.h"
#include "server/ai_server.h"
#include "lwip/netdb.h"
#include "net/assign_macaddr.h"
#include "net/config_network.h"
#endif

Source: app_music.c

网络能力仅在 CONFIG_NET_ENABLE 下编译,保证无网络需求的产品(纯本地/蓝牙版)不引入 lwip 与下载栈,减小固件体积。

示例 2:蓝牙与音频服务联动

蓝牙 A2DP 播放通过 get_bt_music_dec_ops() 与 app_music_bt_event_handler() 接入统一解码框架:

#ifdef CONFIG_BT_ENABLE
#include "btstack/avctp_user.h"
#include "btctrler/btctrler_task.h"
#include "classic/hci_lmp.h"
#include "bt_ble/bt_emitter.h"

extern const struct music_dec_ops *get_bt_music_dec_ops(void);
extern void bt_connection_disable(void);
extern void bt_connection_enable(void);
extern int app_music_bt_event_handler(struct sys_event *event);
#endif

Source: app_music.c

设计意图:music_dec_ops 是解码器抽象接口,本地文件、蓝牙 A2DP、网络流都实现同一组操作(open/decode/close),因此上层播放控制(暂停/切歌/音量)无需感知音源类型,这是「多音源统一播放」架构的关键。

示例 3:DUI 版本的应用结构

DUI 版与基础版共享头文件与提示音机制,仅在编译宏与音量策略上分化:

#if (defined CONFIG_DUI_SDK_ENABLE)

#ifdef CONFIG_NET_ENABLE
#include "network_download/net_download.h"
#include "server/ai_server.h"
#include "lwip/netdb.h"
#include "net/assign_macaddr.h"
#include "net/config_network.h"
#endif
...
static const struct {
    APP_LOCAL_PROMPT_TYPE_E prompt_type;
    const char *file_name;
} local_prompt_table[] = {
    {APP_LOCAL_PROMPT_POWER_ON,                "PowerOn.mp3"},
    ...
};

Source: app_music_dui.c

DUI(Device User Interface)是杰理的语音交互 SDK,负责唤醒词、ASR 识别与云端对话;本文件是它在故事机产品上的应用适配层。

配置选项

以下宏在编译期通过 app_config.h / 工程配置控制方案行为:

配置宏取值默认/典型值作用
CONFIG_WIFI_ENABLE定义/未定义定义使能 WiFi 协议栈任务(tasklet/RtmpMlmeTask/RtmpCmdQTask/wl_rx_irq_thread)
CONFIG_BT_ENABLE定义/未定义定义使能蓝牙任务(btctrler/btstack/btencry)
CONFIG_NET_ENABLE定义/未定义定义使能网络应用层(net_download/ai_server/config_network)
CONFIG_DUI_SDK_ENABLE定义/未定义未定义切换到 DUI 语音 SDK 版本(app_music_dui.c)
CONFIG_TVS_SDK_ENABLE定义/未定义未定义切换到腾讯云 SDK 版本(app_music_tencent.c)
CONFIG_UI_ENABLE定义/未定义视板型使能 UI 任务(ui/lcd_task/te_task)与 LCD 驱动
CONFIG_IPMASK_ENABLE定义/未定义未定义不可屏蔽中断模式(中断内可写 Flash)
CPU_CORE_NUM1 / 22(wl82 双核)运行核数,影响中断表与任务核分配
RCSP_MODE0 / 1按产品杰理 RCSP 私有协议(rcsp/dev_mg 任务、BLE OTA)
TCFG_DEV_MANAGER_ENABLE0 / 1按产品设备管理器(file_bs/ftran_back 任务)
CONFIG_NO_SDRAM_ENABLE定义/未定义未定义无 SDRAM 低配板型,DEC_BUF_LEN 降为 6KB
VOLUME_STEP / MIN/MAX/INIT_VOLUME_VALUE整型5 / 0 / 100(80) / 60(15)音量步进与上下限、初始值(DUI 版更保守)
CONFIG_STORE_VOLUME定义/未定义基础版定义掉电保存音量
CONFIG_PLAY_PROMPT_DISABLE_KEY0 / 11(基础版)/ 0(DUI 版)播放提示音期间是否屏蔽按键

Source: app_main.c、app_music.c

API 参考

void app_main(void)

方案应用入口,由系统在 init 任务中调用。

  • 职责:初始化意图并启动 app_music 应用(ACTION_MUSIC_PLAY_MAIN);当配置为「仅蓝牙无 WiFi」时初始化 BLE 模块。
  • 位置:app_main.c

void app_default_event_handler(struct sys_event *event)

默认系统事件处理函数,在所有活跃应用均未消费事件时被调用。

  • 参数:event — 系统事件(SYS_KEY_EVENT/SYS_TOUCH_EVENT/SYS_DEVICE_EVENT/SYS_NET_EVENT/SYS_BT_EVENT)
  • 行为:SYS_BT_EVENT 且来自 BT_EVENT_FROM_BLE_RCSP_UPDATE 时调用 JL_rcsp_update_msg_deal() 处理 RCSP OTA 消息;未知事件类型触发 ASSERT(0)。
  • 位置:app_main.c

任务/中断注册表(数据结构)

  • const struct irq_info irq_info_table[]:中断号 → 优先级(0-7) → 目标核;哨兵行 {-1,-1,-1} 结尾,{-2,-2,-2} 表示其后所有中断强制 CPU0。
  • const struct task_info task_info_table[]:任务名 → 优先级 → 栈大小 → 队列大小(可选静态堆栈数组),{0,0} 结尾。
  • 位置:app_main.c

提示音接口(约定)

  • app_music_play_voice_prompt(const char *fname, void *dec_end_handler):播放指定提示音文件,可注册解码结束回调(声明于 app_music.c)。
  • local_prompt_table[]:APP_LOCAL_PROMPT_TYPE_E 枚举 → MP3 文件名映射,业务代码以枚举引用提示音,避免硬编码文件名。

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

失败模式

场景处理方式源码依据
WiFi 连接失败播放 NetCfgFail.mp3(APP_LOCAL_PROMPT_WIFI_CONNECT_FAIL),停留在配网/重试流程app_music.c
配网超时播放 NetCfgTo.mp3(APP_LOCAL_PROMPT_WIFI_CONFIG_TIMEOUT)app_music.c
首次开机未配网播放 NetEmpty.mp3(APP_LOCAL_PROMPT_WIFI_FIRST_CONFIG),引导进入配网app_music.c
AI 识别失败播放 AiAsrFail.mp3 / AiTransFail.mp3 / AiPicFail.mp3app_music.c
OTA 升级失败/成功播放 OtaFailed.mp3 / OtaSuccess.mp3app_music.c
低电量播放 LowBatLevel.mp3(提醒)/ LowBatOff.mp3(关机)app_music.c

边界情况

  • 无 SDRAM 板型:DEC_BUF_LEN 从 12KB 降为 6KB,解码抗抖动能力下降,网络播放建议选用带 SDRAM 板型。
  • 单核变体:CPU_CORE_NUM == 1 时中断表通过 {-2,-2,-2} 哨兵强制未列中断注册到 CPU0,WiFi/BT 任务与音频任务共享单核需注意优先级(tasklet 10、audio_server 16)。
  • 仅蓝牙无 WiFi 变体:app_main 中额外调用 bt_ble_module_init(),此时不含网络下载与配网流程。

并发与一致性

  • 双核中断隔离:IRQ_SOFT5_IDX 注册到 CPU0、IRQ_SOFT4_IDX 注册到 CPU1,软中断跨核分发避免同核竞争;不可屏蔽中断(CONFIG_IPMASK_ENABLE)要求中断代码与数据全部置于内部 RAM,防止访问外部总线被屏蔽。
  • 任务优先级分层:WiFi 收发(tasklet 10)优先级刻意低于音频服务(audio_server 16 等),保证 WiFi 重负载下音频不卡顿——注释明确说明该优先级是调优 WiFi/CPU 占比的旋钮。
  • RCSP OTA 消息串行化:BLE 升级消息统一经 app_default_event_handler → JL_rcsp_update_msg_deal 串行处理,避免与业务线程并发修改 Flash。
  • 提示音互斥:基础版 CONFIG_PLAY_PROMPT_DISABLE_KEY=1 在提示音播放期间屏蔽按键,防止提示音播放与用户操作竞争音频通道。

性能与运维

  • 内存规划:核心任务(app_core 2048 字栈 + 1024 字队列、uda_main 7000 字栈)全部静态预分配,运行期无堆碎片风险;WiFi/BT/编码器任务栈按 256~1536 字精细配置,说明该平台对 RAM 预算控制严格。
  • WiFi 收发占比调节:通过 tasklet 任务优先级(当前 10)平衡 WiFi 吞吐与音频实时性,是双核音频产品最重要的性能旋钮。
  • 编码器任务簇:speex/mp3/opus/amr/cvsd/vad/aec/dns/msbc/sbc/adpcm 12 个编码器任务按需编译,未使用的编码器可裁剪以释放 RAM。
  • 固件构建:make ac791n_wifi_story_machine 生成目标固件;工程文件 AC791N_WIFI_STORY_MACHINE.cbp 供 Code::Blocks 导入调试。
  • 升级通道:支持本地 update/dw_update 任务与 RCSP BLE OTA 双通道升级,升级全程有提示音反馈。

扩展点

  1. 新播放源:实现 struct music_dec_ops(参考 get_bt_music_dec_ops()),即可把新音源接入统一播放框架。
  2. 新提示音场景:在 APP_LOCAL_PROMPT_TYPE_E 枚举追加类型,并在 local_prompt_table 增加映射与 MP3 资源。
  3. 新内容领域:在 dir_name_chars / dir_name_chars_english 增加目录名(GBK 字节 + 英文别名),并在领域提示音表中补充提示音。
  4. 新板型:在 board/wl82/ 下新增 board_xxx.c + board_xxx_cfg.h,复用应用层与任务表,仅调整外设/内存配置。
  5. 云端变体:参照 CONFIG_DUI_SDK_ENABLE / 腾讯音乐宏的模式新增编译开关,接入新云端 SDK 时复用现有事件处理与提示音体系。
  6. 任务/中断定制:task_info_table 与 irq_info_table 是静态表,可按产品裁剪任务、调整优先级与核分配。

Related Links

  • SDK 概述(README) — 方案总览、wl82 平台与编译命令
  • WiFi 故事机方案目录 — 源码根目录
  • app_main.c — 入口、中断表、任务表
  • app_music.c — 基础版音乐应用
  • app_music_dui.c — DUI 语音 SDK 版
  • app_music_tencent.c — 腾讯音乐版
  • board/wl82 板级配置 — 多板型适配
  • 相关兄弟页面:WiFi IPC 方案(apps/wifi_ipc/)、扫码盒方案(apps/scan_box/)、11 个功能 demo(apps/demo/)
Prev
WiFi IPC 可视对讲方案
Next
扫码枪 HID 方案