Skip to main content

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%安全余量)