📺 B站视频讲解(Bilibili):https://www.bilibili.com/video/BV1k1C9BYEAB/
📘 《Yocto项目实战教程》京东购买链接:Yocto项目实战教程
Rockchip BLE 低功耗唤醒方案:基于广播扫描的产品级设计与实战(含可执行步骤与代码)
目标:在 Rockchip 设备上,让 Camera 进入低功耗(系统 suspend),由 平板通过 BLE 广播唤醒,Camera 不建立连接,仅通过 Scan 接收广播 → 命中规则 → 触发系统唤醒 完成唤醒;唤醒后可选择 广播 30 秒在线状态。
本文输出:
- 核心原理:为什么“广播 + 扫描”适合低功耗唤醒;为什么不需要连接;RSSI 判定是谁做。
- 协议设计:如何在广播包里“可产品化地识别目标设备”,避免依赖 MAC/名称。
- Rockchip 实战:BlueZ/内核/电源管理的可执行步骤;如何抓包看到 advertise 内容;如何写代码解析;如何做“4 Camera + 1 平板”的唤醒。
- 可执行方案:给出可运行的脚本与(可编译)C 程序,附 systemd 服务示例。

1. 先把模型说清楚:你要的不是“蓝牙连接”,而是“蓝牙事件触发唤醒”
1.1 广播/扫描的本质
- Advertise(广播):设备向空气中“喊话”,单向发送。
- Scan(扫描):设备“竖起耳朵听”,接收广播。
- RSSI(信号强弱):永远由 接收方(Scan 端) 测量得出。
结论:
- 想“唤醒自己”:你的设备必须具备 Scan 接收能力。
- 广播端永远不知道有没有人靠近,它只是在发。
1.2 为什么低功耗唤醒不推荐“连接”
连接(GATT)意味着:
- 需要建立/维护连接状态(心跳、超时、参数协商)。
- 功耗更高、稳定性更复杂。
而唤醒只是一个“事件触发”,最适合:
- 广播发命令(平板)
- 低占空比扫描(Camera)
- 命中后触发唤醒(GPIO 或 wakeup source)
2. 产品级关键:不要用设备名称/MAC 做识别,使用 Manufacturer Specific Data(0xFF)
2.1 为什么不建议用 Name / MAC
- 名称(Local Name):可变、可缺失、易仿冒,适合调试,不适合产品协议。
- MAC 地址:BLE 支持随机地址(random address),很多设备会周期性变化,不适合长期绑定。
2.2 推荐:Manufacturer Specific Data(AD Type 0xFF)
BLE 广播数据是 TLV 结构:
[Len][Type][Value...] [Len][Type][Value...] ...
其中 Type=0xFF 表示 厂商自定义数据,行业主流 Beacon/IoT/门禁/车钥匙/Camera 唤醒都用它。
2.3 推荐协议(可直接量产)
定义一段固定长度的 Manufacturer Data(示例 7 字节负载):
| 字节偏移 | 字段 | 示例 | 说明 |
|---|---|---|---|
| 0-1 | Company ID | 0x1234 | Bluetooth SIG 分配(示例值) |
| 2 | Product ID | 0x01 | Camera 产品类型 |
| 3 | Target ID | 0xFF 或 0x01~0x04 | 0xFF=全部 Camera,1~4=指定 Camera |
| 4 | CMD | 0xA5 | 0xA5=WAKE |
| 5 | Token | 0x66 | 简单校验/防误触(可扩展) |
| 6 | CRC/Version | 0x01 | 可选,版本/CRC |
设计要点:固定长度、可快速匹配、便于 Controller 层过滤。
3. 系统级设计:4 台 Camera + 1 台平板的整体状态机
3.1 逻辑图(建议写进设计文档/PPT)
flowchart LR
T[Tablet 平板
BLE Advertise: WAKE] -->|广播| AIR((Air))
AIR --> A[Camera A
低功耗 Scan]
AIR --> B[Camera B
低功耗 Scan]
AIR --> C[Camera C
低功耗 Scan]
AIR --> D[Camera D
低功耗 Scan]
A -->|命中 Target=All 或 A_ID| WAKE_A[触发唤醒]
B -->|命中 Target=All 或 B_ID| WAKE_B[触发唤醒]
C -->|命中 Target=All 或 C_ID| WAKE_C[触发唤醒]
D -->|命中 Target=All 或 D_ID| WAKE_D[触发唤醒]
WAKE_A --> RUN_A[系统 Resume]
RUN_A --> ADV_A[广播在线状态 30s]
3.2 Camera 端的最小判定逻辑
if company_id == 0x1234
and product_id == CAMERA
and cmd == WAKE
and (target == ALL || target == MY_ID)
and rssi > RSSI_THRESHOLD
then wake_system()
- RSSI 阈值(例如 -65 dBm)用于避免远距离误唤醒。
- Token 用于简单鉴权/防误触(可做滚动码升级)。
4. Rockchip 上实现低功耗唤醒:两种工程路线
路线 A(推荐,产品级):Controller 层过滤 + GPIO/唤醒源
- BLE Controller 在低功耗仍保持低占空比扫描。
- 命中特定 Manufacturer Data 后,触发 Wake GPIO / Wake IRQ。
- SoC 从 suspend/resume 起来。
优点:
- 功耗最低
- CPU 无需常驻解析
- 抗干扰/稳定
路线 B(易落地,开发阶段):Host 解析(BlueZ)+ wakeup source
- 系统未进入最深睡眠或使用 s2ram
- HCI 事件上报到主机
- 用户态/内核解析命中后触发唤醒
优点:
- 更通用
- 便于调试
本文优先讲:路线 B 可快速验证,再给出如何演进到路线 A。
5. 如何“看到”对方的 Advertise 数据:抓包与验证步骤(Rockchip)
5.1 环境检查
- 确认控制器存在:
hciconfig -a
- 确认 BlueZ 工具:
bluetoothctl -v
btmgmt --version || true
btmon -v || true
如果缺少工具:在 Yocto 中把
bluez5、bluez5-tools(发行版命名可能略有差异)加入镜像。
5.2 使用 btmon 抓 HCI(推荐)
btmon 能看到 LE Advertising Report,包括 RSSI 与原始 payload。
btmon &
# 另一个终端开启扫描
bluetoothctl
[bluetooth]# power on
[bluetooth]# scan on
此时你会在 btmon 输出中看到类似:
- 地址
- RSSI
- Advertising Data
- Manufacturer Specific Data(0xFF)
5.3 使用 bluetoothctl 查看扫描结果(简版)
bluetoothctl
scan on
# 看到设备出现,但 bluetoothctl 默认不展示完整 payload
因此:
- 要看 payload:用 btmon
- 仅看设备出现:bluetoothctl 足够
6. 平板侧如何发“唤醒广播”:最小可执行方案
平板(Android/Linux)可以选择:
- Android APP(BLE Advertiser API)
- Linux 平板:
bluetoothd+btmgmt或 直接 HCI
本文给出 Linux 可执行路径(易验证)。
6.1 Linux 平板:用 btmgmt 发送广播(思路)
不同 BlueZ 版本在命令细节上存在差异,工程上更稳定的做法是:
- 写一个小工具,直接通过 HCI 下发
LE Set Extended Advertising Data。
下面给出 可运行的 HCI 脚本(与 Rockchip/BCM 常见脚本风格一致),用于发送 manufacturer data。
发送 WAKE 广播脚本(tablet_adv_wake.sh)
#!/bin/bash
set -e
# 示例:Company=0x1234, Product=0x01, Target=0xFF(All), CMD=0xA5, Token=0x66
COMPANY_L=0x34
COMPANY_H=0x12
PRODUCT=0x01
TARGET=${1:-0xFF}
CMD=0xA5
TOKEN=0x66
# Extended Advertising 参数/数据命令可能因控制器略有不同。
# 这里用 hcitool cmd 演示(部分系统已弃用 hcitool,但仍常用于工程验证)。
# 1) 设置扩展广播参数
hcitool cmd 0x08 0x0036 \
0x00 0x13 0x00 0x90 0x01 0x00 0xc2 0x01 0x00 0x07 0x00 \
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x01 0x00 0x00
# 2) 设置扩展广播数据(TLV)
# Flags: 02 01 06
# Mfg: 07 FF 34 12 01 FF A5 66
hcitool cmd 0x08 0x0037 \
0x00 0x03 0x01 \
0x02 0x01 0x06 \
0x07 0xFF $COMPANY_L $COMPANY_H $PRODUCT $TARGET $CMD $TOKEN
# 3) 启用广播
hcitool cmd 0x08 0x0039 0x01 0x01 0x00 0x00 0x00 0x00
echo "[tablet_adv_wake] advertising wake cmd target=${TARGET}"
使用方法:
chmod +x tablet_adv_wake.sh
# 唤醒全部 Camera
./tablet_adv_wake.sh 0xFF
# 唤醒 Camera #2
./tablet_adv_wake.sh 0x02
提示:上述扩展广告命令与参数在不同控制器上可能需要微调。验证阶段先用 btmon 观察是否成功发出 Manufacturer Data。
7. Camera 侧如何“Scan 并获取 advertise 内容”:两种写法
- 写法 1:btmon 抓包 + 解析(调试用)
- 写法 2:BlueZ D-Bus 扫描回调 + 解析 Manufacturer Data(产品软件层常用)
本文给出“写法 2”:用 C 通过 D-Bus 监听 org.bluez.Device1 的 ManufacturerData。
8. Camera 端 C 程序:扫描并解析 ManufacturerData,命中后执行唤醒动作
说明:为了“可执行”,这里给出一个 基于 BlueZ D-Bus 的实现框架。它适合:
- 系统处于轻睡眠/待机(CPU 未完全断电或允许 D-Bus 服务运行)
- 或作为开发阶段验证(先把协议与过滤跑通)
当你需要进入更深的低功耗,建议迁移到 Controller 层过滤 + GPIO 唤醒(见第 11 节)。
8.1 依赖
libdbus-1-dev(或对应 Yocto SDK 头文件)- BlueZ
bluetoothd
8.2 代码:ble_wake_scanner.c
功能:
- 打开 Adapter 扫描
- 监听新增 Device 对象
- 读取
ManufacturerData与RSSI - 命中协议后执行动作(示例:写一个文件/调用脚本)
// ble_wake_scanner.c
// build: gcc -O2 -Wall ble_wake_scanner.c -o ble_wake_scanner $(pkg-config --cflags --libs dbus-1)
#include <dbus/dbus.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define COMPANY_ID 0x1234
#define PRODUCT_ID 0x01
#define CMD_WAKE 0xA5
// 根据你的场景调整
#define RSSI_THRESHOLD (-65)
#define MY_CAMERA_ID 0x02 // 例:本机为 Camera #2
static void die(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
// 触发唤醒动作:这里用最小可执行方式演示
// 真正产品可以:拉 GPIO、写 /sys/power/wakeup、发 DBus 给 power manager 等
static void trigger_wakeup(void) {
fprintf(stdout, "[ble_wake] TRIGGER WAKEUP!\n");
// 示例:调用外部脚本(你可以替换成 systemctl start xxx 或 GPIO 操作)
system("/usr/local/bin/wake_action.sh");
}
// 解析 ManufacturerData(BlueZ 中是 dict<uint16, variant(array<byte>)>)
// 我们只关心 key==COMPANY_ID 的条目,并解析 value。
static int parse_mfg_data(DBusMessageIter *dict_iter, int rssi) {
// dict entry: key(uint16) -> variant(array<byte>)
DBusMessageIter entry;
dbus_message_iter_recurse(dict_iter, &entry);
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_UINT16)
return 0;
dbus_uint16_t key = 0;
dbus_message_iter_get_basic(&entry, &key);
// move to value (variant)
dbus_message_iter_next(&entry);
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
return 0;
DBusMessageIter var;
dbus_message_iter_recurse(&entry, &var);
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_ARRAY)
return 0;
if (key != COMPANY_ID)
return 0;
// array of bytes
DBusMessageIter arr;
dbus_message_iter_recurse(&var, &arr);
unsigned char buf[32];
int n = 0;
while (dbus_message_iter_get_arg_type(&arr) == DBUS_TYPE_BYTE && n < (int)sizeof(buf)) {
dbus_message_iter_get_basic(&arr, &buf[n]);
n++;
dbus_message_iter_next(&arr);
}
// 期望协议:Product(1) Target(1) CMD(1) Token(1) ...
if (n < 4)
return 0;
unsigned char product = buf[0];
unsigned char target = buf[1];
unsigned char cmd = buf[2];
unsigned char token = buf[3];
if (product != PRODUCT_ID)
return 0;
if (!(target == 0xFF || target == MY_CAMERA_ID))
return 0;
if (cmd != CMD_WAKE)
return 0;
// Token 可扩展为 rolling code/CRC
(void)token;
if (rssi < RSSI_THRESHOLD) {
fprintf(stdout, "[ble_wake] matched but RSSI too low: %d\n", rssi);
return 0;
}
fprintf(stdout, "[ble_wake] matched WAKE (rssi=%d)\n", rssi);
return 1;
}
// 监听 PropertiesChanged 信号,读取 ManufacturerData/RSSI
static void process_properties_changed(DBusMessage *msg) {
DBusMessageIter it;
if (!dbus_message_iter_init(msg, &it))
return;
// interface name
const char *iface = NULL;
if (dbus_message_iter_get_arg_type(&it) != DBUS_TYPE_STRING)
return;
dbus_message_iter_get_basic(&it, &iface);
if (!iface || strcmp(iface, "org.bluez.Device1") != 0)
return;
// changed properties dict
dbus_message_iter_next(&it);
if (dbus_message_iter_get_arg_type(&it) != DBUS_TYPE_ARRAY)
return;
int rssi = -999;
int mfg_hit = 0;
DBusMessageIter arr;
dbus_message_iter_recurse(&it, &arr);
while (dbus_message_iter_get_arg_type(&arr) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry;
dbus_message_iter_recurse(&arr, &entry);
// key
const char *key = NULL;
if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
dbus_message_iter_get_basic(&entry, &key);
}
dbus_message_iter_next(&entry);
if (!key || dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
dbus_message_iter_next(&arr);
continue;
}
DBusMessageIter var;
dbus_message_iter_recurse(&entry, &var);
if (strcmp(key, "RSSI") == 0 && dbus_message_iter_get_arg_type(&var) == DBUS_TYPE_INT16) {
dbus_int16_t v;
dbus_message_iter_get_basic(&var, &v);
rssi = (int)v;
}
if (strcmp(key, "ManufacturerData") == 0 && dbus_message_iter_get_arg_type(&var) == DBUS_TYPE_ARRAY) {
DBusMessageIter dict;
dbus_message_iter_recurse(&var, &dict);
// dict entries
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
if (parse_mfg_data(&dict, rssi)) {
mfg_hit = 1;
break;
}
dbus_message_iter_next(&dict);
}
}
dbus_message_iter_next(&arr);
}
if (mfg_hit) {
trigger_wakeup();
}
}
static void start_discovery(DBusConnection *conn) {
DBusError err;
dbus_error_init(&err);
DBusMessage *msg = dbus_message_new_method_call(
"org.bluez",
"/org/bluez/hci0",
"org.bluez.Adapter1",
"StartDiscovery");
if (!msg)
die("dbus_message_new_method_call failed");
DBusMessage *reply = dbus_connection_send_with_reply_and_block(conn, msg, 5000, &err);
dbus_message_unref(msg);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "StartDiscovery error: %s\n", err.message);
dbus_error_free(&err);
return;
}
if (reply)
dbus_message_unref(reply);
fprintf(stdout, "[ble_wake] discovery started\n");
}
int main(void) {
DBusError err;
dbus_error_init(&err);
DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (!conn) {
fprintf(stderr, "dbus_bus_get: %s\n", err.message);
return 1;
}
// 订阅 PropertiesChanged
const char *rule = "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'";
dbus_bus_add_match(conn, rule, &err);
dbus_connection_flush(conn);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "add_match error: %s\n", err.message);
dbus_error_free(&err);
return 1;
}
start_discovery(conn);
while (1) {
dbus_connection_read_write(conn, 1000);
DBusMessage *msg = dbus_connection_pop_message(conn);
if (!msg)
continue;
if (dbus_message_is_signal(msg, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
process_properties_changed(msg);
}
dbus_message_unref(msg);
}
return 0;
}
8.3 唤醒动作脚本:wake_action.sh
#!/bin/bash
# /usr/local/bin/wake_action.sh
# 示例:命中后做一件可见的动作
# 真实产品:这里可以触发 systemd 进入目标服务,或写入一个状态文件。
logger -t ble_wake "WAKE command matched, do action"
echo 1 > /tmp/ble_wake_triggered
# 可选:唤醒后广播在线状态 30 秒
/usr/local/bin/camera_adv_online.sh &
9. Camera 醒来后广播 30 秒“在线状态”:可执行脚本
9.1 在线广播 payload 设计
把 CMD 改为 ONLINE(例如 0xB1),Target 填自己 ID:
- Company: 0x1234
- Product: 0x01
- Target: MY_ID
- CMD: 0xB1
- Token: 0x66
9.2 脚本:camera_adv_online.sh
#!/bin/bash
set -e
COMPANY_L=0x34
COMPANY_H=0x12
PRODUCT=0x01
MYID=${MYID:-0x02}
CMD=0xB1
TOKEN=0x66
# start adv
hcitool cmd 0x08 0x0036 \
0x00 0x13 0x00 0x90 0x01 0x00 0xc2 0x01 0x00 0x07 0x00 \
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x01 0x00 0x00
hcitool cmd 0x08 0x0037 \
0x00 0x03 0x01 \
0x02 0x01 0x06 \
0x07 0xFF $COMPANY_L $COMPANY_H $PRODUCT $MYID $CMD $TOKEN
hcitool cmd 0x08 0x0039 0x01 0x01 0x00 0x00 0x00 0x00
sleep 30
# stop adv
hcitool cmd 0x08 0x0039 0x00 0x01 0x00 0x00 0x00 0x00
echo "[camera_adv_online] done"
10. 让 Camera 进入低功耗并保持 BLE 作为唤醒源:系统配置要点(Rockchip)
这里要区分:
- 验证阶段:主机不进入最深睡眠,BlueZ 进程仍在跑。
- 产品阶段:主机进入 suspend-to-RAM,BLE Controller 继续低占空比扫描,并通过 wake GPIO/IRQ 唤醒。
10.1 检查蓝牙设备是否允许 wakeup
# 先找到蓝牙相关设备路径(示例)
find /sys/devices -name wakeup -path '*bluetooth*' -o -path '*hci0*' 2>/dev/null
# 典型可设置项:
cat /sys/class/bluetooth/hci0/device/power/wakeup 2>/dev/null || true
# 如果存在,尝试 enable
echo enabled > /sys/class/bluetooth/hci0/device/power/wakeup 2>/dev/null || true
注:不同内核/控制器路径可能不同,关键是找到对应设备的
power/wakeup。
10.2 进入 suspend 验证
# 写入 mem 让系统进入 suspend-to-RAM
echo mem > /sys/power/state
验证点:
- 平板发 WAKE 广播
- Camera 是否被唤醒(串口、日志、/tmp 文件变化、系统服务恢复)
10.3 推荐:systemd 管理扫描服务(开发阶段)
ble-wake.service
[Unit]
Description=BLE Wake Scanner
After=bluetooth.service
Wants=bluetooth.service
[Service]
Type=simple
ExecStart=/usr/local/bin/ble_wake_scanner
Restart=always
RestartSec=1
[Install]
WantedBy=multi-user.target
启用:
systemctl enable ble-wake.service
systemctl start ble-wake.service
journalctl -u ble-wake.service -f
11. 从“开发验证”走向“真正低功耗产品”:Controller 层过滤 + 唤醒中断
如果你要在 Camera 上做到更深的低功耗:
- 不希望用户态进程一直运行
- 不希望主机频繁被无关广播唤醒
那么建议:
-
把过滤下沉到 Controller 层
- 只对特定 Manufacturer Data 上报/触发
- 你已有的 vendor HCI(例如
0x3f 0x157这类)就是这种方向
-
命中后通过硬件链路唤醒 SoC
- Controller → Wake GPIO → PMIC/SoC Wake
-
加入防抖与冷却时间
- 命中一次后 30 秒内忽略
- 或连续命中 N 次才触发
11.1 防误唤醒的最低配策略
- 固定协议字段(Company/Product/CMD/Target)
- RSSI 阈值
- Token(可升级为 rolling code)
- 触发后 cooldown(例如 30 秒)
12. “4 Camera + 1 平板”落地步骤(一步一步,按最短路径验证)
Step 1:统一协议
- Company:0x1234(示例)
- Product:0x01(Camera)
- CMD:WAKE=0xA5
- Target:0xFF(全部)或 0x01~0x04(指定)
为每台 Camera 配置唯一 ID:
- Camera A:0x01
- Camera B:0x02
- Camera C:0x03
- Camera D:0x04
Step 2:在每台 Camera 部署 scanner
- 编译
ble_wake_scanner.c→/usr/local/bin/ble_wake_scanner - 写
wake_action.sh(先写 /tmp 文件验证) - systemd 启动
Step 3:平板发送 WAKE 广播验证
- 运行
tablet_adv_wake.sh 0xFF - Camera 应该全部命中并执行动作
Step 4:验证定向唤醒
tablet_adv_wake.sh 0x02仅唤醒 Camera #2
Step 5:加入 RSSI 阈值/冷却
- 调整
RSSI_THRESHOLD - 在触发后增加 30 秒忽略窗口
Step 6:进入 suspend 测试
- Camera:
echo mem > /sys/power/state - 平板发 WAKE
- 观察 Camera 是否 resume
如果此步不稳定:说明系统的 wakeup source 或控制器侧配置还未打通,需要回到第 10/11 节做电源路径调试。
13. 常见问题与排查
13.1 我能 scan 到设备,但 payload 看不到
- 使用
btmon查看 HCI 报告 - bluetoothctl 默认不展示完整 manufacturer data
13.2 扫描命中但系统不唤醒
- 检查
/sys/.../power/wakeup是否 enabled - 检查 suspend 模式是否为 s2ram
- 检查控制器是否在 suspend 期间仍供电
- 产品级:走 GPIO/IRQ 唤醒链路
13.3 谁都能唤醒的问题
- 不要用 name/MAC
- 必须用 manufacturer data 的固定字段
- 加 token + RSSI + cooldown
13.4 hcitool 不存在
- 新版系统可能移除 hcitool(bluez- deprecated)
- 验证阶段可安装
bluez5-tools - 产品化建议写专用 HCI 程序或使用 mgmt/DBus API
14. 核心知识点总结(你应该真正记住的 10 条)
- Advertise 是发,Scan 是收;RSSI 永远由 Scan 端测量。
- 低功耗唤醒不需要连接,连接只会增加复杂度与功耗。
- 产品识别不要靠 name/MAC,要靠 Manufacturer Specific Data(0xFF)。
- 广播协议字段要固定长度,便于硬件/控制器层过滤。
- 唤醒是“判定 + 触发”,不是“收到就醒”。
- RSSI 阈值可显著降低误唤醒概率。
- Token/rolling code/cooldown 是防误触与抗攻击的基础。
- Rockchip 上要验证 wakeup source 路径:
power/wakeup+ suspend/resume。 - 开发阶段可用 BlueZ D-Bus 解析;产品阶段建议下沉到 controller + GPIO。
- 4 Camera + 平板的最简单先跑通:Target=ALL → 再做 Target=ID。
15. 你可以直接复用的最小文件清单
-
Camera:
/usr/local/bin/ble_wake_scanner/usr/local/bin/wake_action.sh/usr/local/bin/camera_adv_online.sh/etc/systemd/system/ble-wake.service
-
平板:
tablet_adv_wake.sh
16. 结尾:一个“最短成功路径”的建议
工程落地时,优先顺序建议:
- 先在不进入最深睡眠的情况下跑通协议与过滤(btmon 看到 payload、scanner 命中)。
- 再把系统推进到 suspend-to-RAM,打通 wakeup source。
- 最后将过滤下沉到 Controller 层(vendor HCI),实现真正低功耗与高鲁棒。
视频教程请关注 B 站:“嵌入式 Jerry”
📺 B站视频讲解(Bilibili):https://www.bilibili.com/video/BV1k1C9BYEAB/
📘 《Yocto项目实战教程》京东购买链接:Yocto项目实战教程
621

被折叠的 条评论
为什么被折叠?



