(TODO))
书接上回。。。6 Zeypher集成6.1 整体内容整体来说是基于Zephyr 3.6.0。核心的实现如下文件夹内容如下GitHub - brilliantlabsAR/halo-firmware: Firmware for Halo, Brilliant Labs AI glasses — Zephyr RTOS on the Alif Balletto, with a Lua runtime for on-device apps and BLE OTA updates · GitHubPathWhat it isapplications/halo/The Halo application (boot, BLE, Lua runtime, audio, display)modules/halo/Reusable Halo C modules Lua bindings (AEC, codecs, sensors, BLE services)modules/lua/,modules/canvas/Lua 5.4 and the display/canvas font stackboards/arm/halo/ThehaloZephyr board definitiondrivers/,subsys/Device drivers and subsystems (Halo-specific inherited Alif SDK)samples/halo/Small single-peripheral samples (mic, display, sensors, …)west.ymlThe west manifest pinning Zephyr, HALs, and MCUbootapplications/halo/PROTOCOL.mdBLE protocol reference for host apps因为芯片用的是Alif Semiconductor的所以板级驱动是原厂直接在Zephyr包里面提供了。对于Halo产品来说实现的核心内容就是appmodulesdrivers。他们的顺序如下app应用就是一个main.c也没有太多东西。6.2 Modulesmodules服务器上的目录包括canvas、halo、linker和luamodules/halo/Halo 产品功能包括 BLE 管理与 BLE 服务、Lua runtime 及其硬件 API、电源/电池/LED/watchdog/file/memory manager以及音频流、AEC、EQ 和音效处理。modules/lua/Lua 解释器本身。modules/canvas/画布绘图和字体资源。modules/linker/链接脚本片段等构建辅助内容。6.3 Driversdrivers。大概有以下这些路径大致用途audio/max98357a/MAX98357A I²S 扬声器功放及扬声器保护audio/t5838/T5838 PDM 麦克风输入及音频活动检测AADaudio/pwm_audio/PWM 音频输出clock/si570/Si570 可编程时钟codec/wm8904/WM8904 音频编解码器display/display_vga020.cVGA020 显示器i2s/i2s_sync/同步 I²S 音频接口input/input_gpio_button.cGPIO 按键regulator/regulator_tps65132.cTPS65132 电源/偏置管理sensor/alif_vbat.cAlif 电池电压采集sensor/bma580/BMA580 加速度计sensor/qmc6308.cQMC6308 磁力计sm/sm.cGPIO 控制的 shutdown/电源状态机制video/pag7982.cPAG7982 摄像头6.4 小结从上面的内容可以看出如果是基于zeypher开发步骤大概就是west init 挪一个改名的manifest依样画boards/foo/board.dts把外设别名摆好一个也叫产品角色建一个跑main()的纯初始化骨架程序——log出一个Hello 一个k_work心跳外设一个一个加进samples/式的最小例然后接入应用以sysbuildmcuboot为底线第一周就跑通“通过BLE掉固件→回滚”——OTA机制不是产品后期加的是最早基础设施7 音频子系统整体来看音频系统如下这里只看看驱动层stream层以及算法。再上面的app不在范围。7.1 驱动从硬件上来看音频系统涉及的硬件是麦克风T5838 PDM带Always-on Audio Detect可单独唤醒zephyr,micphone扬声器MAX98357AI2S功放zephyr,speaker关于98357之前其实写过一篇总线学习5--I2S_max98357数据手册-CSDN博客在代码中有以下驱动作用如下路径大致用途audio/max98357a/MAX98357A I²S 扬声器功放及扬声器保护audio/t5838/T5838 PDM 麦克风输入及音频活动检测AADaudio/pwm_audio/PWM 音频输出codec/wm8904/WM8904 音频编解码器i2s/i2s_sync/同步 I²S 音频接口播放的DTS定义/delete-node/ i2s049014000; i2s0: i2s049014000 { compatible alif,i2s-sync; reg 0x49014000 0x1000; pinctrl-names default; pinctrl-0 pinctrl_i2s0; interrupts 141 3; bit-depth 16; sample-rate 32000; mono-mode; status okay; }; max98357a: max98357a { compatible maxim,max98357a; i2s i2s0; sd-mode-gpios gpio8 5 GPIO_ACTIVE_HIGH; }; pdm_audio: pdm_audio43002000 { compatible alif,t5838-alif-pdm; reg 0x43002000 0x1000; /* priority 2, above I2S0s 3: the 8-deep PDM FIFO at * 16kHz gives the ISR ~250us from the watermark to * overflow; at priority 4 under duplex load it missed * ~10x/second (732 counted overflows in 72s, EC * 2026-07-13). Bisect-exonerated for the round-2 * wedge (that was the unacked sticky ERROR status). */ interrupts 49 2; pinctrl-0 pinctrl_pdm_audio ; pinctrl-names default; /* almost-full IRQ threshold on the 8-deep FIFO: slack * to overflow is (8 - watermark) samples 62.5us * each at 16kHz. 6 left 125us of ISR headroom and * overflowed under duplex BLELC3 load (capture * losses that slid the AEC window off its ring); * 4 doubles the headroom for a ~1.3x ISR rate. */ fifo-watermark 4; queue-depth 128; iir-bypass; fir-bypass; /* Snip the PDM decimator start-of-stream settling * transient (the pop): the front-end slews to the * ±full-scale rail for the first ~5-12ms after trigger * (measured on cold-start captures, tests/aec/pop_*.py), * a window with no recoverable audio. In the DMA drain * path the discard drops whole MIC_BLOCK_INTERVAL_MS * (20ms) blocks, so 20 drop exactly one block, clearing * the rail with margin at ~20ms of startup latency. The * DC-settling tail past the rail is real audio and is * left to the downstream DC blocker (lua_microphone.c * mic_dc_block). The driver default is 0 (was regressed * 50-0 in 15bc6a1, which re-exposed the pop). Do NOT * un-bypass the IIR to fix this - the AEC relies on the * raw full-band mic (see mic_dc_block rationale). */ discard-duration-ms 20; /* LPPDM RX DMA drain (prototype): dma2 channel 4, * DMA request line 30 / group 2 LPPDM_DMA_REQ * (B1 HWRM Table 14-95 the DMA request MUX table). * The hardware FIFO watermark drives the DMA handshake * (PDM_CTL1 USE_DMA bit), replacing the almost-full ISR * that overflows on 250us CPU blackouts. Drop this * property to fall back to the ISR drain. */ dmas dma2 4 30; dma-names rxdma; status okay; #address-cells 0x1 ; #size-cells 0x0 ; t5838: t583853 { status okay; compatible invensense,t5838-alif-pdm; thsel-gpios gpio3 0 GPIO_ACTIVE_HIGH, gpio5 2 GPIO_ACTIVE_HIGH; wake-gpios lpgpio 0 GPIO_ACTIVE_HIGH; pdmclk-gpios gpio5 5 GPIO_ACTIVE_HIGH; reg 0x53; }; };录音的DTS定义tps65132: tps651323e { compatible ti,tps65132; reg 0x3e; vin-supply cam_1v8; supply-gpios gpio2 1 GPIO_ACTIVE_HIGH; apps 40ma; veng: VENG { regulator-name veng; regulator-init-microvolt 4500000; enable-gpios gpio5 6 GPIO_ACTIVE_HIGH; startup-delay-us 5000; status okay; };在这里驱动把接口封装成zepyher的接口给上层使用。接口可以看Zephyr API Documentation: Audio比如读取麦克风数据alif_pdm_read()就是封装成标准的zepyher接口dmic_read()供上层使用。但是在驱动中也有一些也是HALO项目自己定义的。比如播放接口。max98357a_audio_write_impl。最后是封装成一个自己的接口audio_write()。7.2 流抽象层主要涉及的代码是audio_stream.c。封装了驱动并且提供以下接口。功能上层接口作用扬声器播放audio_speaker_init()、audio_speaker_start()、audio_speaker_write()、audio_speaker_stop()、audio_speaker_destroy()初始化并控制播放会话、写入 PCM 数据、结束会话播放控制与保护audio_speaker_set_volume()、audio_speaker_set_volume_transient()、audio_speaker_get_volume()、audio_speaker_set_stream_gain()、audio_speaker_set_stream_budget()、audio_speaker_notify_display_active()调节音量和每路增益、功耗预算并根据显示状态调整音频保护麦克风录音audio_microphone_init()、audio_microphone_start()、audio_microphone_read()、audio_microphone_free_buffer()、audio_microphone_stop()、audio_microphone_destroy()初始化录音、读取数据并释放驱动交付的缓冲区麦克风控制与资源管理audio_microphone_set_gain()、audio_microphone_get_gain()、audio_microphone_check_owner()、audio_microphone_read_owned()、audio_microphone_free_buffer_owned()控制增益在指定资源拥有者的上下文中读取或释放数据LC3 编解码audio_lc3_decoder_create()、audio_lc3_decode_frame()、audio_lc3_encoder_create()、audio_lc3_encode_frame()以及对应的销毁和帧大小查询函数在 LC3 数据与 PCM 之间转换音频活动检测audio_aad_set_callback()、audio_aad_rearm()、audio_aad_disable()、audio_aad_get_current_settings()注册音频活动检测回调、重新布防、禁用或查询设置音频流源与接收端audio_stream_register_source()、audio_stream_source_read()、audio_stream_unregister_source()audio_stream_register_sink()、audio_stream_sink_write()、audio_stream_unregister_sink()用回调注册数据源和接收端让不同组件通过统一的数据流接口交换音频7.3 算法Halo 的 AEC、EQ 等算法主要由 Halo 自己实现放在音频模块或 MAX98357A 驱动里Zephyr 提供设备与数据流接口算法本身不是 Zephyr 通用音频 API。处理主要实现位置实现方式与所在链路AEC 回声消除modules/halo/src/audio_aec.c、modules/halo/include/halo/audio_aec.h默认使用分区块频域自适应滤波FDAF可配置为时域 NLMS。以扬声器输出作为参考估算泄漏到麦克风的回声并从麦克风信号中扣除还包括双讲检测、抑制滤波等机制。AEC 接入录音链路modules/halo/src/lua_microphone.c麦克风数据经过audio_aec_process()后才进入后续编码。AEC 需要的扬声器参考信号则由 MAX98357A 驱动在发送路径上提供。扬声器保护 DSPHPF、音色 EQ、限幅drivers/audio/max98357a/speaker_protect.c、drivers/audio/max98357a/speaker_protect.h驱动在 PCM 播放路径中、音量处理之后应用保护链包括高通滤波、分频和音色调整、能量限制、起播渐入及削波保护。配置MAX98357A_AUDIO_PROTECTION_EQ默认启用。可选播放端 HPFmodules/halo/src/audio_eq.c、modules/halo/include/halo/audio_eq.haudio_speaker_write()可选地对 PCM 原地应用二阶或四阶 Butterworth 高通滤波。HALO_AUDIO_HPF默认关闭Kconfig 说明 Halo 的扬声器保护主要由驱动里的 DSP 链负责。录音端 DC 和语音频带处理modules/halo/src/lua_microphone.cAEC 之后还会做 DC 偏置抑制语音模式下可再做带通处理然后编码。8 IMU子系统对于系统来说IMU包括了BMA580加速度计 QMC6308磁力计。驱动都在alif/drivers/sensor/这里是直接封装成zeypher的接口。接口描述是在Zephyr API Documentation: sensor_driver_api Struct Reference在HALO项目中IMU的数据全部都是上层控制读取使用的接口是frame.imu.direction() / frame.imu.raw()。驱动或者下层不会去自动推送或者缓存。只有敲击手势是产生中断由imu_trigger_handler捕获。数据模式频率归属MCU消耗姿态 pitch/rollLua调用时拉取现场I2C读Lua想读多快读多快≤~几十Hz现实上限每次~几十µs I2C磁场 raw同上且QMC6308是现场触发转换同上每次含最长100ms DRDY等待实际~几ms敲击手势中断推送芯片检测→事件入环事件频率人类敲击速度每次一个中断一个字节搬运原始804Hz样本流不存在DATA_READY口子预留未用芯片内部800Hz自转零feature engine在芯片内消化9 Camera子系统