嵌入式架构学习5--Brilliant Labs Halo(TODO)

发布时间:2026/10/19 7:00:21

嵌入式架构学习5--Brilliant Labs Halo(TODO) 1 硬件架构目标板Alif Balletto B1特性规格CPUARM Cortex-M55Helium SIMDNPUArm Ethos-U55ML 推理加速蓝牙BLE 5.3LE Audio / LC3 编解码内存内部 ITCM/DTCM 外部 SRAM458KB 配置给 Halo 堆存储FlashMCUboot 分区 LittleFSBoard 定义位于alif/boards/arm/halo/halo.dts— 设备树外设引脚、flash 分区、SRAM 映射halo_defconfig— Kconfig 基础配置Cortex-M55 Ethos-U55 使能外设器件Zephyr别名显示VGA020MIPI-DSIzephyr,panel摄像头PAG7982 低功耗lpcamzephyr,camera麦克风T5838 PDM带Always-on Audio Detect可单独唤醒zephyr,micphone扬声器MAX98357AI2S功放zephyr,speaker加速度计BMA580zephyr,accel磁力计QMC6308zephyr,magn其他唤醒按键LPGPIO、PWM LED、电池计量(vbatADC)、MRAM分区mcuboot / image-0—2 软件架构代码工作区用Zephyr West工具管理west.yml是唯一的版本锁定文件。构建方式west build --sysbuild -b halo alif/applications/halo -p产出build/halo/zephyr/zephyr.signed.bin MCUboot引导镜像。目录内容来源alif/Halo 应用主仓库manifest 仓库selfbrilliantlabsAR/halo-firmwarezephyr/Zephyr RTOS含 Alif 补丁Brilliant Labs forkbrilliantlabsAR/halo-zephyr-alifmodules/hal/alif/Alif HAL含 Halo 补丁brilliantlabsAR/halo-hal-alifmodules/hal/cmsis/ARM CMSISalifsemibootloader/mcuboot/MCUboot含 OTA 相关扩展brilliantlabsAR/halo-mcubootmodules/lib/matter/Matter 协议alifsemi/matter_alifmodules/drivers/dave2d/Dave2D 2D 图形加速驱动alifsemimodules/lib/aipl/Alif 图像处理库NPU 后端alifsemimodules/lib/libmpix/像素格式转换库libmpix/libmpixmodules/lib/lz4/LZ4 压缩zephyrproject-rtos真正值得关注的只有 alif/applications/halo应用 alif/modules/4 个自研模块halo、canvas、lua、linker。一切业务跑在 Zephyr 线程里Lua 有专属 REPL 线程优先级 764KB 栈BLE 有 host 线程传感器有 work 队列。外设靠 devicetree 描述halo.dts功能靠 Kconfig 裁剪CONFIG_HALO_*每个外设还有独立 samplesamples/halo/ 下 18 个battery/bma580/button/max98357a/t5838/vga020/wakeup…——看 samples 是学 Halo 外设最快的路。主要功能模块alif/modules/halo/src/文件职责lua_runtime.cLua VM 生命周期、REPL 线程、异步事件分发统一 Hook 机制ble_manager.cBLE 服务注册/断开调度、事件分发、电源管理集成ble_lua.cLua BLE 服务REPL 通道 数据 framed 队列 视频/音频ble_ota.cOTA 固件升级SMP over BLE → MCUbootble_audio.cLE Audio 流媒体BAP UnicastLC3ble_connection.c/ble_security.cBLE 连接管理与配对安全ble_ancs.c/lua_ancs.cApple 通知中心服务手机通知转发audio_aec.c声学回声消除 (AEC)FDAF 算法状态放在 ITCM64KB256ms 参考环audio_eq.c均衡器audio_stream.c音频流管道Mic → AEC → EQ → BLEbattery_manager.c电池电量监控充电检测、低电告警事件led_manager.cLED 呼吸灯 / 状态指示控制file_manager.cFlash 文件系统LittleFS封装mem_manager.c内部/外部 SRAM 堆管理pm_manager.c系统电源管理suspend/resume 策略watchdog_manager.c看门狗se_mgmt.c安全元件管理SE 固件更新sfxr.c音效合成器Luaframe.soundAPI 后端驱动列表alif/drivers/子目录驱动audio/PDM 麦克风、I2S DAC/ADCcodec/音频编解码器display/MIPI-DSI 显示驱动i2s/I2S 总线驱动input/按键输入led_pwm/LED PWM 驱动sensor/IMU加速度计/陀螺仪video/摄像头驱动DVP/MIPI CSIclock/时钟管理regulator/电源调节器sm/状态机驱动框架子系统层alif/subsys/子系统功能bluetooth/Halo 专用 BLE 协议扩展dbuf_display/双缓冲显示管理img_assets/启动 Logo、图片资源powermgr/细粒度电源状态机matter/Matter 智能家居协议支持modules/Lua 模块 autoload 支持输入和输出输入系统共 7 个输入源对应器件 / 接口驱动与底层处理链路应用层 / Lua 映射1. 声音输入T5838数字 PDM 麦克风 (pdm_audio)通过 PL330 DMA 搬移到 16kHz 16-bit PCM 环形缓冲剥离前 20ms Pop 冲击音经过 **AEC声学回声消除**滤除喇叭回音支持实时压缩为LC3。frame.microphone.read()获取音频支持AAD 硬件语音活动唤醒中断。2. 图像输入PAG7982超低功耗摄像头 (lpcam8-bit DVP)硬件 CPI DMA 传输由libmpix进行软件 ISP 与调色板处理内置软件压缩为JPEG存入 115KB 静态缓冲。frame.camera.capture()直接拍图返回 JPEG 字节流。3. 动作敲击BMA580三轴加速度计 (I2C0,0x18)硬件内部算法直接识别单敲 / 双敲 / 三敲手势硬件中断触发无锁环形队列tap_ring。触发frame.imu.tap_callback(single/double/triple)。4. 地磁罗盘QMC6308三轴磁力计 (I2C0,0x2C)驱动层定时采集 X/Y/Z 三轴磁场强度并进行坐标转换。frame.imu.direction()获取当前朝向方位角。5. 实体按键镜腿WAKEUP微动按键 (lpgpio 1)30ms 硬件消抖驱动状态机精确区分单击、双击(400ms)、1s长按、2s休眠、5s配对、15s运输模式。触发frame.button.callback(...)。6. 供电检测VBAT电量采样电路 (ADC0 Ch4 充电GPIO)分压采样读取电池毫伏电压并查表映射百分比监控充电中/放电中/严重低电量状态。产生事件同步至 BLE Battery 服务或供 Lua 查询。7. 蓝牙下行BLE RX射频接口 (UART HCI)接收控制指令0x02重启、0x03中断、0x04VM重启等拆包组包用户数据帧支持标准LE Audio BAP接收。驱动 Lua REPL 控制台或触发frame.bluetooth.receive_callback()。输出系统共 5 个输出源对应器件 / 接口驱动与底层处理链路应用层 / Lua 映射1. 微显示输出VGA020Micro-OLED 屏 (MIPI-DSI, 256×256)由CDC200控制器管理双缓冲 Framebuffer集成Dogica点阵字体与整数倍等比无损缩放引擎支持LZ4 启动 Logo快速直刷。frame.display.text()、bitmap()绘制完毕后调show()经 DMA 刷屏。2. 音频输出MAX98357AI2S D类功放 (I2S0, 32kHz)支持LC3 实时解压为 PCM带防爆音时序保护同时把播放的声音同步镜像拷贝至256ms AEC 参考环用于麦克风回声对消板载SFXR8-bit 复古音效合成器。frame.speaker.play()播放音频流frame.sound.play()播放激光/跳跃等内置预置音效。3. 状态指示呼吸LED(Timer3 PWM引脚 P6.6)驱动层集成 PWM 占空比呼吸算法、脉冲闪烁与常量模式。自动绑定连接状态、充电状态与长按反馈。4. 关机控制SM-GPIO系统电源控制器 (GPIO6.0)接收到整机关机或超低功耗运输模式Ship Mode指令后拉低电平直接切断外设电源域供电。frame.system.power_off()。5. 蓝牙上行BLE TX射频通道 (GATT Notify)LUA TX 字符通道回显 REPL 结果与print()回传电量及 OTA 升级确认包通过LE Audio BAP上行麦克风语音。frame.bluetooth.send()发送应用业务数据。通讯协议的官方参考文档 PROTOCOL.md3 main应用入口src/main.c核心配置prj.conf/* * Copyright (c) 2025 Brilliant Labs Inc. * SPDX-License-Identifier: Apache-2.0 */ #include zephyr/kernel.h #include zephyr/logging/log.h #include zephyr/sys/printk.h #include zephyr/sys/reboot.h #include zephyr/drivers/sensor.h #include app_version.h #include halo/mem_manager.h #include halo/file_manager.h #include halo/pm_manager.h #include halo/led_manager.h #include zephyr/drivers/input/button.h #ifdef CONFIG_SENSOR #include halo/battery_manager.h #endif #ifdef CONFIG_HALO_BLE_MANAGER #include halo/ble_manager.h #include halo/ble_connection.h #include halo/ble_security.h #ifdef CONFIG_HALO_BLE_LUA_SERVICE #include halo/ble_lua.h #endif #endif #ifdef CONFIG_HALO_LUA_RUNTIME #include halo/lua_runtime.h #endif #if defined(CONFIG_HALO_STARTUP_SOUND) || defined(CONFIG_HALO_SHUTDOWN_SOUND) #include halo/sfxr.h #endif #ifdef CONFIG_HALO_BOOT_LOGO #include halo/boot_logo.h #endif #ifdef CONFIG_HALO_WATCHDOG_MANAGER #include halo/watchdog_manager.h #endif #include zephyr/drivers/regulator.h #include zephyr/pm/device.h #if defined(CONFIG_BOOTLOADER_MCUBOOT) defined(CONFIG_MCUBOOT_IMG_MANAGER) #include zephyr/dfu/mcuboot.h #endif #include se_service.h LOG_MODULE_REGISTER(halo, CONFIG_HALO_LOG_LEVEL); const char halo_banner[] _ _ _ \n | | | | | | \n | |__| | __ _| | ___ \n | __ |/ _ | |/ _ \\ \n | | | | (_| | | (_) |\n |_| |_|\\__,_|_|\\___/ \n Copyright (C) 2025 Brilliant Labs\n https://brilliant.xyz/\n; /** * brief Main application entry point * * Initializes all core subsystems and starts the Lua runtime. * The system is then driven by Lua scripts and BLE events. */ int main(void) { int ret; #ifdef CONFIG_HALO_WATCHDOG_MANAGER if (halo_watchdog_has_fired()) { // Reboot on watchdog timeout, make sure everything is fresh #ifdef CONFIG_HALO_BLE_MANAGER halo_ble_conn_prepare_reboot(); #endif sys_reboot(SYS_REBOOT_COLD); } #endif #ifdef CONFIG_HALO_LOG_LEVEL_DBG printk(\n%s, halo_banner); printk(Hardware Version: %s\n, CONFIG_BOARD); printk(Firmware Version: %s\n, APP_VERSION_STRING); printk(Build Date: %s\n, __DATE__); #endif #ifdef CONFIG_HALO_PM_MANAGER /* Initialize power manager */ ret halo_pm_init(); if (ret 0) { __ASSERT(false, Failed to initialize power manager: %d, ret); return ret; } #endif #ifdef CONFIG_HALO_MEM_MANAGER /* Initialize memory manager */ ret halo_mem_init(); if (ret 0) { __ASSERT(false, Failed to initialize memory manager: %d, ret); return ret; } #endif #ifdef CONFIG_HALO_WATCHDOG_MANAGER /* Initialize watchdog manager */ ret halo_watchdog_init(); if (ret 0) { __ASSERT(false, Failed to initialize watchdog manager: %d, ret); return ret; } #endif #ifdef CONFIG_HALO_LED_MANAGER /* Initialize LED manager */ ret halo_led_init(); if (ret 0) { __ASSERT(false, Failed to initialize LED manager: %d, ret); return ret; } #endif #ifdef CONFIG_HALO_BATTERY_MANAGER /* Initialize battery manager */ ret halo_battery_init(); if (ret 0) { __ASSERT(false, Failed to initialize battery manager: %d, ret); return ret; } #endif #ifdef CONFIG_HALO_FILE_MANAGER /* Initialize file manager */ ret halo_file_init(); if (ret 0) { __ASSERT(false, Failed to initialize file manager: %d, ret); return ret; } #endif #ifdef CONFIG_HALO_BLE_MANAGER /* Initialize BLE manager */ ret halo_ble_init(NULL); if (ret 0) { __ASSERT(false, Failed to initialize BLE manager: %d, ret); return ret; } #endif /* CONFIG_HALO_BLE_MANAGER */ #if defined(CONFIG_HALO_STARTUP_SOUND) || defined(CONFIG_HALO_BOOT_LOGO) /* * Boot splash: kick off the (async) startup sound and draw the logo * BEFORE the Lua runtime starts. main.lua runs on the REPL thread as * soon as halo_lua_runtime_init() is called and would clear the display * out from under the logo. Holding here on the main thread (which only * sleeps forever afterwards) keeps the splash up with no race against * the app: we wait for the sound to finish (when enabled), then top up * to a minimum hold time. An unpaired device holds longer and shows its * BLE name under the logo so the user can identify it while pairing. */ #ifdef CONFIG_HALO_STARTUP_SOUND halo_startup_sound_schedule(); #endif #ifdef CONFIG_HALO_BOOT_LOGO bool splash_unpaired false; const char *splash_label NULL; #ifdef CONFIG_HALO_BLE_MANAGER splash_unpaired !halo_ble_sec_is_bonded(); if (splash_unpaired) { splash_label halo_ble_conn_get_device_name(); } #endif int64_t splash_start k_uptime_get(); if (halo_display_boot_logo_show(splash_label) 0) { #ifdef CONFIG_HALO_STARTUP_SOUND /* Bounded so a missing/stuck speaker cant stall boot. */ halo_startup_sound_wait(CONFIG_HALO_STARTUP_SOUND_TIMEOUT_MS CONFIG_HALO_STARTUP_SOUND_DURATION_MS 250); #endif int64_t hold_ms splash_unpaired ? CONFIG_HALO_BOOT_LOGO_UNPAIRED_HOLD_MS : CONFIG_HALO_BOOT_LOGO_MIN_HOLD_MS; int64_t remaining_ms hold_ms - (k_uptime_get() - splash_start); if (remaining_ms 0) { k_sleep(K_MSEC(remaining_ms)); } halo_display_boot_logo_hide(); } #endif #endif #ifdef CONFIG_HALO_LUA_RUNTIME /* Initialize Lua runtime - this is the core of the system */ ret halo_lua_runtime_init(); if (ret 0) { __ASSERT(false, Failed to initialize Lua runtime: %d, ret); return ret; } #endif #if defined(CONFIG_BOOTLOADER_MCUBOOT) defined(CONFIG_MCUBOOT_IMG_MANAGER) /* * Mark this image as confirmed now that the full boot sequence has * succeeded. This must be the last step of bring-up: if any subsystem * above hangs or faults, the image stays unconfirmed and MCUboot reverts * to the previously good image on the next reset (the app-level watchdog * provides that reset). Confirming earlier would defeat that safety net. * boot_write_img_confirmed() is a no-op when the image is already confirmed. */ ret boot_write_img_confirmed(); if (ret 0) { LOG_ERR(Failed to confirm MCUboot image: %d, ret); } else { LOG_INF(MCUboot image confirmed); } #endif #if defined(CONFIG_HALO_STARTUP_SOUND) || defined(CONFIG_HALO_SHUTDOWN_SOUND) /* Boot settled: re-arm the boot/shutdown cues for the next power-on. * Must stay after the image confirm so a boot that ends earlier keeps * the cue gate flag set (see CONFIG_HALO_CUE_GATE_DIRTY_BOOT). */ halo_sound_cue_boot_settled(); #endif while (1) { k_sleep(K_FOREVER); } return 0; }从代码可以看出main还是很简单就只有一系列初始化。只做装配依次初始化 mem_manager → file_manager → pm_manager → led_manager → battery → watchdog → ble_manager然后启动 Lua运行时之后系统完全由Lua脚本和BLE事件驱动。prj.conf# Zephyr Project Configuration File # Zephyr Base Configuration CONFIG_ASSERTy CONFIG_LOGy CONFIG_LOG_DEFAULT_LEVEL2 CONFIG_LOG_BUFFER_SIZE8192 CONFIG_LOG_PROCESS_THREAD_CUSTOM_PRIORITYy CONFIG_LOG_PROCESS_THREAD_PRIORITY3 CONFIG_LOG_PROCESS_THREAD_STACK_SIZE2048 # Log Filesystem Backend — persist logs to LittleFS. DISABLED on this # branch: littlefs writes hit the same flash the code executes from, so # every persisted log line (e.g. the AECs 10-s load INF) stalls the # whole system mid-audio-session — the same mechanism as the /lfs # capture-write emission gaps the AEC harnesses had to design around. # Also returns the 2x16KB log files to /lfs. Re-enable when the audio # timing work no longer needs stall-free sessions (the logs skill # depends on it for post-flash diagnostics; verify.py still covers # boot checks). CONFIG_LOG_BACKEND_FSn # CONFIG_LOG_BACKEND_FS_DIR/lfs # CONFIG_LOG_BACKEND_FS_AUTOSTARTy # CONFIG_LOG_BACKEND_FS_OVERWRITEy # CONFIG_LOG_BACKEND_FS_FILE_PREFIXlog. # CONFIG_LOG_BACKEND_FS_FILE_SIZE16384 # CONFIG_LOG_BACKEND_FS_FILES_LIMIT2 # System Workqueue Configuration CONFIG_MAIN_STACK_SIZE4096 CONFIG_ISR_STACK_SIZE4096 CONFIG_PRIVILEGED_STACK_SIZE2048 CONFIG_IDLE_STACK_SIZE2048 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE4096 # Power Management Configuration CONFIG_PMy CONFIG_PM_DEVICEy # Thread Monitoring and Debugging CONFIG_THREAD_NAMEy CONFIG_THREAD_MONITORy CONFIG_THREAD_STACK_INFOy CONFIG_THREAD_RUNTIME_STATSy # Halo Framework CONFIG_HALOy # Acoustic echo cancellation (speaker leakage removed from the mic path) CONFIG_HALO_AUDIO_AECy CONFIG_HALO_AUDIO_AEC_TAPS1024 CONFIG_MPIX_LOG_LEVEL_WRNy CONFIG_FS_LOG_LEVEL_WRNy # Memory Manager Configuration # The libc malloc arena defaults to all RAM left after static allocations, # which had decayed to ~50 bytes - any .bss growth then fails the sys_heap # minimum-size assert in malloc_prepare() and the image panics at boot. # Pin the arena explicitly and give back one page from the internal pool so # the link keeps real headroom. CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE2048 # (also funds the AECs 256ms reference ring and its ~3.3KB paired-capture # snapshot buffers - see audio_aec.c) CONFIG_HALO_MEM_INTERNAL_SIZE352256 CONFIG_HALO_MEM_USE_EXTERNAL_SRAMy CONFIG_HALO_MEM_EXTERNAL_SRAM_ADDR0x00000000 # The first 64KB of ITCM belong to the AEC FDAF state (the linkers ITCM # section; BUILD_ASSERTed in audio_aec.c to fit below this offset) - the # region-1 heap starts above it. Was offset 4096 (NULL guard) 520192. CONFIG_HALO_MEM_EXTERNAL_SRAM_OFFSET65536 CONFIG_HALO_MEM_EXTERNAL_SRAM_SIZE458752 CONFIG_HALO_MEM_MANAGER_STATSy # Flash and Storage Configuration CONFIG_FLASHy CONFIG_FLASH_MAPy CONFIG_FLASH_PAGE_LAYOUTy CONFIG_MPU_ALLOW_FLASH_WRITEy # LittleFS Configuration CONFIG_FILE_SYSTEM_LITTLEFSy CONFIG_FS_LITTLEFS_FMP_DEVy # Settings Configuration CONFIG_SETTINGSy CONFIG_SETTINGS_FILEy CONFIG_SETTINGS_FILE_PATH/lfs/settings # Sensor Configuration for Battery Service CONFIG_SENSORy CONFIG_SENSOR_INIT_PRIORITY60 # Regulator Init Priority # cam_1v8 (regulator-fixed, priority 32) must initialize before tps65132 # (REGULATOR_TPS65132_COMMON_INIT_PRIORITY61), since tps65132 has # vin-supply cam_1v8 and checks device_is_ready() during init. CONFIG_REGULATOR_FIXED_INIT_PRIORITY32 # LED Configuration for Battery Charging Indicator CONFIG_PWMy CONFIG_LED_PWMy # Halo BLE Manager Configuration CONFIG_HALO_BLE_MAX_SERVICES8 CONFIG_HALO_BLE_BOND_STORAGEy CONFIG_HALO_BLE_REQUIRE_PAIRINGy CONFIG_HALO_BLE_ALLOW_BOND_OVERWRITEn # BLE Lua Service Configuration CONFIG_HALO_BLE_LUA_SERVICEy CONFIG_HALO_LUA_MAX_REPL_SIZE1024 CONFIG_HALO_LUA_MAX_DATA_SIZE4096 CONFIG_HALO_AUDIO_MAX_DATA_SIZE8192 CONFIG_HALO_SFXRy CONFIG_HALO_LUA_SOUNDy CONFIG_HALO_STARTUP_SOUNDy CONFIG_HALO_STARTUP_SOUND_PRESETpowerup CONFIG_HALO_STARTUP_SOUND_SEED4149902225 CONFIG_HALO_STARTUP_SOUND_DURATION_MS1000 # Boot/shutdown cues play at the app-wide SFXR level (20). CONFIG_HALO_STARTUP_SOUND_VOLUME20 CONFIG_HALO_SHUTDOWN_SOUNDy CONFIG_HALO_SHUTDOWN_SOUND_PRESETlaser CONFIG_HALO_SHUTDOWN_SOUND_SEED573636714 CONFIG_HALO_SHUTDOWN_SOUND_DURATION_MS700 CONFIG_HALO_SHUTDOWN_SOUND_VOLUME20 # Boot logo splash (drawn pre-runtime_init, held for the startup sound duration) CONFIG_HALO_BOOT_LOGOy # Lua Runtime Configuration CONFIG_HALO_LUA_RUNTIMEy # REPL thread: 128KB stack for Lua VM and complex user scripts CONFIG_HALO_LUA_REPL_TASK_STACK_SIZE65536 CONFIG_HALO_LUA_REPL_TASK_PRIORITY7 # Watchdog Configuration CONFIG_HALO_WATCHDOG_MANAGERy CONFIG_HALO_WATCHDOG_TIMEOUT_MS5000 CONFIG_HALO_WATCHDOG_ALLOW_CALLBACKy CONFIG_HALO_WATCHDOG_AUTO_FEEDy CONFIG_HALO_WATCHDOG_AUTO_FEED_PRIORITY2 CONFIG_HALO_WATCHDOG_AUTO_FEED_STACK_SIZE512 CONFIG_HALO_WATCHDOG_FEED_INTERVAL_MS1000 CONFIG_HALO_BLE_MANAGERy CONFIG_HALO_SE_MGMTy CONFIG_BOOT_BANNERn CONFIG_HALO_BATTERY_MANAGERy CONFIG_HALO_LED_MANAGERy CONFIG_HALO_WATCHDOG_MANAGERy CONFIG_HALO_LUA_RUNTIMEy CONFIG_HALO_BLE_ALLOW_BOND_OVERWRITEn CONFIG_HALO_BLE_AUDIO_SERVICEy CONFIG_HALO_BLE_AUDIO_SINK_ENABLEy CONFIG_HALO_BLE_AUDIO_OUTPUT_STEREOy CONFIG_HALO_BLE_AUDIO_SOURCE_ENABLEy CONFIG_HALO_BLE_AUDIO_INPUT_STEREOn # Set a current budget for the speakers to avoid tripping the battery protection IC CONFIG_MAX98357A_AUDIO_PROTECT_BUDGET_PERCENT804 LUA层启动是在main里面#ifdef CONFIG_HALO_LUA_RUNTIME /* Initialize Lua runtime - this is the core of the system */ ret halo_lua_runtime_init(); if (ret 0) { __ASSERT(false, Failed to initialize Lua runtime: %d, ret); return ret; } #endif在里面启动核心线程lua_repl_thread_fn。REPL Read–Eval–Print Loop中文通常叫“读取—求值—输出循环”。它是一种交互式程序运行方式输入一条指令系统执行它并显示结果然后等待下一条指令。之前在AR1的项目里面MCU基本上也是这样的模式。在里面一个核心是启动虚拟机lua_vm_init(lua_ctx.L);LUA异步事件处理Lua 绑定文件对应外设 API绑定文件暴露给 Lua 的frame.*命名空间lua_display.cframe.displayMIPI-DSI 屏幕绘制lua_microphone.cframe.microphonePDM 录音AAD 检测lua_speaker.cframe.speakerLC3/PCM 播放lua_bluetooth.cframe.bluetooth数据收发lua_camera.cframe.camera图像采集lua_imu.cframe.imu加速度计/陀螺仪、tap 检测lua_button.cframe.button按键事件lua_file.cframe.fileLittleFS 读写lua_compression.cframe.compressionLZ4 压缩lua_time.cframe.timeRTC 时间lua_system.cframe.system版本、重启等lua_log.cframe.log日志输出lua_sound.cframe.soundSFXR 音效比如手机发送 frame.camera.capture() 的完整执行轨迹[手机 App]│ 通过 BLE 发送字符串 frame.camera.capture()\n▼[眼镜端 BLE 接收通道 (ble_lua.c)]│ 写入环形接收缓冲区▼[lua_repl_thread_fn 线程] ◄─── 你问的核心就在这里│├─ 1. halo_ble_lua_repl_read() 读出这段字符串├─ 2. 按 \n 识别出这是一条完整命令: frame.camera.capture()├─ 3. 调用 Lua 引擎: luaL_dostring(L, frame.camera.capture())│ ││ ▼│ [Lua 虚拟机寻址]│ 找到 C 函数绑定表中的 lua_camera_capture() (位于 lua_camera.c)│ ││ ▼├─ 4. 在 REPL 线程中执行 lua_camera_capture(L):│ • 检查摄像头状态与分辨率 (默认 640x640)│ • 配置视频格式与 DMA 缓冲区│ • 释放信号量: k_sem_give(camera_state.capture_sem) ──┐│ • 函数立即返回REPL 线程不会在此死等拍照完成 │ (异步唤醒)│ ▼[后台摄像头采集线程 (camera_thread_fn)] ◄────────────────────────┘│├─ 5. 等到信号量被唤醒控制硬件拍摄│ • 向底层 PAG7982 驱动发抓帧指令│ • 硬件 CPI DMA 自动将像素数据搬移至内存│ • 硬件/软件压缩为 JPEG 并存入静态全局缓冲│ • 标记: camera_state.ready true5 BLE层官方参考文档BLE_SERVICES.md。整体架构核心控制服务Halo Lua Service (7A230001-5475-A6A4-654C-8431F6AD49C4)这是手机控制眼镜的最核心服务包含 3 个 Characteristic特征值 (UUID)属性通信方向核心功能LUA RX(7A230002...)Write / Write Without Response手机 ➔ 眼镜下行控制通道手机向眼镜发控制指令、动态 Lua 脚本或二进制透传数据MTU 512 字节。LUA TX(7A230003...)Notify眼镜 ➔ 手机上行响应通道眼镜向手机返回执行结果、print()终端输出、主动上报的传感器事件或应用数据。AUDIO RX(7A230005...)Write / Write Without Response手机 ➔ 眼镜独立音频下行专用于手机向眼镜扬声器流式推送 PCM / LC3 音频数据。BLE命令协议Header byte含义0x01数据帧用户数据通道0x02CtrlB重启设备0x03CtrlC中断脚本可被 pcall 捕获0x04CtrlD重启 Lua VM不可被捕获0x05CtrlE删除 main.lua 并重启0x06CtrlF完全退出 Lua 运行时0x07CtrlG删除所有文件保留 settings在蓝牙接收数据时候对数据进行了分流。手机写入 LUA RX 特征值│▼[第一道关卡: ble_lua.c (蓝牙接收回调)]│┌───────────────┴───────────────┐│ │首字节 0x02 ~ 0x07 首字节 ! 0x02 ~ 0x07 (ASCII 文本)【单字节硬控制指令】 【普通 Lua 代码字符串】│ │▼ ▼【在此处立刻拦截处理】 写入 repl_rx_ring 缓冲区• 0x02: 直接调 sys_reboot() 重启 │• 0x03: 强行置位中断信号 (CtrlC) │• 0x04: 标记 running false 重启 VM │• 0x05: 删除 main.lua ▼• 根本不会传给 lua_repl_thread_fn [第二道关卡: lua_repl_thread_fn]从缓冲区读出字符串:frame.camera.capture()\n│▼交给 Lua VM 解释执行:luaL_dostring(...)两个通道的分工如下【阶段 1启动部署阶段】手机走【文本通道 (Lua REPL)】┌──────────────────────────────────────────────┐│ 手机下发整个业务脚本 duplex_frame_app.lua: ││ 1. 注册消息协议表 handlers[0x12] show_text ││ 2. 绑定蓝牙接收: frame.bluetooth.receive_cb ││ 3. 绑定敲击唤醒: frame.imu.tap_callback │└──────────────────────────────────────────────┘│▼ 脚本部署就绪进入常驻监听【阶段 2高频实时交互阶段】手机与眼镜走【二进制透传通道 (0x01)】┌──────────────────────────────────────────────┐│ • 用户说话眼镜通过 BLE TX 高频回传音频分片 ││ • 手机返回首字节 0x01 业务码 (0x12 文字) ││ • 零内存开销直接触发 receive_cb 高频流式显示 │└──────────────────────────────────────────────┘│▼ 发生异常/退出【阶段 3急刹车/生命周期重置】手机走【单字节控制通道 (0x02~0x07)】┌──────────────────────────────────────────────┐│ 手机写入 0x03 (打断) 或 0x04 (重启重置) │└──────────────────────────────────────────────┘6 Zeypher集成7 音频子系统8 IMU子系统9 Camera子系统
延伸阅读

