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 音频方案」的产品级参考实现,面向儿童故事机、智能音箱、网络音频播放三类典型产品形态。方案的核心设计思路是:
- 单入口多应用调度:
app_main()通过 intent/action 机制启动app_music应用,由应用层按编译宏(CONFIG_DUI_SDK_ENABLE、CONFIG_TVS_SDK_ENABLE、CONFIG_NET_ENABLE等)切换不同产品变体。 - 全场景音频覆盖:同一框架内支持本地存储(Flash/SD 卡/U 盘)音乐、WiFi 网络下载播放、蓝牙 A2DP、FM 收音、AI 语音(ASR/翻译/识图)、闹钟/提醒等模式。
- 分层任务体系:通过
task_info_table静态声明全部系统任务(音频服务、编码器、WiFi、蓝牙、UI),配合中断表实现 CPU0/CPU1 双核负载分配。 - 提示音统一管理:
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_core | 15 | 2048 | 应用主任务,带 1024 字消息队列 |
| 事件 | sys_event | 29 | 512 | 系统事件分发 |
| 定时器 | systimer / sys_timer | 14 / 9 | 256 / 512 | 系统时钟与软件定时器 |
| 音频服务 | audio_server / audio_mix | 16 / 28 | 512 | 音频播放服务与混音 |
| 编码器 | speex_encoder ~ adpcm_encoder 等 12 个 | 12~14 | 256~1536 | 各类语音/音频编码器 |
| 回声/降噪 | echo_deal | 11 | 1024 | 回声消除 |
| UAC | uac_play0/1、uac_record0/1 | 26 | 512 | USB 音频设备 |
| RCSP | rcsp / dev_mg | 4 / 3 | 768 / 512 | 杰理 RCSP 私有协议与设备管理(RCSP_MODE) |
| WiFi | tcpip_thread、tasklet、RtmpMlmeTask、RtmpCmdQTask、wl_rx_irq_thread | 16/10/17/17/7 | 256~1400 | WiFi 协议栈与收发任务(CONFIG_WIFI_ENABLE) |
| 蓝牙 | btctrler、btstack、btencry | 19/18/14 | 512~1024 | 蓝牙控制器/协议栈(CONFIG_BT_ENABLE,双核下加 #C0 前缀指定核) |
| 视频 | video_server、net_video_server、jpg_dec 等 | 10~20 | 256~1024 | 视频/图片解码服务(预留给带屏/摄像头变体) |
| UI | ui、lcd_task_0/1、te_task | 8~21 | 768~1024 | LCD 显示与触摸(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.c | DUI 版 app_music_dui.c | 说明 |
|---|---|---|---|
VOLUME_STEP | 5 | 5 | 每次按键音量步进 |
MIN_VOLUME_VALUE | 0 | 0 | 最小音量 |
MAX_VOLUME_VALUE | 100 | 80 | 最大音量(DUI 版限 80 保护听力) |
INIT_VOLUME_VALUE | 60 | 15 | 开机默认音量(DUI 版默认较低) |
CONFIG_STORE_VOLUME | 定义 | 未定义 | 基础版掉电保存音量 |
CONFIG_PLAY_PROMPT_DISABLE_KEY | 1 | 0 | 播放提示音时是否屏蔽按键 |
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.h | AC7911B | 开发板配置 |
board_7911B_dui_cfg.h | AC7911B | DUI 语音 SDK 专用配置 |
board_7911B0/7911B8/7911BA/7911BB_cfg.h | AC7911B | 不同封装/型号子配置 |
board_7911D.c + board_7911D_cfg.h | AC7911D | 7911D 板型 |
board_7912AB/7912D_cfg.h、board_7912D.c | AC7912A/D | 7912 系列 |
board_7913A.c + board_7913A6_cfg.h | AC7913A | 7913A 板型 |
AC791N_WIFI_STORY_MACHINE.cbp | — | Code::Blocks 工程文件 |
板级头文件声明外设引脚、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_NUM | 1 / 2 | 2(wl82 双核) | 运行核数,影响中断表与任务核分配 |
RCSP_MODE | 0 / 1 | 按产品 | 杰理 RCSP 私有协议(rcsp/dev_mg 任务、BLE OTA) |
TCFG_DEV_MANAGER_ENABLE | 0 / 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_KEY | 0 / 1 | 1(基础版)/ 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.mp3 | app_music.c |
| OTA 升级失败/成功 | 播放 OtaFailed.mp3 / OtaSuccess.mp3 | app_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 任务与音频任务共享单核需注意优先级(tasklet10、audio_server16)。 - 仅蓝牙无 WiFi 变体:
app_main中额外调用bt_ble_module_init(),此时不含网络下载与配网流程。
并发与一致性
- 双核中断隔离:
IRQ_SOFT5_IDX注册到 CPU0、IRQ_SOFT4_IDX注册到 CPU1,软中断跨核分发避免同核竞争;不可屏蔽中断(CONFIG_IPMASK_ENABLE)要求中断代码与数据全部置于内部 RAM,防止访问外部总线被屏蔽。 - 任务优先级分层:WiFi 收发(
tasklet10)优先级刻意低于音频服务(audio_server16 等),保证 WiFi 重负载下音频不卡顿——注释明确说明该优先级是调优 WiFi/CPU 占比的旋钮。 - RCSP OTA 消息串行化:BLE 升级消息统一经
app_default_event_handler→JL_rcsp_update_msg_deal串行处理,避免与业务线程并发修改 Flash。 - 提示音互斥:基础版
CONFIG_PLAY_PROMPT_DISABLE_KEY=1在提示音播放期间屏蔽按键,防止提示音播放与用户操作竞争音频通道。
性能与运维
- 内存规划:核心任务(
app_core2048 字栈 + 1024 字队列、uda_main7000 字栈)全部静态预分配,运行期无堆碎片风险;WiFi/BT/编码器任务栈按 256~1536 字精细配置,说明该平台对 RAM 预算控制严格。 - WiFi 收发占比调节:通过
tasklet任务优先级(当前 10)平衡 WiFi 吞吐与音频实时性,是双核音频产品最重要的性能旋钮。 - 编码器任务簇:
speex/mp3/opus/amr/cvsd/vad/aec/dns/msbc/sbc/adpcm12 个编码器任务按需编译,未使用的编码器可裁剪以释放 RAM。 - 固件构建:
make ac791n_wifi_story_machine生成目标固件;工程文件AC791N_WIFI_STORY_MACHINE.cbp供 Code::Blocks 导入调试。 - 升级通道:支持本地
update/dw_update任务与 RCSP BLE OTA 双通道升级,升级全程有提示音反馈。
扩展点
- 新播放源:实现
struct music_dec_ops(参考get_bt_music_dec_ops()),即可把新音源接入统一播放框架。 - 新提示音场景:在
APP_LOCAL_PROMPT_TYPE_E枚举追加类型,并在local_prompt_table增加映射与 MP3 资源。 - 新内容领域:在
dir_name_chars/dir_name_chars_english增加目录名(GBK 字节 + 英文别名),并在领域提示音表中补充提示音。 - 新板型:在
board/wl82/下新增board_xxx.c+board_xxx_cfg.h,复用应用层与任务表,仅调整外设/内存配置。 - 云端变体:参照
CONFIG_DUI_SDK_ENABLE/ 腾讯音乐宏的模式新增编译开关,接入新云端 SDK 时复用现有事件处理与提示音体系。 - 任务/中断定制:
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/)