简介:面向蓝牙耳机固件开发者的Airoha洛达AB1568应用开发参考资料,聚焦该芯片平台从硬件启动到应用层功能实现的完整知识链路,适合已具备一定嵌入式基础、希望系统掌握AB1568开发的中高级工程师。资源包为1个PDF文档,约9.58MB,内容以工程分析为主线,涵盖上电执行函数、mk文件中的宏定义、app活动行为开启、ANC模式切换、LED呼吸灯样式修改、充电参数监测、超时时间设置与事件收发删除、Airoha API使用参考、回调函数注册调用、自动关机与配对时间配置、开机提示电量、清除配对列表、链路丢失重连、UI Shell框架、SideTone与音频路径设置、DUT模式测RF、硬件复位及PEQ设定等模块,目录结构清晰,便于按功能点查阅。已有374人学习,可作为开发过程中的速查手册与实现思路参考。
1. 拿到 AB1568 头戴耳机工程,先搞清楚它到底怎么跑起来
拆一个蓝牙耳机 SDK 工程,最怕的不是代码多,而是不知道从哪下手。我手上这份 Airoha AB1568 头戴耳机应用工程,目录一打开就是 bootloader、earbuds、headset 三套工程混在一起,mk 文件散落在 GCC 目录下,宏定义藏在 feature_68_evk.mk 里,按键行为对应在 customerized_key_config.c 里,ANC 参数又得靠 Config Tool 导入 NVR 文件才能生效。新手拿到这种工程,第一反应往往是直接编译烧录,结果发现 ANC 没效果、按键没反应、log 打不出来,然后开始怀疑人生。
这份工程的价值在于,它把 AB1568 芯片上头戴耳机从开机到关机的完整链路都摊开了:上电执行顺序、宏定义在哪个 mk 文件、UI Shell 活动进程怎么调度、ANC 四种模式怎么切换、LED 呼吸灯怎么改、充电参数怎么监测、FOTA 怎么升级、产测模式怎么进。适合正在做洛达 AB1568 蓝牙耳机定制开发、需要二次修改功能或者排查问题的开发者。下面按「先跑通、再拆架构、最后上手改」的顺序,把这份工程里真正能抄作业的部分讲清楚。
2. 编译与启动链路:从 build.sh 到 main 函数到底走了哪几步
2.1 先搞清楚编译命令调的是哪个 mk 文件
这份工程最容易被忽略的一步,是编译前先确认当前工程用的是哪个 mk 文件。GCC 目录下有一堆 mk 文件,不同工程调用的不是同一个。工程里给了一个很实用的命令:
# 列出所有可编译工程及其对应的 mk 文件 ./build.sh list执行后会看到类似ab1568_evk headset_ref_desgin feature_68_evk这样的映射关系。当前头戴耳机是基于 ab1565_ab1568_evk 开发板工程改出来的,所以编译 ab1568_evk 的 headset_ref_desgin 工程时,实际调用的是feature_68_evk.mk。这个文件就是宏定义的总开关,比如MTK_ANC_ENABLE、BL_FOTA_ENABLE都在里面。
参数说明:build.sh list只是列出映射,不执行编译;真正编译用./build.sh ab1568_evk headset_ref_desgin(具体参数以工程实际脚本为准)。改宏定义时直接编辑feature_68_evk.mk,加一行CFLAGS += -DXXX_ENABLE就能生效,但改完必须 clean 再 build,否则增量编译可能不重新预处理。
提示:宏定义改错位置是高频翻车点。改在别的 mk 文件里,编译能过但功能不生效,因为链接时根本没带上那段条件编译代码。
2.2 上电后先跑 bootloader 的 main,再跑应用工程的 main
上电执行顺序在工程里写得很明确:先运行apps下 bootloader 的 main 函数,再运行对应工程(earbuds 或 headset)的 main 函数。bootloader 阶段有一个关键条件编译:
/* bootloader 中 FOTA 处理逻辑,只有 BL_FOTA_ENABLE 被定义时才会被编译 */ #ifdef BL_FOTA_ENABLE bl_fota_process(); #endif这段代码说明一件事:BL_FOTA_ENABLE必须在 GCC 目录下的 mk 文件里定义,bl_fota_process才会成为被编译的代码。如果 FOTA 升级不生效,第一件事就是去 mk 文件确认这个宏有没有开。
进入应用工程 main 之后,会调用apps_inits初始化各种应用模块。这个函数是应用层初始化的总入口,里面按顺序初始化了 UI Shell、活动进程、事件组、按键、LED、音频路径等。初始化顺序不能随便调,比如 UI Shell 没起来就发事件,事件会丢;音频路径没配好就切 ANC,效果出不来。
2.3 所有 app 活动行为是怎么开启的
应用初始化里包含所有活动行为的初始化,核心是ui_shell_start_activity函数:
/* 在活动堆里为活动申请一个空闲 item,并启动该活动进程 */ ui_shell_start_activity(&app_home_screen_idle_activity_proc); ui_shell_start_activity(&app_anc_activity_proc); /* 其他子 UI 界面活动进程... */app_preproc_activity_proc是主进程,负责管理和调配其它子进程,比如app_home_screen_idle_activity_proc。开机后开启了很多不同进程,每个进程里都有不同事件组。系统产生一个事件时会把事件抛出去,所有进程都能监听到,如果该事件属于自己,就由该进程处理。
UI Shell 启用的每个活动进程类似于一个个 UI 界面。处于某个界面时发生某个事件,该事件就由此进程处理。比如在 home_screen 状态下,能处理的事件包括按键短按、长按、三连击、充电插入、蓝牙连接状态变化等。这种设计的好处是事件和界面解耦,坏处是事件发错组或者没注册监听,就会出现「按键有提示音但功能没反应」的玄学问题。
3. ANC 模式切换与参数固化:从按键事件到滤波器生效的完整链路
3.1 四种 ANC 模式和按键行为的对应关系
这份工程的 ANC 用 FF 麦(前馈)和 FB 麦(反馈)实现,Config Tool 上有三种参数:ANC、FBC、Passthrough,其中 ANC 包含 FF 和 FB,FBC 是 FB 的补偿。硬件上有 4 个麦克风用于降噪,1 个主麦(说话麦),2 个振动喇叭,2 个声音喇叭。音频降噪用 FF 和 FB,通话降噪用 talk 麦和 FF。
目标是在 home_screen 状态下用按键切换 ANC 模式。按键事件先进入_proc_key_event_group处理,需要开启宏MTK_ANC_ENABLE,在feature_68_evk.mk里确认已开启。所有 ANC 事件行为都调用app_home_screen_process_anc_and_pass_through函数处理。
按键行为key_action的值有四种:
| key_action 值 | 行为含义 |
|---|---|
| KEY_PASS_THROUGH | 通透模式开和关 |
| KEY_ANC | ANC 开和关 |
| KEY_SWITCH_ANC_AND_PASSTHROUGH | 全关到通透模式开到 ANC 开 |
| KEY_BETWEEN_ANC_PASSTHROUGH | 切换通透模式开和 ANC 开 |
耳机按键行为对应到key_action的配置在customerized_key_config.c文件里。改按键功能就是改这个文件里的映射表,不用动 ANC 处理逻辑本身。
3.2 三连击有提示音但没 ANC 效果,问题出在 NVR 参数
工程里记录了一个很典型的翻车场景:三连击 POWER 键有提示音,但没有 ANC 效果。原因不是代码没跑,而是用 Config Tool 打开工程的 download 文件夹后,看到 ANC 模式里根本没有调整过的参数。
解决路径是:把声学调好的 ANC 参数(nvr 文件)通过 Config Tool 的 Import NVR 功能导入工程,或者直接在 Tool 上调整参数。先 Write NV 后 Reset,把 FF、FB、FBC、AiroThru 参数写入耳机。参数写入固件后,循环三连击 Power 键就能听出不同 ANC 模式的降噪效果。
ANC 执行代码分析:按键行为KEY_SWITCH_ANC_AND_PASSTHROUGH改变变量target_anc_type和target_filter_id的值,接着传入app_anc_service_enable函数执行 ANC 效果。看切换 ANC 时的 log,三个模式循环切换,过滤anc_result就能看到当前 ANC 类型和滤波器编号。
ANC 默认滤波器AUDIO_ANC_CONTROL_ANC_FILTER_DEFAULT是值为 1 的枚举变量,PassThrough 默认滤波器AUDIO_ANC_CONTROL_PASS_THRU_FILTER_DEFAULT是值为 9 的枚举变量。NVkey 值对应 Tool UI 里,把 R 和 L 重叠看,就是 4 组滤波器:
- Filter 1:FF1(L/R) + FB1(L/R) + FBC1(L/R)
- Filter 2:FF2(L/R) + FB2(L/R) + FBC2(L/R)
- Filter 3:FF3(L/R) + FB3(L/R) + FBC3(L/R)
- Filter 4:FF4(L/R) + FB4(L/R) + FBC4(L/R)
3.3 把 ANC 参数固化到代码里,而不是只存在 download 文件
点击保存后,download 文件就有 ANC 参数了。但要把参数保存到代码里,流程是:先 clean 后 build 生成最新 download 文件,然后在 Config Tool 打开 download,导入声学 NVR 文件,再用 Special_Export 导出变更到文件,会生成 4 个文件。如果用 Save 方式保存成 download 文件,生成 3 个文件,其中 syskey 和 bin 文件与 4 文件方式一致。
有一部分 NVkey 被保存到filesystem.bin文件中。XML 文件和 bin 文件是用在量产程序编译的。编译工程代码时,用多个 XML 文件一起编译生成 bin 文件。以 ab1568_evk 为例,xml 1 有 7 个 KeyID,xml 2 有 4 个 KeyID,xml 3 有剩下的所有 KeyID。
把 Special_Export 导出的syskey.xml变更参数一一更新(复制粘贴)到上面 3 个nvkey.xml文件即可。注意:syskey.xml里有的 keyID,在nvkey.xml里不一定有,没有的就添加,有的就替换。ANC 参数 keyID 0xEE00~0xEEFF 在nvkey.xml中没有,需要手动补。同时替换filesystem.bin文件,重新编译工程生成 download 文件,用 Config Tool 打开后发现 ANC 参数变成了 nvr 文件的配置,说明参数成功固化到代码。
3.4 NVR 参数解析:0xE1E5 这种值怎么读
工程里给了一个 Component Gain 校准的解析例子:0xE1E5 = 10FF 1400 D8DC D8DC,高字节在前,低字节在后。
- FF(10FF) 对应 -2.4dB(component gain 是 -240),解析时前后位反转 10FF→FF10,十六进制转十进制再减去 65536 得到正确值。
- FB(1400) 对应 0.2dB(component gain 是 20),解析时前后位反转 1400→0014,十六进制转十进制直接得到正确值。
这个解析规则在排查 ANC 参数异常时很有用。如果读出来的值和 Tool 上显示的对不上,先检查字节序有没有反转,再检查是不是有符号数需要减 65536。
4. 事件框架与系统配置:UI Shell、超时、自动关机、配对和电量提示
4.1 ui_shell_send_event 和 ui_shell_remove_event 的用法
UI Shell 框架是这份工程事件驱动编程的核心。发送事件用ui_shell_send_event函数,删除事件用ui_shell_remove_event函数,接收事件消息用ui_shell_init_input_msg函数。
/* 发送一个事件到指定的事件组,携带数据和大小 */ ui_shell_send_event(false, EVENT_PRIORITY_HIGH, EVENT_GROUP_UI_SHELL_APP, EVENT_ID_APP_ANC_MODE_CHANGED, &anc_data, sizeof(anc_data), NULL, 0); /* 删除一个尚未被处理的事件,避免过期事件被消费 */ ui_shell_remove_event(EVENT_GROUP_UI_SHELL_APP, EVENT_ID_APP_ANC_MODE_CHANGED);参数说明:第一个参数表示是否立即发送,第二个是事件优先级,第三个是事件组,第四个是事件 ID,第五个是携带数据指针,第六个是数据大小,后面两个是超时和回调相关参数。删除事件时只需要事件组和事件 ID 就能定位。
常见误用是事件发了但没注册监听,或者事件组写错导致目标进程收不到。排查时先确认目标活动进程的_proc_xxx_event_group里有没有对应事件 ID 的处理分支。
4.2 超时时间、自动关机和配对时间的配置位置
超时时间设置、自动关机配置、配对时间设置这三项在工程里是分开配置的。自动关机配置涉及节能管理,设置合理的超时时间后通过编程实现自动关机。配对时间设置优化用户连接耳机时的体验,确定最合适的配对时间窗口。开机提示电量功能需要和电量监测机制整合,防止电量不足时使用耳机。
这些配置项通常落在 NVkey 或者应用配置结构体里,改的时候要注意:改 NVkey 默认值需要重新生成 download 文件并烧录,改代码里的默认结构体则编译即可生效。两者混用会出现「改了代码但耳机行为没变」的情况,因为运行时读的是 NVkey 里的值。
4.3 清除配对列表和链路丢失重连
清除配对列表是为了隐私保护和重新进入配对模式。链路丢失重连则是蓝牙耳机的基本体验保障。这两块逻辑都在应用层活动进程里处理,清除配对列表通常对应一个长按按键事件,链路丢失重连则依赖蓝牙协议栈的回调。
回调函数注册和调用是事件驱动编程的核心。很多功能模块的运行依赖特定事件触发,通过注册回调函数确保模块在恰当的时候执行。Airoha API 函数使用参考里列了常用接口,实际开发中建议先把回调注册链路画清楚,再动业务逻辑,否则容易出现回调没注册、事件空转的问题。
5. 避坑与排查:这几个坑我踩过,你大概率也会遇到
5.1 改了宏定义但功能不生效
现象:在代码里加了#ifdef XXX_ENABLE,也在 mk 文件里加了宏,编译通过,但功能没反应。
原因:宏加在了错误的 mk 文件里。不同工程调用不同 mk 文件,./build.sh list没确认就直接改,改的那个文件根本没被当前编译命令引用。
解决:先跑./build.sh list确认当前工程对应的 mk 文件,再改。改完 clean 再 build,不要依赖增量编译。
5.2 ANC 有提示音但降噪没效果
现象:按键切换有提示音,log 也显示 ANC 模式在切,但耳朵听不出降噪差异。
原因:NVR 参数没导入。代码逻辑跑通了,但 FF/FB/FBC 滤波器参数全是默认值或者空值,ANC 服务使能了但没有实际滤波系数。
解决:用 Config Tool 打开 download 文件夹确认 ANC 参数是否存在,不存在就 Import NVR 文件,Write NV 后 Reset。要固化到代码就按 Special_Export 流程更新 nvkey.xml 和 filesystem.bin。
5.3 事件发了但目标进程收不到
现象:ui_shell_send_event返回值正常,但目标活动进程的处理函数没被调用。
原因:事件组或者事件 ID 不匹配,或者目标活动进程还没启动。UI Shell 的活动进程是按启动顺序注册监听的,启动前发的事件会丢。
解决:确认ui_shell_start_activity在发事件之前执行,确认事件组和事件 ID 与目标进程_proc_xxx_event_group里的定义一致。必要时在发送前后加 log 确认事件流向。
5.4 改了按键行为但耳机没变化
现象:在customerized_key_config.c里改了按键映射,烧录后按键行为还是旧的。
原因:按键配置可能被 NVkey 覆盖,或者改的不是当前工程实际编译的那份配置文件。
解决:确认当前编译工程引用的配置文件路径,确认 NVkey 里有没有按键相关配置项覆盖了代码默认值。改完先恢复出厂设置或者清除 NVkey 再验证。
5.5 FOTA 升级不触发
现象:固件里做了 FOTA 相关逻辑,但升级流程走不起来。
原因:BL_FOTA_ENABLE宏没在 bootloader 对应的 mk 文件里定义,bl_fota_process根本没被编译进去。
解决:去 GCC 目录下 bootloader 对应的 mk 文件确认宏定义,补上后 clean 重编 bootloader 和应用工程。
6. 二次开发改造思路:从改一个 LED 呼吸灯开始验证整条链路
拿到这种 SDK 工程,我一般不建议一上来就动 ANC 或者音频路径,那些模块牵涉声学参数和 NVkey,改错了我连回滚都找不到入口。比较稳的切入点是 LED 呼吸灯样式,因为它链路短、现象直观、不依赖外部声学设备,改完烧进去肉眼就能验证。
具体做法是先在工程里找到 LED 控制模块,确认呼吸灯样式是由哪个结构体或者配置表驱动的。常见做法是把亮度、周期、占空比做成一张表,应用层按状态切换表项。改的时候只动表项数值,不动调度逻辑,这样即使效果不对,也能快速定位是参数问题还是流程问题。
/* LED 呼吸灯样式配置示例:亮度等级和周期按状态分组 */ typedef struct { uint8_t brightness; /* 亮度等级 0-100 */ uint16_t period_ms; /* 呼吸周期,单位毫秒 */ uint8_t step_ms; /* 每级亮度步进间隔 */ } led_breath_cfg_t; static const led_breath_cfg_t led_cfg_table[] = { { 80, 2000, 20 }, /* 开机呼吸 */ { 40, 3000, 30 }, /* 配对中呼吸 */ { 100, 1000, 10 }, /* 低电量快闪 */ };改完表项后,验证方法是:烧录,观察开机、配对、低电量三种状态下呼吸灯节奏是否符合预期。如果节奏不对,先查period_ms和step_ms的比例关系;如果亮度不对,查 PWM 占空比映射有没有做 gamma 校正。这一步跑通之后,再按同样的「配置表 + 状态机」思路去改按键行为、超时时间、提示音,链路就顺了。
再往深一层做二次开发,建议把 NVkey 的读写封装成独立模块,所有业务代码只调封装接口,不直接碰 NVkey ID。这样后面换芯片或者换工程时,只需要替换封装层,业务逻辑不用动。工程里NVKEY_Setting.c文件中的函数就是用来写该文件中 NVkey 的,可以以它为参考做一层薄封装。
还有一个血泪经验:每次改完 ANC 或者音频相关参数,我都会强制走一遍「clean → build → 生成 download → Config Tool 打开确认参数 → 烧录 → 听感验证」的完整流程,不跳过任何一步。因为 ANC 参数有一部分存在filesystem.bin里,只编译不重新生成 download,烧进去的还是旧参数,log 看着一切正常,耳朵就是没感觉。从那以后我每次动 NVkey 相关的东西都强制走一遍这个流程,希望帮到你。
本文还有配套的精品资源,点击获取