更多相关文章

2026/10/19 7:00:21

木工DIY桌面收纳手作攻略:从选材到树脂拼接

artcraft这个名字,听起来像个工作室代号,其实是我最近做完的一件桌面小木作的工程名——全称可以理解为"艺术工艺"。它的最终成品是一块约30cm20cm的多层拼接木托,左侧有个下沉小托盘用来放钥匙、U盘、桌面零碎,右侧是一…

2026/10/19 6:55:21

【项目】【在线判题系统】竞赛列表

目录一、表的设计二、实体类三、功能梳理四、controller五、service六、mapper一、表的设计 一张竞赛表,以及一张竞赛题目关联表 CREATE TABLE tb_exam (exam_id BIGINT UNSIGNED NOT NULL COMMENT 竞赛id(主键),title VARCHAR(50) NOT NULL…

2026/10/19 6:55:21

基于YOLOv26的绝缘子缺陷检测系统:从数据到部署全流程实践

电力绝缘子缺陷检测这几年在巡检圈子里真的是绕不开的话题,输电线路上的绝缘子数量大、分布广,尤其是山区和林区的杆塔,人工巡检一趟成本极高,而且很多缺陷在肉眼看来并不明显。我这次要分享的,是同事前段时间做的一个…

2026/10/19 8:20:29

MCP开源项目:让AI Agent读懂无源码的黑盒软件

1. 项目概述:为什么一个 MCP 能两天涨星近 10 万我刷到这个消息的时候第一反应是去看日历,确认不是四月一号。两天涨星近 10 万,放在整个开源圈都是相当炸裂的数据。如果你常年混迹开源社区,应该清楚一个项目正常情况下的涨星曲线…

2026/10/19 8:20:29

Docker部署SRS直播集群:从单机瓶颈到Origin-Edge横向扩展

一台服务器撑不住一万人在线看直播,这个问题跟SRS本身的关系不大,更多是单节点物理上限的问题。前阵子帮朋友调一个RTMP直播服务,单台SRS跑测试一切正常,推流不卡、画面延迟也稳定,结果活动一上线,上千路播…

2026/10/19 8:20:29

YOLOv5自动标注工程化实践:构建质量可控的落地流水线

1. 为什么“自动标注”不是点几下鼠标就能跑通的事YOLOv5被很多人当成目标检测的“万能钥匙”——模型结构清晰、训练快、精度稳、社区资源多,连刚接触CV的新手都能在两小时内跑通官方Demo。但一旦把“用YOLOv5做自动标注”这句话从PPT搬到真实项目里,90…

2026/10/19 8:20:29

LACP链路聚合原理与华为设备实战配置指南

1. 为什么链路聚合不是“堆线就能提速”,而LACP才是企业级网络的刚需在某次为某高校数据中心做网络优化时,我遇到一个典型场景:核心交换机到服务器集群的上行带宽长期跑满,运维同事第一反应是“再加一根网线不就完了?”…

2026/10/19 8:20:29

最近点对问题:从蛮力到分治的算法优化指南

刚开始接触最近点对问题,是在某次算法课程的大作业里:题目要求从几千个坐标点里找出距离最近的两个点。我当时随手写了个蛮力双层循环,几十毫秒跑完,心里想的是——这种题也配叫经典?直到后来做一个上万节点的模拟项目…

2026/10/19 8:15:29

SMPL模型详解:参数化人体骨架的原理与Python实践

简介:本资源是一份面向计算机图形学与三维人体建模初学者的SMPL模型解析实践包,聚焦Python环境下的SMPL基础结构理解与数据加载操作。资源完整呈现SMPL官方模型的核心组成:6890个顶点网格、24个关节(含根节点)及其对应…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/19 0:04:56

悟空开源无代码平台实战:从实体建模到应用设计避坑指南

简介:基于悟空开源无代码平台的多种应用设计源码,面向希望在不编写代码的情况下快速搭建CRM、HRM、财务系统、ERP、SRM等业务应用的企业与技术人员,通过拖放式界面和内置模板即可完成应用定制与部署。压缩包共697个文件,约10.74MB…

2026/10/19 0:04:56

基于.NET9的多租户权限系统:数据权限与动态API落地实践

简介:这份资源是一套面向 .NET 与 Vue 全栈开发者的中台权限管理系统,后端基于 .Net9,前端采用 Vue3 Element Plus,并配套 uniapp uviewui 移动端方案,实现前后端分离。系统覆盖多租户隔离、数据权限、动态 Api、任务…

2026/10/19 0:04:56

场地预约小程序毕设实战:SSM+微信小程序+MySQL数据库设计到避坑

简介:面向毕业设计场景的场地预约小程序完整项目,基于微信小程序SSMMySql技术栈开发,适合计算机相关专业学生作为选题参考、功能扩展或二次开发起点。系统实现场地类型管理、场地管理、预约管理、取消申请与押金退回等功能,分为管…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