main_task.c 技术文档
1. 文件功能概述
main_task.c是BP10xx DSP项目中BT Audio SDK的核心主任务文件,承担着整个音频应用系统的主控调度中枢角色。该文件实现了基于RTOS的多任务音频系统架构,主要负责:
- 系统初始化与资源配置:完成DMA通道映射、音频核心服务初始化、硬件外设配置
- 模式生命周期管理:实现音频播放模式的状态机控制(创建→进入→工作→退出→销毁)
- 消息分发与处理:集中处理系统级消息,包括蓝牙事件、电源管理、用户交互等
- 电源管理策略:实现深度睡眠与唤醒机制,优化系统功耗
- 音频通路管理:协调DAC、ADC、I2S等音频外设的资源分配与配置
该文件采用分层服务架构,通过AudioCore、Device、Display、RemindSound等基础服务,支撑蓝牙音频、TWS、K歌、录音等多种应用模式的运行。
2. 核心代码解析
2.1 系统初始化模块
主任务入口函数 MainAppTaskEntrance()
void MainAppTaskEntrance(void* pParam)
{
MainAppInit(); // 主任务上下文初始化
SysVarInit(); // 系统变量初始化
DMA_ChannelAllocTableSet(DmaChannelMap); // DMA通道映射配置
// ... 音频核心配置与模式启动
}
核心职责:
- 初始化主任务消息队列(10个消息槽位)
- 配置DMA通道映射表(8通道资源分配)
- 设置音频采样率与帧大小(默认48kHz/256帧)
- 启动首个模式(WaitingPlay模式)
系统变量初始化 SysVarInit()
该函数实现了断电记忆恢复机制,从 pBpSysInfo系统信息结构体中恢复:
- 当前工作模式(支持蓝牙、TWS、K歌、录音等模式)
- 音量参数(音乐音量、麦克风音量、通话音量)
- 音效配置(混响、EQ、特效模式、高低音调节)
2.2 模式管理模块
模式状态机实现
采用四阶段状态模型:
ModeStateNone → ModeStateEnter → ModeStateWork → ModeStateExit → ModeStateNone
模式切换核心函数 NextModeProcess()
static AppMode NextModeProcess(AppMode StartMode)
{
AppMode NextMode = StartMode;
// 优先级调度策略:
// 1. 蓝牙模式(最高优先级)
// 2. TWS模式
// 3. 线路输入模式
// 4. 其他媒体模式
switch(StartMode) {
case AppModeBtAudioPlay:
// TWS支持时优先检查TWS连接状态
#ifdef BT_TWS_SUPPORT
if(tws_link_status_get() == BT_TWS_STATE_CONNECTED)
return AppModeTwsMasterPlay;
#endif
break;
case AppModeWaitingPlay:
// 等待模式结束后进入默认模式
return AppModeBtAudioPlay;
}
return NextMode;
}
模式资源管理
- 进入模式
SelectModeBeforeEnter():申请音频资源、初始化硬件外设 - 退出模式
StartModeExit():释放资源、保存状态参数 - 模式超时保护:通过
ModeTimer实现(进入5s/退出3s超时)
2.3 消息处理模块
消息分类与处理策略
系统级消息处理 CommonMsgProccess():
- 音量控制消息:支持主音量、音乐音量、麦克风音量的独立调节
- 音效控制消息:混响、EQ、特效模式、3D音效等参数调整
- 模式切换消息:处理用户按键触发的模式切换请求
深度睡眠管理消息:
case MSG_DEEPSLEEP:
case MSG_TASK_DEEPSLEEP:
case MSG_BTSTACK_DEEPSLEEP:
// 蓝牙协议栈睡眠与普通睡眠分流处理
if(msgId == MSG_BTSTACK_DEEPSLEEP) {
MainAppServicePauseBt(); // 保持蓝牙连接
} else {
MainAppServicePause(); // 完全睡眠
}
break;
TWS模式特殊处理
实现主从设备协同机制:
- 主机模式:负责音频同步与设备管理
- 从机模式:接收主机指令,执行本地播放
- 连接状态检测:通过
tws_link_status_get()实时监控
2.4 电源管理模块
深度睡眠流程 SleepMainAppTask()
void SleepMainAppTask(void)
{
AudioCoreSourceDisable(MIC_SOURCE_NUM); // 关闭麦克风
WDG_Disable(); // 关闭看门狗
AudioADC_PowerDown(); // ADC断电
#ifdef CFG_RES_AUDIO_DAC0_EN
AudioDAC_PowerDown(DAC0); // DAC0断电
#endif
// ... 其他外设断电
}
唤醒恢复流程 WakeupMainAppTask()
实现状态恢复机制:
- 重新初始化音频外设(DAC/ADC/I2S)
- 恢复音量与音效参数
- 重建音频数据通路
- 服务重新启动(蓝牙协议栈等)
2.5 音频资源管理模块
动态内存分配策略 AudioResMalloc()
根据TWS模式与普通模式采用差异化缓冲区策略:
#ifdef BT_TWS_SUPPORT
// TWS模式:4倍缓冲区保证相位同步
uint16_t Dac0FifoLen = SampleLen * 2 * 2 * 2 * 4;
uint16_t DacxFifoLen = SampleLen * 2 * 2 * 4;
#else
// 普通模式:标准缓冲区大小
uint16_t Dac0FifoLen = SampleLen * 2 * 2 * 2;
uint16_t DacxFifoLen = SampleLen * 2 * 2;
#endif
资源释放与重建
- 帧大小切换处理:通过
AudioResRelease()释放所有音频资源 - 重新申请资源:根据新模式需求重新配置缓冲区
- DMA通道重新映射:确保音频数据通路正确连接
3. 重要数据结构
3.1 主任务上下文结构体
typedef struct {
// 任务状态管理
TaskState state; // 任务运行状态
ModeState MState; // 模式状态机状态
// 模式管理
AppMode appCurrentMode; // 当前工作模式
AppMode appTargetMode; // 目标模式
AppMode appBackupMode; // 备份模式(断电记忆)
// 音频参数
uint8_t MusicVolume; // 音乐音量(0-32级)
uint8_t MicVolume; // 麦克风音量
uint8_t HfVolume; // 通话音量
// 音效参数
uint8_t EffectMode; // 特效模式
uint8_t EqMode; // EQ模式
uint8_t ReverbStep; // 混响级别
// 系统资源
MessageHandle msgHandle; // 消息队列句柄
AudioCoreHandle AudioCore; // 音频核心句柄
// 硬件配置
uint32_t SampleRate; // 采样率
uint16_t SamplesPreFrame; // 每帧采样数
// 缓冲区指针
uint32_t *DACFIFO; // DAC0 FIFO缓冲区
uint32_t *DACXFIFO; // DACX FIFO缓冲区
uint32_t *ADCFIFO; // ADC FIFO缓冲区
uint32_t *I2SFIFO; // I2S FIFO缓冲区
} MainAppContext;
3.2 DMA通道映射表
static const uint8_t DmaChannelMap[29] = {
// 音频外设固定分配
[PERIPHERAL_ID_AUDIO_ADC0_RX] = 0, // ADC0 → DMA通道0
[PERIPHERAL_ID_AUDIO_ADC1_RX] = 1, // ADC1 → DMA通道1
[PERIPHERAL_ID_AUDIO_DAC0_TX] = 2, // DAC0 → DMA通道2
[PERIPHERAL_ID_AUDIO_DAC1_TX] = 3, // DAC1 → DMA通道3
// SD卡录音
[PERIPHERAL_ID_SDIO_RX] = 4, // SDIO → DMA通道4
[PERIPHERAL_ID_SDIO_TX] = 4, // SDIO → DMA通道4(共享)
// HDMI CEC
[PERIPHERAL_ID_TIMER3] = 5, // TIMER3 → DMA通道5
// 串口调音(可选)
[PERIPHERAL_ID_UART1_TX] = 6, // UART1 TX → DMA通道6
[PERIPHERAL_ID_UART1_RX] = 7, // UART1 RX → DMA通道7
};
3.3 软件标志位管理
// 关键软件标志位定义
typedef enum {
SoftFlagDeepSleepRequest = 0, // 深度睡眠请求
SoftFlagWakeUpSouceIsCEC, // CEC唤醒源
SoftFlagWaitDetect, // 等待检测阶段
SoftFlagPlayback, // 播放状态
SoftFlagBtHfDelayEnterSleep, // 蓝牙通话延迟睡眠
} SoftwareFlagType;
4. 业务流程
4.1 系统启动流程
graph TD
A[上电复位] --> B[硬件初始化]
B --> C[RTOS系统启动]
C --> D[创建主任务]
D --> E[MainAppInit]
E --> F[SysVarInit]
F --> G[服务创建]
G --> H{服务创建完成?}
H -->|是| I[服务启动]
H -->|否| G
I --> J{服务启动完成?}
J -->|是| K[进入Waiting模式]
J -->|否| I
K --> L[播放开机提示音]
L --> M[模式检测与切换]
M --> N[进入默认工作模式]
4.2 模式切换流程
graph TD
A[当前模式] --> B[模式切换请求]
B --> C[StartModeExit]
C --> D[资源释放]
D --> E[模式状态=Exit]
E --> F{退出完成?}
F -->|超时3s| G[强制销毁]
F -->|正常| H[模式销毁]
H --> I[NextModeProcess]
I --> J[选择目标模式]
J --> K[SelectModeBeforeEnter]
K --> L[资源申请]
L --> M[硬件初始化]
M --> N[模式状态=Enter]
N --> O{进入完成?}
O -->|超时5s| P[进入失败处理]
O -->|正常| Q[模式状态=Work]
Q --> R[新模式运行]
4.3 深度睡眠流程
graph TD
A[睡眠请求] --> B{请求类型}
B -->|MSG_BTSTACK_DEEPSLEEP| C[蓝牙协议栈睡眠]
B -->|其他睡眠消息| D[完全深度睡眠]
C --> E[保持蓝牙连接]
E --> F[暂停其他服务]
F --> G[配置蓝牙睡眠参数]
G --> H[进入轻睡眠]
D --> I[断开蓝牙连接]
I --> J[暂停所有服务]
J --> K[释放音频资源]
K --> L[关闭硬件外设]
L --> M[配置睡眠参数]
M --> N[进入深度睡眠]
O[唤醒事件] --> P{唤醒源}
P -->|CEC唤醒| Q[恢复HDMI模式]
P -->|其他唤醒| R[恢复默认模式]
Q --> S[硬件初始化]
R --> S
S --> T[服务恢复]
T --> U[音频通路重建]
U --> V[模式状态恢复]
5. 接口说明
5.1 系统控制接口
系统关机接口
/**
* @brief 系统进入关机状态
* @note 发送关机消息到主任务,触发优雅关机流程
*/
void SystemGotoPowerDown(void);
资源分配状态查询
/**
* @brief 获取系统资源分配状态
* @return 0: 未分配 1: 已分配
* @note 用于判断音频资源是否已申请成功
*/
uint8_t GetSysResMallocStatus(void);
5.2 音频配置接口
I2S输出参数设置
/**
* @brief 配置I2S输出参数
* @note 根据主任务上下文配置I2S时钟、格式、缓冲区
*/
void AudioI2sOutParamsSet(void);
麦克风源恢复接口
/**
* @brief 恢复麦克风音频源(用于蓝牙通话结束)
* @note 从通话模式恢复到正常K歌模式
*/
void ResumeAudioCoreMicSource(void);
5.3 模式管理接口
模式状态设置
/**
* @brief 设置模式状态机状态
* @param state 目标状态(Create/Enter/Work/Exit/Destroy)
* @return 成功返回TRUE,失败返回FALSE
* @note 触发模式生命周期状态转换
*/
bool ModeStateSet(ModeState state);
模式恢复掩码检查
/**
* @brief 检查模式是否需要恢复(断电记忆)
* @param mode 待检查的模式
* @return 需要恢复返回TRUE,否则返回FALSE
* @note 用于判断唤醒后是否恢复该模式
*/
bool ModeResumeMask(AppMode mode);
6. 注意事项
6.1 并发与同步问题
消息队列竞争
- 问题:主任务消息队列(10槽位)在高频模式切换时可能溢出
- 解决:增加消息队列深度或实现消息合并机制
DMA通道冲突
- 问题:多模式共享DMA通道时可能产生资源竞争
- 解决:严格遵循DMA映射表,在模式切换时进行通道保护
6.2 内存管理要点
动态内存碎片
- 现象:频繁的模式切换导致音频缓冲区反复申请/释放
- 优化:采用内存池管理,或预分配最大需求内存
TWS模式缓冲区特殊要求
- 关键:TWS模式需要4倍标准缓冲区大小以保证相位同步
- 注意:缓冲区大小计算需考虑采样率×通道数×帧数×4的倍数关系
6.3 功耗优化注意事项
蓝牙协议栈睡眠时机
- 原则:在蓝牙连接状态下优先使用
MSG_BTSTACK_DEEPSLEEP - 注意:完全深度睡眠前需确保蓝牙连接已断开,避免协议栈异常
外设断电顺序
- 关键路径:先关闭音频源(ADC)→ 再关闭音频输出(DAC)→ 最后关闭系统时钟
- 恢复顺序:逆序恢复,确保音频通路建立正确
6.4 音频质量保障
模式切换爆音防护
- 机制:在模式切换前后加入软静音(SoftMute)处理
- 时序:退出模式前静音 → 资源释放 → 资源申请 → 进入模式后恢复音量
采样率切换处理
- 注意:不同模式可能使用不同采样率(44.1kHz/48kHz)
- 要求:采样率切换时必须重新初始化音频外设并清空FIFO缓冲区
6.5 调试与维护建议
关键调试信息
- 模式切换跟踪:通过
APP_DBG宏输出模式切换全流程 - 资源使用监控:在内存申请/释放时打印剩余内存大小
- 超时异常捕获:模式进入/退出超时需记录错误码并触发故障恢复
性能监控指标
- 模式切换延迟:从请求到完成的时间应<100ms
- 睡眠唤醒时间:深度睡眠唤醒到音频播放应<500ms
- 内存使用率:动态内存使用峰值应<80%(预留20%安全余量)