精简 usr_app 架构:去掉关机/休眠死代码,按键复用 key.c 状态机,ISR 重活统一延后到任务上下文
Type-C 长供电、上电即工作、无软关机,删除 app_boot/app_power 及 DP0 开关相关逻辑, 去掉空占位 app_fan_run 和无效的 usr_timer_pick_mode/rearm(数码管 4ms 扫描已 priority=1, 系统本来就不会进低功耗)。按键 5s 配对 / 12s OTA 改走 key.c 长按分级,去掉自计时与 1~5s 死区。 新增 app_defer,NVM/配对/OTA 只在 ISR 置位、在 500ms 任务上下文落地,避免再在 usr_timer 里写 flash。 规格书与注释同步精简。
This commit is contained in:
+4
-8
@@ -796,10 +796,6 @@
|
|||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
<Unit filename="apps/usr_periph/bsp_aht20.h" />
|
<Unit filename="apps/usr_periph/bsp_aht20.h" />
|
||||||
<Unit filename="apps/usr_app/app_boot.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_app/app_boot.h" />
|
|
||||||
<Unit filename="apps/usr_app/app_cond.c">
|
<Unit filename="apps/usr_app/app_cond.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
@@ -832,14 +828,14 @@
|
|||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
<Unit filename="apps/usr_app/app_nvm.h" />
|
<Unit filename="apps/usr_app/app_nvm.h" />
|
||||||
|
<Unit filename="apps/usr_app/app_defer.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="apps/usr_app/app_defer.h" />
|
||||||
<Unit filename="apps/usr_app/app_pair.c">
|
<Unit filename="apps/usr_app/app_pair.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
<Unit filename="apps/usr_app/app_pair.h" />
|
<Unit filename="apps/usr_app/app_pair.h" />
|
||||||
<Unit filename="apps/usr_app/app_power.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_app/app_power.h" />
|
|
||||||
<Unit filename="apps/usr_app/app_th.c">
|
<Unit filename="apps/usr_app/app_th.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
|||||||
+90
-57
@@ -7,12 +7,18 @@
|
|||||||
| 工程 | `温湿度风扇_soc_JieLi-JL7016` |
|
| 工程 | `温湿度风扇_soc_JieLi-JL7016` |
|
||||||
| 产品码 | ProdtCode=`CBR3`,productCode=`PRCBR3` |
|
| 产品码 | ProdtCode=`CBR3`,productCode=`PRCBR3` |
|
||||||
| 协议 | 见宝 SOC 55AA,V1.0.0 |
|
| 协议 | 见宝 SOC 55AA,V1.0.0 |
|
||||||
| 文档版本 | V1.2.0 |
|
| 文档版本 | V2.2.0 |
|
||||||
| 日期 | 2026.08.31 |
|
| 日期 | 2026.08.31 |
|
||||||
| 作者 | cyWu |
|
| 作者 | cyWu |
|
||||||
| 读者 | WorkBuddy / 固件开发 |
|
| 读者 | WorkBuddy / 固件开发 |
|
||||||
| 参考工程 | `D:\Jianbao\Project\产品\宠物\门夹弹力绳\门夹弹力绳_soc_JieLi-JL7016` |
|
| 参考工程 | `D:\Jianbao\Project\产品\宠物\门夹弹力绳\门夹弹力绳_soc_JieLi-JL7016` |
|
||||||
|
|
||||||
|
> **V2.2.0 变更(2026-08-31):** 顺着 V2.1.0 删 `app_power` 的思路,继续清掉同一类"保留但无调用者"的死代码:删除 `app_function_soft_off()` / `app_function_is_power_on()` / `app_function_power_on_silent()`,`gDevData.power` 恒为 1、写死在 `app_function_init()`(不再需要 `s_func.app_power` 状态字段);`usr_on_key_short()` 里对应的"软关态唤醒"死分支一并删除。
|
||||||
|
>
|
||||||
|
> **V2.1.0 变更(2026-08-31):** 关机功能确认彻底不存在(关机=拔电),**整模块删除 `app_power.c/.h`**(原 request/finalize 深睡钩子已无任何触发源,纯累赘代码);`usr_jb_main.c`/`app_function.c`/`app_disp.c` 里所有 `app_power_poweroff_pending()` 判断一并清理。同时把配对/OTA/NVM 落盘的"ISR 打标志"统一收进新模块 `app_defer.c/.h`(见 16 章)。
|
||||||
|
>
|
||||||
|
> **V2.0.0 变更(2026-08-31):** **上电即自动开机**,删除 `app_boot`(原阻塞式 3s/5s/12s 开机判定整模块移除)。按键语义改为运行态按住分级:**短按切档;按住 5s 松手清绑定进配对;按住 12s 到点即进 OTA;取消长按 3s 软关机**(拔电即关)。详见 5.1/5.2/5.3。
|
||||||
|
>
|
||||||
> **V1.2.0 变更(2026-08-31):** 风扇档位占空比按用户拍板改为 **1档 50%(5000/10000)、2档 75%(7500/10000)**(原 35%/65%,第 5.3/7/17/18 章同步)。
|
> **V1.2.0 变更(2026-08-31):** 风扇档位占空比按用户拍板改为 **1档 50%(5000/10000)、2档 75%(7500/10000)**(原 35%/65%,第 5.3/7/17/18 章同步)。
|
||||||
>
|
>
|
||||||
> **V1.1.0 变更(2026-08-31):** IO 分离。CT1642 改走 **PG0(CLK)/PG1(DATA)**,AHT20 独占 **PC4(SCL)/PC5(SDA)**,两路物理隔离,**删除 `bsp_bus` 共线分时机制**(原 8.3 节整体替换为"IO 独立")。同时把 2.2 节显示协议修正为实测 **18bit 帧**。
|
> **V1.1.0 变更(2026-08-31):** IO 分离。CT1642 改走 **PG0(CLK)/PG1(DATA)**,AHT20 独占 **PC4(SCL)/PC5(SDA)**,两路物理隔离,**删除 `bsp_bus` 共线分时机制**(原 8.3 节整体替换为"IO 独立")。同时把 2.2 节显示协议修正为实测 **18bit 帧**。
|
||||||
@@ -25,9 +31,9 @@
|
|||||||
|
|
||||||
1. **先改协议再写业务。** Excel 里 `cond_config1~7` 已是 **7 字节**,当前工程 `jb_protocol.*` / `dp_definition.json` 仍是 6 字节。必须按 Excel 重新生成协议,禁止继续按 6 字节解析。
|
1. **先改协议再写业务。** Excel 里 `cond_config1~7` 已是 **7 字节**,当前工程 `jb_protocol.*` / `dp_definition.json` 仍是 6 字节。必须按 Excel 重新生成协议,禁止继续按 6 字节解析。
|
||||||
2. **不要把业务算法写进 `jb_product.c`。** 只把 DP 写入 `gDevData` 并转调 `app_*`。组合根是 `usr_jb_main.c`(照门夹)。
|
2. **不要把业务算法写进 `jb_product.c`。** 只把 DP 写入 `gDevData` 并转调 `app_*`。组合根是 `usr_jb_main.c`(照门夹)。
|
||||||
3. **不要抄门夹的电池 / USB 直通开机 / 低电拒绝开机。** 本机 USB 常电、无电池。插上电 **不会** 自动工作,必须长按 3s。
|
3. **不要抄门夹的电池 / 低电拒绝开机。** 本机 USB 常电、无电池。**上电即开机**(V2.0.0 起,不再长按 3s 才开机);拔电即关,无软关机深睡。
|
||||||
4. **不要把调试 UART 放在 PC5。** 调试 UART TX = **PG6**(`IO_PORTG_06`)。PC5 是 AHT20 SDA(独立使用)。
|
4. **不要把调试 UART 放在 PC5。** 调试 UART TX = **PG6**(`IO_PORTG_06`)。PC5 是 AHT20 SDA(独立使用)。
|
||||||
5. **DP0 `power` 预留,不当开关。** 真开关只有按键 3s 软开关机。运行中上报 `power=1`,写忽略。
|
5. **DP0 `power` 预留,不当开关。** 上电恒为开机态(`power=1`),运行中上报 `power=1`,写忽略;停机靠短按切到 0 档或拔电。
|
||||||
6. **CT1642 与 AHT20 已 IO 分离(V1.1.0)。** CT1642 走 PG0(CLK)/PG1(DATA),AHT20 走 PC4(SCL)/PC5(SDA),两路独立、无总线竞争,**不存在分时/总线锁**(见 8.3)。
|
6. **CT1642 与 AHT20 已 IO 分离(V1.1.0)。** CT1642 走 PG0(CLK)/PG1(DATA),AHT20 走 PC4(SCL)/PC5(SDA),两路独立、无总线竞争,**不存在分时/总线锁**(见 8.3)。
|
||||||
7. 每个模块必须能用 `board_pin.h` 的 `BOARD_xxx_ENABLE` **单独关掉** 仍能编过、能配网上报(关掉的模块返回空操作)。
|
7. 每个模块必须能用 `board_pin.h` 的 `BOARD_xxx_ENABLE` **单独关掉** 仍能编过、能配网上报(关掉的模块返回空操作)。
|
||||||
8. 日志全部 **英文**。中文只出现在注释和本文。
|
8. 日志全部 **英文**。中文只出现在注释和本文。
|
||||||
@@ -95,45 +101,48 @@ apps/earphone/app_main.c
|
|||||||
└─ usr_rtc_init()
|
└─ usr_rtc_init()
|
||||||
└─ usr_jb_init() ← 唯一组合根
|
└─ usr_jb_init() ← 唯一组合根
|
||||||
bsp_hw_init()
|
bsp_hw_init()
|
||||||
app_led_init() ← 必须在开机等待之前
|
app_led_init() ← 灯效事件表最先装载
|
||||||
app_boot_wait_key() ← 3s/5s/12s,失败则 soft poweroff 不返回
|
|
||||||
jbInit() + userInit()
|
jbInit() + userInit()
|
||||||
若 usr_goto_updata → OTA
|
(上电即开机:无按键等待,不再有 app_boot)
|
||||||
app_nvm_load() ← 恢复 VM
|
app_fan_init() / app_disp_init()
|
||||||
app_fan_init()
|
usr_timer_add(app_disp_scan, 4ms, priority=1) ← CT1642 扫描,常驻
|
||||||
app_disp_init()
|
app_th_init() / app_mode_init() / app_arbiter_init()
|
||||||
app_th_init()
|
app_cond_init() / app_timer_init()
|
||||||
app_mode_init()
|
app_nvm_init() + app_nvm_load() ← 恢复 VM
|
||||||
app_cond_init()
|
|
||||||
app_timer_init()
|
|
||||||
app_function_init()
|
app_function_init()
|
||||||
user_key_init() + lock_if_held
|
user_key_init() + lock_if_held
|
||||||
usr_timer_rearm(20ms)
|
usr_timer_add(usr_timer_tick, 20ms, priority=1) ← 常驻,永不重挂
|
||||||
```
|
```
|
||||||
|
|
||||||
**20ms 业务节拍**(`usr_timer_tick`,与门夹相同,禁止再开 1ms ISR):
|
**20ms 业务节拍**(`usr_timer_tick`,硬件定时器中断上下文,禁止再开 1ms ISR):
|
||||||
|
|
||||||
1. `jbTimerIrq()` × dt
|
1. `jbTimerIrq()` × dt
|
||||||
2. `user_key_scan` + `user_key_handle`
|
2. `user_key_scan` + `user_key_handle`
|
||||||
3. `app_th_poll`(内部 2s 才真正采;IO 分离后采集与显示互不干扰)
|
3. `app_th_poll`(内部 2s 才真正采;IO 分离后采集与显示互不干扰)
|
||||||
4. `app_cond_run` / `app_timer_run` / `app_mode_run`(仲裁见第 12 章)
|
4. `app_mode_run`(通风/强力状态机;条件/定时引擎在 500ms 任务上下文,见下)
|
||||||
5. `app_fan_run`
|
5. `app_disp_run`(闪烁、刷新)
|
||||||
6. `app_disp_run`(闪烁、刷新)
|
6. `app_function_poll`(同步 DP)
|
||||||
7. `app_led_run`
|
7. `app_nvm_tick`(变化检测 + 500ms 防抖计时,不写 flash)
|
||||||
8. `app_function_poll`(同步 DP)
|
8. `app_led_run`
|
||||||
9. 重装定时器(按键按住 / 风扇转 / 关机流程中 → 不可睡)
|
|
||||||
|
|
||||||
`usr_timer_loop()`(BLE 500ms)只做:`userHandle()` 填温湿度 DP + `jbProtocolHandle()`。
|
**priority 固定 1、只注册一次,不动态重挂**:本产品 Type-C 长供电,不需要低功耗;
|
||||||
|
且 `app_disp_scan` 本身就以 priority=1 常驻,系统本来就永远无法进入低功耗——
|
||||||
|
按业务状态动态切换 `usr_timer_tick` 自己的 priority 没有任何实际效果,已删除
|
||||||
|
(原 `usr_timer_pick_mode`/`usr_timer_rearm`,规格书 V2.3.0 起废弃)。
|
||||||
|
|
||||||
|
`usr_timer_loop()`(BLE 500ms 任务上下文):`userHandle()` 填温湿度 DP、
|
||||||
|
`jbProtocolHandle()`、`app_cond_run()`/`app_timer_run()`(条件/定时引擎,
|
||||||
|
仲裁见第 12 章)、`app_function_loop()`(VM 落盘 + 配对/OTA 落地)。
|
||||||
|
|
||||||
可直接复用门夹源码(拷贝后改引脚/事件表,不要改框架语义):
|
可直接复用门夹源码(拷贝后改引脚/事件表,不要改框架语义):
|
||||||
|
|
||||||
| 复用 | 路径 | 改什么 |
|
| 复用 | 路径 | 改什么 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 按键 FSM | `key.c` / `key.h` / `key_manager.c` | 短按切档、长按关机 |
|
| 按键 FSM | `key.c` / `key.h` / `key_manager.c` | 短按切档;**按住分级 5s 配对 / 12s OTA**(V2.0.0,无长按关机) |
|
||||||
| LED 事件库 | `led.c` / `led.h` / `led_manager.c` | 单灯 PC2,删红绿双通道 |
|
| LED 事件库 | `led.c` / `led.h` / `led_manager.c` | 单灯 PC2,删红绿双通道 |
|
||||||
| 开机判定 | `app_boot.c` | **删除 USB 直通、低电拒绝** |
|
| ~~开机判定~~ | ~~`app_boot.c`~~ | **V2.0.0 已整模块删除**(上电即开机,判定下沉到 key_manager) |
|
||||||
| 配对会话 | `app_pair.c` | 120s 超时,灯效改单灯 |
|
| 配对会话 | `app_pair.c` | 120s 超时,灯效改单灯 |
|
||||||
| 软关机 | `app_power.c` 精简 | 无电池、无充电;只保留 request/finalize |
|
| ~~软关机~~ | ~~`app_power.c`~~ | **V2.1.0 已整模块删除**:无电池、无充电,关机=拔电,无软件关机路径 |
|
||||||
| RTC | `usr_rtc.c` | 原样 |
|
| RTC | `usr_rtc.c` | 原样 |
|
||||||
| 协议骨架 | `usr_jb_proto` | 重生 7 字节条件 |
|
| 协议骨架 | `usr_jb_proto` | 重生 7 字节条件 |
|
||||||
|
|
||||||
@@ -170,38 +179,57 @@ P0 建议先 `MODE/COND/TIMER/NVM=0`,台上只验按键、灯、PWM、数码
|
|||||||
|
|
||||||
## 5. 电源与按键
|
## 5. 电源与按键
|
||||||
|
|
||||||
### 5.1 关机 / 开机
|
### 5.1 上电 / 断电(V2.0.0 改:上电即开机)
|
||||||
|
|
||||||
- 关机 = `power_set_soft_poweroff()`:风扇 PWM=0 并关 MCPWM,数码管锁存灭(全段灭),LED 灭,BLE 停。
|
- **插 USB / 冷启动直接进入工作态**,无需按键,无 3s 等待。上电流程:
|
||||||
- **插 USB / 冷启动不会自动进入工作态。** 必须按住 3s。
|
`bsp_hw_init()` → `app_led_init()` → `jbInit()/userInit()` → 各 `app_*_init()`
|
||||||
- DP0 不参与。不要用 APP 开关机。
|
(`app_function_init()` 里写死 `gDevData.power=1`)→ `app_nvm_load()` →
|
||||||
- 无电池逻辑。
|
`user_key_init()` + `user_key_lock_if_held()` → 起 20ms 业务节拍。
|
||||||
|
- **关机 = 拔电。** 已取消按键长按 3s 软关机(原 3s 与新的 5s/12s 时间轴直接冲突)。
|
||||||
|
`app_power.c` 的软关机能力(request/finalize + 关机前落盘)**V2.1.0 已整模块删除**
|
||||||
|
(无任何触发源,纯累赘代码);**V2.2.0** 进一步删除 `app_function_soft_off` /
|
||||||
|
`app_function_is_power_on` / `app_function_power_on_silent`(同样无调用者的
|
||||||
|
死代码,`power` 恒 1 不再需要状态字段)。
|
||||||
|
- 上电若键仍按着:`user_key_lock_if_held()` 只锁**短按**(防一上电就切档),
|
||||||
|
不锁长按分级 —— 所以"插电时就按住 5s"照样进配对。
|
||||||
|
- DP0 不参与开关机,运行中恒上报 `power=1`(写死,非每 tick 同步),写忽略。
|
||||||
|
- 无电池、无充电逻辑。
|
||||||
|
|
||||||
### 5.2 关机态按住(`app_boot.c`,用 `timer_get_ms()` 轮询,与运行态 FSM 分开)
|
### 5.2 按住分级(运行态,`key_manager.c` 直接复用 `key.c` 长按/连按/释放事件)
|
||||||
|
|
||||||
| 松开时已按住 | 行为 |
|
上电后**任意时刻**按住 PB1 都按同一套时序判定(不再有"关机态/开机态"两套):
|
||||||
|
|
||||||
|
| 按住时长 | 行为 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| < 3000 ms | 继续软关机 |
|
| < 5000 ms 松开 | 短按:切档(见 5.3) |
|
||||||
| ≥ 3000 且 < 5000 ms | 正常开机,加载 VM,恢复上次 mode/gear 并从周期起点开跑 |
|
| 满 5000 ms(仍按住) | **只**切配对提示灯(100ms 快闪),**不清绑定** |
|
||||||
| ≥ 5000 且 < 12000 ms | 开机 + `usr_clear_pair_info` + 进配对(换手机用这条) |
|
| 满 5s 后、12s 前松开 | 提交配对:`usr_goto_pair_mode()`(断连+清绑定+**重发绑定广播**)+ `app_pair_start()` 起 120s 会话(换手机用这条) |
|
||||||
| ≥ 12000 ms | 进 OTA(门夹 `usr_app_ota_init` 路径) |
|
| 满 12000 ms(仍按住,到点即触发) | 进 OTA(`usr_app_ota_init`),不等松手;同时撤销本次配对 |
|
||||||
|
|
||||||
|
设计理由:配对刻意不在 5s 到点提交 —— 用户可能想继续按到 12s 进 OTA,
|
||||||
|
提前清绑定会误伤已配对的手机。
|
||||||
|
|
||||||
|
⚠ **上下文约束**:这几个回调跑在 20ms 硬件定时器中断上下文,只准置标志 +
|
||||||
|
切灯效(纯 RAM)。清绑定(写 VM)与 `usr_app_ota_init`(BLE 广播切换)
|
||||||
|
一律延后到 `app_function_loop()`(500ms 任务上下文)执行 —— 违反会栈溢出软复位
|
||||||
|
(2026-08-31 事故定论)。因此配对/OTA 的实际生效有最多 500ms 延迟。
|
||||||
|
|
||||||
按住过程 LED 提示(单灯):
|
按住过程 LED 提示(单灯):
|
||||||
|
|
||||||
- ≥3s:常亮(将开机)
|
- ≥5s:100ms 闪(将配网,松手生效)
|
||||||
- ≥5s:100ms 闪(将配对)
|
- ≥12s:200ms 闪(已进入 OTA)
|
||||||
- ≥12s:200ms 闪(将 OTA)
|
|
||||||
|
|
||||||
开机后若键仍按着:`user_key_lock_if_held()`,直到松开才接受短按/长按。
|
|
||||||
|
|
||||||
### 5.3 开机态按键
|
### 5.3 开机态按键
|
||||||
|
|
||||||
| 事件 | 行为 |
|
| 事件 | 行为 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 短按 | 风扇档位循环:1(50%) → 2(75%) → 3(100%) → 0(关风扇) → 1 … **立刻退出通风/强力**,改为手动档。设备仍开机,数码管继续刷 |
|
| 短按(<1s 松开) | 风扇档位循环:1(50%) → 2(75%) → 3(100%) → 0(关风扇) → 1 … **立刻退出通风/强力**,改为手动档。设备仍开机,数码管继续刷 |
|
||||||
| 长按 3s | 请求软关机。VM **不清** |
|
| 按住 5s 后松开 | 清绑定 + 进配对(见 5.2) |
|
||||||
|
| 按住 12s | 进 OTA(见 5.2) |
|
||||||
|
| ~~长按 3s 软关机~~ | **V2.0.0 已取消**,拔电即关 |
|
||||||
|
|
||||||
配对进行中:长按关机可忽略(与门夹一致,避免配到一半睡死)。短按仍可切档。
|
OTA 进行中:忽略配对/短按之外的重复分级(`app_led_is_ota()` 为 1 时不再重入)。
|
||||||
|
配对进行中:短按仍可切档。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -211,6 +239,7 @@ P0 建议先 `MODE/COND/TIMER/NVM=0`,台上只验按键、灯、PWM、数码
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 软关机 / 未开机 | 灭 | — |
|
| 软关机 / 未开机 | 灭 | — |
|
||||||
| 正常开机 | 常亮 | 低 |
|
| 正常开机 | 常亮 | 低 |
|
||||||
|
| 按住满 5s(待配网,未松手) | 100ms 亮 / 100ms 灭 | 中 |
|
||||||
| 配对中 | 100ms 亮 / 100ms 灭,直到成功或 120s 失败 | 中 |
|
| 配对中 | 100ms 亮 / 100ms 灭,直到成功或 120s 失败 | 中 |
|
||||||
| 配对成功 | 常亮(可保持 3s 再回到常亮,允许直接常亮) | 中 |
|
| 配对成功 | 常亮(可保持 3s 再回到常亮,允许直接常亮) | 中 |
|
||||||
| 配对失败 | 200ms 闪 3s,然后常亮 | 中 |
|
| 配对失败 | 200ms 闪 3s,然后常亮 | 中 |
|
||||||
@@ -232,9 +261,10 @@ LED **不** 表示风扇档位,**不** 表示温湿度告警(告警走数码
|
|||||||
| 2 | 75% | 7500/10000(用户拍板 2026-08-31) |
|
| 2 | 75% | 7500/10000(用户拍板 2026-08-31) |
|
||||||
| 3 | 100% | 10000/10000 |
|
| 3 | 100% | 10000/10000 |
|
||||||
|
|
||||||
- 模块接口建议:`app_fan_init` / `app_fan_set_gear(uint8_t)` / `app_fan_get_gear` / `app_fan_run`。
|
- 模块接口:`app_fan_init` / `app_fan_set_gear(uint8_t)` / `app_fan_get_gear`。
|
||||||
- DP2 必须等于 **当前真实档位**(通风停 5 分钟那段报 0)。
|
- DP2 必须等于 **当前真实档位**(通风停 5 分钟那段报 0)。
|
||||||
- 换档无需软爬坡(P0 不做)。若 100% 上电冲击过大,允许后续加 200ms 爬升,不作为 P0 验收。
|
- 换档无需软爬坡(P0 不做,也不做占位接口)。若 100% 上电冲击过大,后续要加
|
||||||
|
200ms 爬升时再新增 `app_fan_run` 接口即可,不作为 P0 验收。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -441,11 +471,11 @@ usr_rtc_get_time() 失败 → 全部定时不执行(等同 time_en=0)
|
|||||||
- 条件作废标志、模式已运行秒数、AHT20 原始采样
|
- 条件作废标志、模式已运行秒数、AHT20 原始采样
|
||||||
- BLE 三元组(走现有 `CFG_USER_PAIR_INFO`,出厂重置 **不清**)
|
- BLE 三元组(走现有 `CFG_USER_PAIR_INFO`,出厂重置 **不清**)
|
||||||
|
|
||||||
开机 3s 成功后:加载上述字段,**按上次 mode/gear 从周期起点继续工作**。
|
上电(V2.0.0 起无需按键)后:加载上述字段,**按上次 mode/gear 从周期起点继续工作**。
|
||||||
|
|
||||||
首次上电(VM 无效):mode=0,gear=0,条件/定时全 0,`cond_en=time_en=0`。
|
首次上电(VM 无效):mode=0,gear=0,条件/定时全 0,`cond_en=time_en=0`。
|
||||||
|
|
||||||
写 VM 时机:APP 改配置后、单次定时自毁使能时、软关机前、档位/模式稳定变化时(可做 500ms 防抖,避免短按循环打爆 Flash)。
|
写 VM 时机:APP 改配置后、单次定时自毁使能时、档位/模式稳定变化时(可做 500ms 防抖,避免短按循环打爆 Flash)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -454,7 +484,7 @@ usr_rtc_get_time() 失败 → 全部定时不执行(等同 time_en=0)
|
|||||||
- **清全部业务 VM**(第 13 章列表)。
|
- **清全部业务 VM**(第 13 章列表)。
|
||||||
- **保留 BLE 配对,不断开、不软复位。**
|
- **保留 BLE 配对,不断开、不软复位。**
|
||||||
- RAM 中 mode=0,gear=0,风扇停,条件/定时停止。
|
- RAM 中 mode=0,gear=0,风扇停,条件/定时停止。
|
||||||
- 换机:用户关机后 **长按 5s** 清配对进绑定广播。
|
- 换机:运行中 **按住 5s 后松手** 清配对进绑定广播(见 5.2,无需关机)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -478,7 +508,7 @@ usr_rtc_get_time() 失败 → 全部定时不执行(等同 time_en=0)
|
|||||||
| 25 factory_reset | 第 14 章 |
|
| 25 factory_reset | 第 14 章 |
|
||||||
| 26~28 | 存 RAM/VM 可不实现动作 |
|
| 26~28 | 存 RAM/VM 可不实现动作 |
|
||||||
|
|
||||||
OTA:12s 开机走门夹 `usr_app_ota_init`。`jbOnOtaNotify` 等协议 OTA **P2 可继续 stub**,注释写明未实现,禁止假装升级成功后擦用户区。
|
OTA:运行态按住 12s 走门夹 `usr_app_ota_init`(在 `app_function_loop` 任务上下文调用,灯效 200ms 闪)。`jbOnOtaNotify` 等协议 OTA **P2 可继续 stub**,注释写明未实现,禁止假装升级成功后擦用户区。
|
||||||
|
|
||||||
配对超时 120s,失败保持开机。
|
配对超时 120s,失败保持开机。
|
||||||
|
|
||||||
@@ -495,11 +525,10 @@ apps/usr_periph/
|
|||||||
usr_rtc.c/.h # 已有则保留
|
usr_rtc.c/.h # 已有则保留
|
||||||
|
|
||||||
apps/usr_app/
|
apps/usr_app/
|
||||||
key.c/.h, key_manager.c/.h # 拷贝门夹
|
key.c/.h, key_manager.c/.h # 拷贝门夹;短按切档 + 按住 5s/12s 分级
|
||||||
led.c/.h, led_manager.c/.h # 改单灯
|
led.c/.h, led_manager.c/.h # 改单灯
|
||||||
app_boot.c/.h # 拷贝后删 USB/电池
|
app_led.c/.h # 含长按 5s "将配网"提示灯
|
||||||
app_led.c/.h
|
app_defer.c/.h # ISR→任务上下文延后执行标志位(NVM/配对/OTA 统一收口)
|
||||||
app_power.c/.h # 精简
|
|
||||||
app_pair.c/.h
|
app_pair.c/.h
|
||||||
app_fan.c/.h
|
app_fan.c/.h
|
||||||
app_disp.c/.h # 数值、闪烁、--
|
app_disp.c/.h # 数值、闪烁、--
|
||||||
@@ -523,13 +552,17 @@ apps/usr_app/
|
|||||||
**目标:** 两路 IO(CT1642 显示 / AHT20 采集)、PWM、按键、灯可独立开关验证。
|
**目标:** 两路 IO(CT1642 显示 / AHT20 采集)、PWM、按键、灯可独立开关验证。
|
||||||
|
|
||||||
- [ ] `board_pin.h` + UART TX=PG6,打印正常,且不影响 PC5
|
- [ ] `board_pin.h` + UART TX=PG6,打印正常,且不影响 PC5
|
||||||
- [ ] 关机态 3s 开机、<3s 仍睡;开机态 3s 关机
|
- [ ] 插电即开机(不按键,直接进工作态、数码管亮、LED 常亮)
|
||||||
- [ ] 短按四态循环,示波器/听感确认 50/75/100/0%
|
- [ ] 长按 3s **不再**关机(已取消软关机按键入口)
|
||||||
|
- [ ] 短按(<5s 松手)四态循环,示波器/听感确认 50/75/100/0%
|
||||||
|
- [ ] 按住满 5s → 100ms 快闪;此时松手 → 清绑定进配对(APP 可搜到)
|
||||||
|
- [ ] 按住满 5s 不松手继续到 12s → 不进配对,直接进 OTA(200ms 闪)
|
||||||
- [ ] LED 开机常亮、模拟配对闪、模拟 OTA 闪(可用宏强制)
|
- [ ] LED 开机常亮、模拟配对闪、模拟 OTA 闪(可用宏强制)
|
||||||
- [ ] CT1642 两管能稳定显示写死的 `25` 和 `60`,无鬼影
|
- [ ] CT1642 两管能稳定显示写死的 `25` 和 `60`,无鬼影
|
||||||
- [ ] AHT20 串口打印 ℃/%,CRC 正确;采数时数码管不闪、不乱码(IO 独立,无需锁存)
|
- [ ] AHT20 串口打印 ℃/%,CRC 正确;采数时数码管不闪、不乱码(IO 独立,无需锁存)
|
||||||
- [ ] `BOARD_TH_ENABLE=0` 时显示仍可刷;`BOARD_DISP_ENABLE=0` 时传感器仍可打印
|
- [ ] `BOARD_TH_ENABLE=0` 时显示仍可刷;`BOARD_DISP_ENABLE=0` 时传感器仍可打印
|
||||||
- [ ] 12s 能进 OTA 广播(可先只打日志 + LED)
|
- [ ] 12s 能进 OTA 广播(可先只打日志 + LED)
|
||||||
|
- [ ] 长按进配对/OTA 后不复位(验证动作确实走的任务上下文)
|
||||||
|
|
||||||
**P0 关闭:** `BOARD_MODE/COND/TIMER/NVM_ENABLE=0`
|
**P0 关闭:** `BOARD_MODE/COND/TIMER/NVM_ENABLE=0`
|
||||||
|
|
||||||
@@ -539,7 +572,7 @@ apps/usr_app/
|
|||||||
- [ ] 通风 25/5、强力 15min 后停;短按立即退模式
|
- [ ] 通风 25/5、强力 15min 后停;短按立即退模式
|
||||||
- [ ] 超限闪(可用调试宏灌假温度)、失败 `--`
|
- [ ] 超限闪(可用调试宏灌假温度)、失败 `--`
|
||||||
- [ ] DP0 写 0 风扇不变、设备不关
|
- [ ] DP0 写 0 风扇不变、设备不关
|
||||||
- [ ] VM:改档/改模式/写下条件定时后断电,3s 开机从周期头恢复 mode
|
- [ ] VM:改档/改模式/写下条件定时后断电,重新上电从周期头恢复 mode
|
||||||
- [ ] 定时引擎可只存不跑(`BOARD_TIMER_ENABLE=0` 仍能保存 DP)
|
- [ ] 定时引擎可只存不跑(`BOARD_TIMER_ENABLE=0` 仍能保存 DP)
|
||||||
|
|
||||||
### P2 — 自动化
|
### P2 — 自动化
|
||||||
|
|||||||
@@ -394,9 +394,7 @@ c_SRC_FILES := \
|
|||||||
apps/usr_app/key.c \
|
apps/usr_app/key.c \
|
||||||
apps/usr_app/key_manager.c \
|
apps/usr_app/key_manager.c \
|
||||||
apps/usr_app/app_mode.c \
|
apps/usr_app/app_mode.c \
|
||||||
apps/usr_app/app_power.c \
|
|
||||||
apps/usr_app/app_pair.c \
|
apps/usr_app/app_pair.c \
|
||||||
apps/usr_app/app_boot.c \
|
|
||||||
apps/usr_app/app_function.c \
|
apps/usr_app/app_function.c \
|
||||||
cpu/br28/adc_api.c \
|
cpu/br28/adc_api.c \
|
||||||
cpu/br28/app_audio.c \
|
cpu/br28/app_audio.c \
|
||||||
@@ -454,7 +452,8 @@ c_SRC_FILES := \
|
|||||||
apps/usr_app/app_cond.c \
|
apps/usr_app/app_cond.c \
|
||||||
apps/usr_app/app_timer_task.c \
|
apps/usr_app/app_timer_task.c \
|
||||||
apps/usr_app/app_arbiter.c \
|
apps/usr_app/app_arbiter.c \
|
||||||
apps/usr_app/app_nvm.c
|
apps/usr_app/app_nvm.c \
|
||||||
|
apps/usr_app/app_defer.c
|
||||||
S_SRC_FILES := \
|
S_SRC_FILES := \
|
||||||
apps/earphone/sdk_version.z.S \
|
apps/earphone/sdk_version.z.S \
|
||||||
|
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ void app_main()
|
|||||||
usr_var.usr_power_charge_flag=2;
|
usr_var.usr_power_charge_flag=2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 配对只由 app_boot 长按 5s 置 usr_goto_pair;禁止上电清三元组(规格书 5.2 / 14 章) */
|
/* 配对只由运行态长按 5s(key_manager 分级)置 usr_goto_pair;禁止上电清三元组(规格书 5.2 / 14 章) */
|
||||||
|
|
||||||
ui_manage_init();
|
ui_manage_init();
|
||||||
ui_update_status(STATUS_POWERON);
|
ui_update_status(STATUS_POWERON);
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 模式仲裁器实现(规格书第 12 章:手动 > 定时 > 条件)
|
* @brief CBR3 模式仲裁器实现(规格书第 12 章:手动 > 定时 > 条件)
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.31
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(P2)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.31, cyWu, 首次发布(P2)
|
|
||||||
*
|
*
|
||||||
* @note 本模块是唯一模式占用源,运行在 usr_timer_loop(任务上下文)。
|
* @note 本模块是唯一模式占用源,运行在 usr_timer_loop(任务上下文)。
|
||||||
* 规则落地(规格书 12 章):
|
* 规则落地(规格书 12 章):
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 模式仲裁器(规格书第 12 章):手动 > 定时 > 条件
|
* @brief CBR3 模式仲裁器(规格书第 12 章):手动 > 定时 > 条件
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.31
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(P2)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.31, cyWu, 首次发布(P2)
|
|
||||||
*
|
*
|
||||||
* @note 把"谁在驱动模式"收成一处,避免 mode/cond/timer 互调成环。
|
* @note 把"谁在驱动模式"收成一处,避免 mode/cond/timer 互调成环。
|
||||||
* 唯一状态源是 owner(NONE/COND/TIMER)+ 条件快照;
|
* 唯一状态源是 owner(NONE/COND/TIMER)+ 条件快照;
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* @file app_boot.c
|
|
||||||
* @brief CBR3 上电按键判定实现(3s 开机 / 5s 配对 / 12s OTA)
|
|
||||||
* @author cyWu <1917507415@qq.com>
|
|
||||||
* @date 2026.08.29
|
|
||||||
* @version V1.0.0
|
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹:删 USB 直通、删低电拒绝)
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "app_boot.h"
|
|
||||||
#include "app_pair.h"
|
|
||||||
#include "bsp_hw.h"
|
|
||||||
#include "board_pin.h"
|
|
||||||
#include "app_main.h"
|
|
||||||
#include "usr_le_api.h"
|
|
||||||
#include "led_manager.h"
|
|
||||||
#include "asm/power/power_api.h"
|
|
||||||
#include "asm/power/power_reset.h"
|
|
||||||
|
|
||||||
#define LOG_TAG_CONST APP
|
|
||||||
#define LOG_TAG "[APP_BOOT]"
|
|
||||||
#define LOG_INFO_ENABLE
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
extern void clr_wdt(void);
|
|
||||||
extern u32 timer_get_ms(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 忙等若干毫秒,并喂狗
|
|
||||||
* @param ms 等待时长
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
static void boot_delay_ms(uint32_t ms)
|
|
||||||
{
|
|
||||||
uint32_t t0 = timer_get_ms();
|
|
||||||
|
|
||||||
while ((timer_get_ms() - t0) < ms) {
|
|
||||||
clr_wdt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief BLE 起来前进深睡(业务定时器尚未启动),原地喂狗不返回
|
|
||||||
* @note power_set_soft_poweroff() 只是向 SDK 底层发起软关机请求(置个标志位),
|
|
||||||
* 不是同步断电——真正切电源是底层电源管理在之后某个时机才执行的。
|
|
||||||
* 此时 BLE 栈、业务定时器都还没起来,如果直接 return,代码会接着把
|
|
||||||
* usr_jb_init 剩下的初始化跑完,等于白判定。所以必须用 while(1) 卡住:
|
|
||||||
* 一边喂狗防止看门狗打断,一边等底层真正把电断掉。
|
|
||||||
* @return 无(不会返回)
|
|
||||||
*/
|
|
||||||
static void boot_sleep(void)
|
|
||||||
{
|
|
||||||
log_info("boot sleep\n");
|
|
||||||
bsp_hw_enter_sleep_io();
|
|
||||||
power_set_soft_poweroff();
|
|
||||||
while (1) {
|
|
||||||
clr_wdt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 等待并判定开机按键
|
|
||||||
* @note 配对(5s)不在到点时立即提交:继续按住观察是否会按到 12s 触发 OTA,
|
|
||||||
* 真正的配对提交放在松手那一刻做。按满 5s 灯先切到配对快闪提示。
|
|
||||||
* 3s 常亮 / 5s 快闪直接复用 led_manager 的 LED_EVENT_STANDBY /
|
|
||||||
* LED_EVENT_PAIRING 事件。LED 事件库由调用方(usr_jb_init)在本函数
|
|
||||||
* 之前完成初始化,这里直接假定可用。
|
|
||||||
* @return 无(深睡分支不返回)
|
|
||||||
*/
|
|
||||||
void app_boot_wait_key(void)
|
|
||||||
{
|
|
||||||
uint32_t t0;
|
|
||||||
uint32_t elapsed;
|
|
||||||
uint8_t pair_armed = 0;
|
|
||||||
|
|
||||||
usr_var.usr_goto_pair = 0;
|
|
||||||
|
|
||||||
/* ⚠ 无 USB 直通:插电/冷启动一律走按键判定(规格书 5.1)。 */
|
|
||||||
|
|
||||||
if (!bsp_key_is_pressed()) {
|
|
||||||
log_info("boot no key, sleep\n");
|
|
||||||
boot_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
t0 = timer_get_ms();
|
|
||||||
log_info("boot key hold, wait 3s on / 5s pair / 12s ota\n");
|
|
||||||
|
|
||||||
while (bsp_key_is_pressed()) {
|
|
||||||
elapsed = timer_get_ms() - t0;
|
|
||||||
clr_wdt();
|
|
||||||
|
|
||||||
/* 12s 优先于配对:按满 12s 直接进 OTA,不再等松手 */
|
|
||||||
if (elapsed >= BOARD_KEY_OTA_MS) {
|
|
||||||
log_info("boot hold %ums, power on + ota\n", (unsigned)elapsed);
|
|
||||||
usr_app_ota_init();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 5s 只武装配对并切到快闪,真正提交放到松手那一刻 */
|
|
||||||
if (!pair_armed && (elapsed >= BOARD_KEY_PAIR_MS)) {
|
|
||||||
pair_armed = 1;
|
|
||||||
LED_EventDelete(LED_EVENT_STANDBY);
|
|
||||||
LED_EventAdd(LED_EVENT_PAIRING);
|
|
||||||
log_info("boot hold %ums, pair hint blink (release now for pair, "
|
|
||||||
"keep holding to %ums for ota)\n",
|
|
||||||
(unsigned)elapsed, (unsigned)BOARD_KEY_OTA_MS);
|
|
||||||
} else if (!pair_armed && !LED_IsEventExist(LED_EVENT_STANDBY)
|
|
||||||
&& (elapsed >= BOARD_KEY_POWER_MS)) {
|
|
||||||
LED_EventAdd(LED_EVENT_STANDBY);
|
|
||||||
log_info("boot hold 3s, will power on\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
user_led_handle(); /* 按事件表当前状态刷新一次灯 */
|
|
||||||
}
|
|
||||||
|
|
||||||
elapsed = timer_get_ms() - t0;
|
|
||||||
if (elapsed < BOARD_KEY_POWER_MS) {
|
|
||||||
log_info("boot hold %ums < 3s, sleep\n", (unsigned)elapsed);
|
|
||||||
boot_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 松手时已过 5s(且没按到 12s):提交配对;否则只是正常开机 */
|
|
||||||
if (pair_armed) {
|
|
||||||
usr_var.usr_goto_pair = 1;
|
|
||||||
usr_clear_pair_info_noreset();
|
|
||||||
app_pair_start();
|
|
||||||
log_info("boot hold %ums, power on + pair\n", (unsigned)elapsed);
|
|
||||||
} else {
|
|
||||||
log_info("boot hold %ums, power on\n", (unsigned)elapsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* @file app_boot.h
|
|
||||||
* @brief CBR3 上电按键判定:3s 开机,5s 配对,12s OTA,不足 3s 松手再睡
|
|
||||||
* @author cyWu <1917507415@qq.com>
|
|
||||||
* @date 2026.08.29
|
|
||||||
* @version V1.0.0
|
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹:删 USB 直通开机、删低电拒绝开机)
|
|
||||||
*
|
|
||||||
* @note 必须在 BLE 协议栈起来、业务定时器启动之前调用。杰理 jiffies 此时
|
|
||||||
* 往往 10ms 才跳一次,所以内部一律用 timer_get_ms 直接量时间。
|
|
||||||
* ⚠ 本产品 USB 常电、无电池:插电/冷启动【不会】自动进入工作态,
|
|
||||||
* 必须按住 3s(规格书 5.1/5.2)。门夹的 USB 直通开机逻辑禁止移植。
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __APP_BOOT_H__
|
|
||||||
#define __APP_BOOT_H__
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 等待并判定开机按键:不足 3s 松手、或全程未按键,直接原地深睡(不返回);
|
|
||||||
* 满 3s 视为正常开机;按满 5s 绿灯改快闪提示"松手即配网",真正清绑定 /
|
|
||||||
* 开绑定广播仍等松手(内部调用 app_pair_start);持续按满 12s 直接开机
|
|
||||||
* 并进入 OTA(调用 usr_app_ota_init)。
|
|
||||||
* @return 无(深睡分支通过 while(1) 喂狗不返回;其余情况正常返回)
|
|
||||||
*/
|
|
||||||
void app_boot_wait_key(void);
|
|
||||||
|
|
||||||
#endif /* __APP_BOOT_H__ */
|
|
||||||
@@ -2,14 +2,10 @@
|
|||||||
* @file app_cond.c
|
* @file app_cond.c
|
||||||
* @brief CBR3 条件引擎(P2):7 组 7 字节条件,比较成立满时长触发模式
|
* @brief CBR3 条件引擎(P2):7 组 7 字节条件,比较成立满时长触发模式
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V2.0.0
|
* @version V2.0.0,完整条件引擎(规格书第 10 章):7 字节解析/AND 比较/时长
|
||||||
* @history
|
* 累计(采样成功才累计)/触发/保持/条件强力循环/后覆盖不回栈/手动
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 stub)
|
* 作废(RAM)/快照恢复/闪烁喂真值
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1:set_en/set_config 存 VM(引擎仍关)
|
|
||||||
* - V2.0.0, 2026.08.31, cyWu, P2 实现完整条件引擎(规格书第 10 章):
|
|
||||||
* 7 字节解析/AND 比较/时长累计(采样成功才累计)/触发/保持/
|
|
||||||
* 条件强力循环/后覆盖不回栈/手动作废(RAM)/快照恢复/闪烁喂真值
|
|
||||||
*
|
*
|
||||||
* @note 运行上下文:app_cond_run 由 usr_timer_loop(500ms,任务上下文)调用
|
* @note 运行上下文:app_cond_run 由 usr_timer_loop(500ms,任务上下文)调用
|
||||||
* (规格书 8.4 时长按采样周期 2s 计,500ms 粒度足够;且触发时可能
|
* (规格书 8.4 时长按采样周期 2s 计,500ms 粒度足够;且触发时可能
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 条件引擎(P2):7 组 7 字节条件,比较成立满时长触发模式
|
* @brief CBR3 条件引擎(P2):7 组 7 字节条件,比较成立满时长触发模式
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(P0 仅接口与 stub)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 仅接口与 stub)
|
|
||||||
*
|
*
|
||||||
* @note P2 实现(BOARD_COND_ENABLE=1)。字节布局见规格书 10.2:
|
* @note P2 实现(BOARD_COND_ENABLE=1)。字节布局见规格书 10.2:
|
||||||
* Byte0=使能 Byte1-2=温度阈值(int16 大端 ×10) Byte3=湿度阈值
|
* Byte0=使能 Byte1-2=温度阈值(int16 大端 ×10) Byte3=湿度阈值
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file app_defer.c
|
||||||
|
* @brief ISR→任务上下文的延后执行标志位实现
|
||||||
|
* @author cyWu <1917507415@qq.com>
|
||||||
|
* @date 2026.08.31
|
||||||
|
* @version V1.0.0,首次发布
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "system/includes.h"
|
||||||
|
#include "app_defer.h"
|
||||||
|
|
||||||
|
/** 位掩码,volatile:request() 在中断上下文写,take()/is_pending()/cancel()
|
||||||
|
* 在任务上下文读写,两侧都用 local_irq_disable/enable 包一下读改写,
|
||||||
|
* 避免"任务侧正在清 A 位时中断侧设 B 位"这种读改写竞态把 B 位冲丢。 */
|
||||||
|
static volatile uint8_t s_flags;
|
||||||
|
|
||||||
|
void app_defer_request(AppDeferBit_t bit)
|
||||||
|
{
|
||||||
|
if (bit >= APP_DEFER_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
local_irq_disable();
|
||||||
|
s_flags |= (uint8_t)(1u << bit);
|
||||||
|
local_irq_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t app_defer_take(AppDeferBit_t bit)
|
||||||
|
{
|
||||||
|
uint8_t was_set;
|
||||||
|
|
||||||
|
if (bit >= APP_DEFER_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
local_irq_disable();
|
||||||
|
was_set = (s_flags & (uint8_t)(1u << bit)) ? 1 : 0;
|
||||||
|
s_flags &= (uint8_t)~(1u << bit);
|
||||||
|
local_irq_enable();
|
||||||
|
return was_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t app_defer_is_pending(AppDeferBit_t bit)
|
||||||
|
{
|
||||||
|
if (bit >= APP_DEFER_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (s_flags & (uint8_t)(1u << bit)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_defer_cancel(AppDeferBit_t bit)
|
||||||
|
{
|
||||||
|
if (bit >= APP_DEFER_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
local_irq_disable();
|
||||||
|
s_flags &= (uint8_t)~(1u << bit);
|
||||||
|
local_irq_enable();
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file app_defer.h
|
||||||
|
* @brief ISR→任务上下文的延后执行标志位(统一收口 2026-08-31 复位事故教训)
|
||||||
|
* @author cyWu <1917507415@qq.com>
|
||||||
|
* @date 2026.08.31
|
||||||
|
* @version V1.0.0,首次发布
|
||||||
|
*
|
||||||
|
* @note ⚠ 硬约束:flash 擦写(syscfg_write)、BLE 广播切换、关机收口等"重活"
|
||||||
|
* 禁止在 usr_timer_add 的中断上下文回调(本产品 20ms usr_timer_tick /
|
||||||
|
* 按键长按回调)里直接执行,只能在 usr_timer_loop(BLE 线程,任务
|
||||||
|
* 上下文,栈充足)里执行。之前每个模块各自发明一个 pending 标志
|
||||||
|
* (off_pending/pair_pending/ota_pending/nvm 的 s_need_save),
|
||||||
|
* 容易被后来的功能遗漏这条红线——本模块把"打标志"这一步收成统一
|
||||||
|
* 接口:ISR 只准调 app_defer_request(),真正执行永远在
|
||||||
|
* app_function_loop() 里用 app_defer_take() 消费。
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __APP_DEFER_H__
|
||||||
|
#define __APP_DEFER_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/** 延后动作位,新增一种"需要写flash/切广播/关机"的动作就加一项 */
|
||||||
|
typedef enum {
|
||||||
|
APP_DEFER_NVM_SAVE = 0, /**< VM 防抖到点,需要落盘 */
|
||||||
|
APP_DEFER_PAIR, /**< 长按 5s 松手,需要清绑定进配对 */
|
||||||
|
APP_DEFER_OTA, /**< 长按 12s 到点,需要进 OTA */
|
||||||
|
APP_DEFER_MAX
|
||||||
|
} AppDeferBit_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 中断上下文调用:只置位,不做任何实际动作
|
||||||
|
* @param bit 要延后的动作
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void app_defer_request(AppDeferBit_t bit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 任务上下文调用:查询并清除标志(取出即消费,最多处理一次)
|
||||||
|
* @param bit 要消费的动作
|
||||||
|
* @return 1=之前挂起过(现在可以执行真正动作),0=没挂起
|
||||||
|
*/
|
||||||
|
uint8_t app_defer_take(AppDeferBit_t bit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 任务上下文调用:只查询是否挂起,不清除(多个动作互斥判断用)
|
||||||
|
* @param bit 要查询的动作
|
||||||
|
* @return 1=挂起中,0=未挂起
|
||||||
|
*/
|
||||||
|
uint8_t app_defer_is_pending(AppDeferBit_t bit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 任务上下文调用:撤销挂起(如 OTA 触发时要撤销配对)
|
||||||
|
* @param bit 要撤销的动作
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void app_defer_cancel(AppDeferBit_t bit);
|
||||||
|
|
||||||
|
#endif /* __APP_DEFER_H__ */
|
||||||
+4
-16
@@ -2,14 +2,10 @@
|
|||||||
* @file app_disp.c
|
* @file app_disp.c
|
||||||
* @brief CBR3 数码管显示实现
|
* @brief CBR3 数码管显示实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.1.0
|
* @version V1.1.0,动态扫描(20ms 算段码写缓冲 + BOARD_DISP_SCAN_MS 快节拍
|
||||||
* @history
|
* 轮询点亮 1 位)+ 告警闪烁(温度/湿度管独立 500ms 亮灭,
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
* BOARD_DISP_ALARM_TEST 宏可强制模拟超限;fault 时 "--" 优先)
|
||||||
* - V1.0.1, 2026.08.29, cyWu, 改动态扫描:20ms 节拍只算数据写缓冲,
|
|
||||||
* 另起 BOARD_DISP_SCAN_MS 快节拍定时器轮询点亮 1 位,解决闪烁
|
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1 加告警闪烁:温度/湿度管独立 500ms 亮灭,
|
|
||||||
* BOARD_DISP_ALARM_TEST 宏可强制模拟超限;fault 时 "--" 优先
|
|
||||||
*
|
*
|
||||||
* @note ⚠ CT1642 内部只有单个 12 位锁存器(4 位选 + 8 段码),无按位显示 RAM、
|
* @note ⚠ CT1642 内部只有单个 12 位锁存器(4 位选 + 8 段码),无按位显示 RAM、
|
||||||
* 不自动扫描,一次只点亮当前锁存的那 1 位。要让 4 位都亮且不闪,必须由 MCU
|
* 不自动扫描,一次只点亮当前锁存的那 1 位。要让 4 位都亮且不闪,必须由 MCU
|
||||||
@@ -22,7 +18,6 @@
|
|||||||
|
|
||||||
#include "app_disp.h"
|
#include "app_disp.h"
|
||||||
#include "app_th.h"
|
#include "app_th.h"
|
||||||
#include "app_power.h"
|
|
||||||
#include "bsp_ct1642.h"
|
#include "bsp_ct1642.h"
|
||||||
#include "board_pin.h"
|
#include "board_pin.h"
|
||||||
|
|
||||||
@@ -212,7 +207,6 @@ void app_disp_run(uint16_t dt)
|
|||||||
* @note 必须短、不可阻塞。每次只发 1 帧,靠高频轮询让 4 位视觉同亮不闪。
|
* @note 必须短、不可阻塞。每次只发 1 帧,靠高频轮询让 4 位视觉同亮不闪。
|
||||||
* IO 分离后 CT1642 独占 PG0/PG1,与 AHT20 的 PC4/PC5 无总线竞争,
|
* IO 分离后 CT1642 独占 PG0/PG1,与 AHT20 的 PC4/PC5 无总线竞争,
|
||||||
* 扫描回调无需锁、无跳过。
|
* 扫描回调无需锁、无跳过。
|
||||||
* 软关机流程:4 位全灭(com=0x00 → 所有 Cx 高,位选全关)。
|
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_disp_scan(void)
|
void app_disp_scan(void)
|
||||||
@@ -224,12 +218,6 @@ void app_disp_scan(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 软关机流程:数码管锁存灭(规格书 5.1:风扇 0、数码管锁存灭、LED 灭) */
|
|
||||||
if (app_power_poweroff_pending()) {
|
|
||||||
bsp_ct1642_send_frame(0x00, 0x00); /* com=0x00 → 4 位全灭 */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BOARD_DISP_SCAN_TEST == 1
|
#if BOARD_DISP_SCAN_TEST == 1
|
||||||
/* 段扫描:4 位同显一段。⭐ 值变化才刷(无鬼影),com=0xF 四位全选同显。 */
|
/* 段扫描:4 位同显一段。⭐ 值变化才刷(无鬼影),com=0xF 四位全选同显。 */
|
||||||
static uint8_t seg = 0;
|
static uint8_t seg = 0;
|
||||||
|
|||||||
@@ -2,13 +2,10 @@
|
|||||||
* @file app_disp.h
|
* @file app_disp.h
|
||||||
* @brief CBR3 数码管显示:温度/湿度整数、负号、-- 故障、告警闪烁
|
* @brief CBR3 数码管显示:温度/湿度整数、负号、-- 故障、告警闪烁
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.1.0
|
* @version V1.1.0,加告警闪烁:温度/湿度管独立 500ms 亮灭,由
|
||||||
* @history
|
* app_disp_set_temp/humi_alarm 驱动(P2 条件引擎喂真值,也可用
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
* BOARD_DISP_ALARM_TEST 宏强制验证)
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1 加告警闪烁:温度/湿度管独立 500ms 亮灭,
|
|
||||||
* 由 app_disp_set_temp/humi_alarm 驱动(P2 条件引擎喂真值,
|
|
||||||
* P1 可用 BOARD_DISP_ALARM_TEST 宏强制验证)
|
|
||||||
*
|
*
|
||||||
* @note 两块 2 位 7 段数码管:温度管整数 ℃、湿度管整数 %。DP 恒灭。
|
* @note 两块 2 位 7 段数码管:温度管整数 ℃、湿度管整数 %。DP 恒灭。
|
||||||
* 0~99 显示绝对值;<0 显示 -9~-1(G 段负号);<-9 钳位 -9;>99 钳位 99。
|
* 0~99 显示绝对值;<0 显示 -9~-1(G 段负号);<-9 钳位 -9;>99 钳位 99。
|
||||||
|
|||||||
+2
-14
@@ -2,10 +2,8 @@
|
|||||||
* @file app_fan.c
|
* @file app_fan.c
|
||||||
* @brief CBR3 风扇档位实现
|
* @brief CBR3 风扇档位实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V1.1.0,删除 app_fan_run(P0 无动作的空占位,从未真正做过软爬坡)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "app_fan.h"
|
#include "app_fan.h"
|
||||||
@@ -70,13 +68,3 @@ uint8_t app_fan_get_gear(void)
|
|||||||
{
|
{
|
||||||
return s_gear;
|
return s_gear;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 业务节拍(P0 无动作,保留接口供 P1 爬坡)
|
|
||||||
* @param dt 距上次调用的毫秒数
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_fan_run(uint16_t dt)
|
|
||||||
{
|
|
||||||
(void)dt;
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-11
@@ -2,10 +2,8 @@
|
|||||||
* @file app_fan.h
|
* @file app_fan.h
|
||||||
* @brief CBR3 风扇档位:0/1/2/3 → 0%/50%/75%/100%
|
* @brief CBR3 风扇档位:0/1/2/3 → 0%/50%/75%/100%
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V1.1.0,删除 app_fan_run(从未真正做过软爬坡的空占位)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __APP_FAN_H__
|
#ifndef __APP_FAN_H__
|
||||||
@@ -32,11 +30,4 @@ void app_fan_set_gear(uint8_t gear);
|
|||||||
*/
|
*/
|
||||||
uint8_t app_fan_get_gear(void);
|
uint8_t app_fan_get_gear(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 业务节拍(P0 无动作,保留接口供 P1 爬坡)
|
|
||||||
* @param dt 距上次调用的毫秒数
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_fan_run(uint16_t dt);
|
|
||||||
|
|
||||||
#endif /* __APP_FAN_H__ */
|
#endif /* __APP_FAN_H__ */
|
||||||
|
|||||||
+70
-93
@@ -2,31 +2,30 @@
|
|||||||
* @file app_function.c
|
* @file app_function.c
|
||||||
* @brief CBR3 功能总装实现
|
* @brief CBR3 功能总装实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.1.0
|
* @version V2.2.0,上电即开机:短按切档;长按分级满 5s 提示→松手提交配对、
|
||||||
* @history
|
* 满 12s 到点进 OTA;配对/OTA 的实质动作(清绑定写 VM、
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
* usr_app_ota_init)统一放 app_function_loop(任务上下文)执行,
|
||||||
* - V1.1.0, 2026.08.31, cyWu, 长按关机改为延后到任务上下文执行:按键在
|
* 中断层只置标志;DP0 power 恒为开机态(规格书 0 章第 5 条:预留
|
||||||
* usr_timer 20ms(硬件定时器中断上下文)里处理,直接调
|
* 不当开关),已删除 soft_off/is_power_on 等围绕"可关机"的死代码
|
||||||
* app_power_request_poweroff 会在中断里跑 VM 落盘(栈溢出复位);
|
|
||||||
* 现改为置 off_pending,由 app_function_loop(usr_timer_loop,
|
|
||||||
* BLE 线程)先落盘再关机
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "system/includes.h" /* 必须先于 app_main.h:u8/u16/u32 等类型由 SDK 定义 */
|
||||||
#include "app_function.h"
|
#include "app_function.h"
|
||||||
#include "app_power.h"
|
|
||||||
#include "app_pair.h"
|
#include "app_pair.h"
|
||||||
#include "app_mode.h"
|
#include "app_mode.h"
|
||||||
#include "app_fan.h"
|
#include "app_fan.h"
|
||||||
#include "app_nvm.h"
|
#include "app_nvm.h"
|
||||||
|
#include "app_defer.h"
|
||||||
#include "app_arbiter.h"
|
#include "app_arbiter.h"
|
||||||
#include "app_cond.h"
|
#include "app_cond.h"
|
||||||
#include "app_timer_task.h"
|
#include "app_timer_task.h"
|
||||||
#include "app_th.h"
|
#include "app_th.h"
|
||||||
#include "app_disp.h"
|
#include "app_disp.h"
|
||||||
#include "app_led.h"
|
#include "app_led.h"
|
||||||
|
#include "app_main.h"
|
||||||
|
#include "usr_le_api.h"
|
||||||
#include "jb_product.h"
|
#include "jb_product.h"
|
||||||
#include "system/includes.h"
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define LOG_TAG_CONST APP
|
#define LOG_TAG_CONST APP
|
||||||
@@ -34,49 +33,54 @@
|
|||||||
#define LOG_INFO_ENABLE
|
#define LOG_INFO_ENABLE
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
/** 功能模块状态 */
|
|
||||||
typedef struct {
|
|
||||||
uint8_t app_power; /**< DP0:1=开机态(本产品无 APP 软关) */
|
|
||||||
uint8_t off_pending; /**< 1=长按已触发关机,等任务上下文落盘后再关机 */
|
|
||||||
} AppFunctionCtx_t;
|
|
||||||
|
|
||||||
static AppFunctionCtx_t s_func;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化功能模块状态
|
* @brief 初始化功能模块状态
|
||||||
|
* @note DP0 power 恒为开机态:规格书 0 章第 5 条"预留,不当开关",
|
||||||
|
* 协议层 DP0 写入本就忽略(jb_product.c),本产品无软关机,
|
||||||
|
* 这里写死一次即可,不需要额外状态字段
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_function_init(void)
|
void app_function_init(void)
|
||||||
{
|
{
|
||||||
s_func.app_power = 0;
|
gDevData.power = 1;
|
||||||
s_func.off_pending = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 任务上下文周期处理(由 usr_timer_loop 500ms 调用)
|
* @brief 任务上下文周期处理(由 usr_timer_loop 500ms 调用)
|
||||||
* @note ⚠ 本函数是唯一允许做 VM 落盘与关机收口的地方:usr_timer_loop 跑在
|
* @note ⚠ 本函数是唯一允许做 VM 落盘、清绑定、OTA 启动的地方:
|
||||||
* BLE 线程(sys_timer 同步接口,任务上下文,栈充足)。20ms 的
|
* usr_timer_loop 跑在 BLE 线程(sys_timer 同步接口,任务上下文,栈充足)。
|
||||||
* usr_timer_tick 是硬件定时器中断上下文,禁止做这两件事。
|
* 20ms 的 usr_timer_tick 是硬件定时器中断上下文,做这些会栈溢出复位。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_function_loop(void)
|
void app_function_loop(void)
|
||||||
{
|
{
|
||||||
app_nvm_flush(); /* 防抖满后真正写 VM(syscfg_write 必须在任务上下文) */
|
app_nvm_flush(); /* 防抖满后真正写 VM(syscfg_write 必须在任务上下文) */
|
||||||
|
|
||||||
if (s_func.off_pending) {
|
/* OTA 优先于配对:按满 12s 说明用户不是想配网,放弃本次清绑定 */
|
||||||
s_func.off_pending = 0;
|
if (app_defer_take(APP_DEFER_OTA)) {
|
||||||
app_power_request_poweroff(); /* 落盘后再走关机流程 */
|
app_defer_cancel(APP_DEFER_PAIR);
|
||||||
|
usr_app_ota_init(); /* BLE 侧:置 usr_goto_updata + 1s 定时器切 OTA 广播 */
|
||||||
|
app_led_request_ota(); /* 200ms 闪,优先级最高 */
|
||||||
|
log_info("key hold 12s -> ota\n");
|
||||||
|
} else if (app_defer_take(APP_DEFER_PAIR)) {
|
||||||
|
/* ⚠ 真正发起配对广播:usr_goto_pair_mode 内部会断连+清绑定(写VM)+重发绑定广播
|
||||||
|
* 必须在任务上下文调用(写 VM)。仅置 usr_var.usr_goto_pair 标志无效——
|
||||||
|
* SDK adv 模块只消费 usr_goto_updata,不消费该标志,不会开广播。 */
|
||||||
|
usr_goto_pair_mode();
|
||||||
|
app_pair_start(); /* 起 120s 配对会话,灯交由 app_led_run 接管 */
|
||||||
|
app_led_clear_pair_hint();
|
||||||
|
log_info("key hold 5s -> pair\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 同步 DP(power 恒 1、fan_gear、mode、fault_code),每个业务 tick 调用
|
* @brief 同步 DP(fan_gear、mode、fault_code),每个业务 tick 调用
|
||||||
* @note DP3/DP4 温湿度在 userHandle(500ms)填;DP0 写忽略,运行中恒上报 1
|
* @note DP3/DP4 温湿度在 userHandle(500ms)填;DP0 power 不在这里同步,
|
||||||
|
* 恒为开机态,写死在 app_function_init
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_function_poll(void)
|
void app_function_poll(void)
|
||||||
{
|
{
|
||||||
gDevData.power = (s_func.app_power) ? 1 : 0;
|
|
||||||
gDevData.fan_gear = app_fan_get_gear(); /* DP2 必须等于当前真实档位 */
|
gDevData.fan_gear = app_fan_get_gear(); /* DP2 必须等于当前真实档位 */
|
||||||
gDevData.mode = app_mode_get_active();
|
gDevData.mode = app_mode_get_active();
|
||||||
/* 规格书 8.2/15:传感器故障优先 2;否则温湿度比较成立报 1 */
|
/* 规格书 8.2/15:传感器故障优先 2;否则温湿度比较成立报 1 */
|
||||||
@@ -89,47 +93,6 @@ void app_function_poll(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 停手动 + 模式,风扇关(关机请求 / 软关时用)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_function_stop_all(void)
|
|
||||||
{
|
|
||||||
app_mode_stop();
|
|
||||||
app_fan_set_gear(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 软关:风扇停、DP0=0(本产品 DP0 写忽略,软关仅按键 3s 触发)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_function_soft_off(void)
|
|
||||||
{
|
|
||||||
s_func.app_power = 0;
|
|
||||||
gDevData.power = 0;
|
|
||||||
app_function_stop_all();
|
|
||||||
log_info("soft off\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 上电默认开启功能(DP0=1),不带开机灯效提示
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_function_power_on_silent(void)
|
|
||||||
{
|
|
||||||
s_func.app_power = 1;
|
|
||||||
gDevData.power = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 查询功能开关状态(DP0)
|
|
||||||
* @return 1=开,0=关
|
|
||||||
*/
|
|
||||||
uint8_t app_function_is_power_on(void)
|
|
||||||
{
|
|
||||||
return s_func.app_power;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 短按:风扇档位循环 1→2→3→0→1…(规格书 5.3)
|
* @brief 短按:风扇档位循环 1→2→3→0→1…(规格书 5.3)
|
||||||
* @note 立刻退出通风/强力改为手动档:用 app_mode_stop() 只清模式、
|
* @note 立刻退出通风/强力改为手动档:用 app_mode_stop() 只清模式、
|
||||||
@@ -141,17 +104,6 @@ void usr_on_key_short(void)
|
|||||||
{
|
{
|
||||||
uint8_t g;
|
uint8_t g;
|
||||||
|
|
||||||
if (app_power_poweroff_pending()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!s_func.app_power) {
|
|
||||||
/* 软关态短按只唤醒,不切档(P0 无 APP 软关,保留分支) */
|
|
||||||
s_func.app_power = 1;
|
|
||||||
gDevData.power = 1;
|
|
||||||
app_led_hint_power_on();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_arbiter_manual_intervene(); /* 手动动作:释放条件/定时占用(12 章) */
|
app_arbiter_manual_intervene(); /* 手动动作:释放条件/定时占用(12 章) */
|
||||||
app_mode_stop(); /* 退模式(不动档位,下面立刻切循环下一档) */
|
app_mode_stop(); /* 退模式(不动档位,下面立刻切循环下一档) */
|
||||||
g = app_fan_get_gear(); /* 当前实际档:手动=手动档;模式中=模式强制档(1/3) */
|
g = app_fan_get_gear(); /* 当前实际档:手动=手动档;模式中=模式强制档(1/3) */
|
||||||
@@ -161,23 +113,48 @@ void usr_on_key_short(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 长按 3s:请求软关机(配对中忽略,避免配到一半睡死,规格书 5.3)
|
* @brief 按住满 5s:切配对提示灯,提示"松手即配网,继续按到 12s 进 OTA"
|
||||||
* @note ⚠ 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,禁止直接
|
* @note 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,只准动灯效事件
|
||||||
* 调 app_power_request_poweroff(其钩子会做 VM 落盘 → 栈溢出)。
|
* (纯 RAM)。清绑定写 VM 在 app_function_loop 做。
|
||||||
* 只置 off_pending,由 app_function_loop(任务上下文)落盘后关机。
|
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void usr_on_key_long(void)
|
void usr_on_key_pair_hint(void)
|
||||||
{
|
{
|
||||||
if (app_power_poweroff_pending()) {
|
if (app_led_is_ota()) {
|
||||||
|
return; /* OTA 灯效最高优先级,不打断 */
|
||||||
|
}
|
||||||
|
app_led_hint_pair();
|
||||||
|
log_info("key hold 5s, pair hint (release to pair, keep to 12s for ota)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 按满 5s 后松手:提交配对(只置标志)
|
||||||
|
* @note ⚠ 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,只置标志。
|
||||||
|
* 清绑定(usr_clear_pair_info_noreset 会写 VM)放到任务上下文。
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void usr_on_key_pair_start(void)
|
||||||
|
{
|
||||||
|
if (app_led_is_ota()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (app_pair_is_active()) {
|
app_defer_request(APP_DEFER_PAIR);
|
||||||
log_info("key hold 3s ignored, pairing\n");
|
log_info("key hold 5s released, pair pending\n");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
log_info("key hold 3s, poweroff pending (wait vm flush)\n");
|
|
||||||
s_func.off_pending = 1;
|
/**
|
||||||
|
* @brief 按住满 12s:进 OTA(只置标志,到点即触发不等松手)
|
||||||
|
* @note ⚠ 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,只置标志。
|
||||||
|
* usr_app_ota_init 涉及 BLE 广播切换,放到任务上下文。
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void usr_on_key_ota_start(void)
|
||||||
|
{
|
||||||
|
if (app_led_is_ota()) {
|
||||||
|
return; /* 已在 OTA,不重复发起 */
|
||||||
|
}
|
||||||
|
app_defer_request(APP_DEFER_OTA);
|
||||||
|
log_info("key hold 12s, ota pending\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+26
-34
@@ -1,11 +1,11 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* @file app_function.h
|
* @file app_function.h
|
||||||
* @brief CBR3 功能总装:按键动作(短按切档/长按关机)+ DP 同步
|
* @brief CBR3 功能总装:按键动作(短按切档 / 长按 5s 配对 / 长按 12s OTA)+ DP 同步
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V2.2.0,上电即开机:长按分级回调 usr_on_key_pair_hint/pair_start/
|
||||||
* @history
|
* ota_start;DP0 power 恒为开机态(无软关机),已删除
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹语义重写)
|
* app_function_soft_off/is_power_on 等死代码
|
||||||
*
|
*
|
||||||
* @note 本模块只做"按键 → 动作"和"状态 → DP",不写业务算法。
|
* @note 本模块只做"按键 → 动作"和"状态 → DP",不写业务算法。
|
||||||
* 档位/模式/条件的执行在各自 app_* 模块(规格书第 0 章第 2 条)。
|
* 档位/模式/条件的执行在各自 app_* 模块(规格书第 0 章第 2 条)。
|
||||||
@@ -23,44 +23,21 @@
|
|||||||
void app_function_init(void);
|
void app_function_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 同步 DP(power 恒 1、fan_gear、mode、fault_code),每个业务 tick 调用
|
* @brief 同步 DP(fan_gear、mode、fault_code),每个业务 tick 调用
|
||||||
|
* @note DP0 power 不在这里同步:恒为开机态,写死在 app_function_init
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_function_poll(void);
|
void app_function_poll(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 任务上下文周期处理(由 usr_timer_loop 500ms 调用)
|
* @brief 任务上下文周期处理(由 usr_timer_loop 500ms 调用)
|
||||||
* @note ⚠ VM 落盘(syscfg_write)与关机收口只允许在这里做:usr_timer_loop
|
* @note ⚠ VM 落盘(syscfg_write)与配对/OTA 落地只允许在这里做:usr_timer_loop
|
||||||
* 跑在 BLE 线程(任务上下文,栈充足);usr_timer_tick 是硬件定时器
|
* 跑在 BLE 线程(任务上下文,栈充足);usr_timer_tick 是硬件定时器
|
||||||
* 中断上下文,做这两件事会栈溢出复位。
|
* 中断上下文,做这些会栈溢出复位。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_function_loop(void);
|
void app_function_loop(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 停手动 + 模式,风扇关(关机请求 / 软关时用)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_function_stop_all(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 软关:风扇停、DP0=0(本产品 DP0 写忽略,软关仅按键 3s 触发)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_function_soft_off(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 上电默认开启功能(DP0=1),不带开机灯效提示
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_function_power_on_silent(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 查询功能开关状态(DP0)
|
|
||||||
* @return 1=开,0=关
|
|
||||||
*/
|
|
||||||
uint8_t app_function_is_power_on(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 业务层短按回调(key_manager 触发):档位 1→2→3→0→1…
|
* @brief 业务层短按回调(key_manager 触发):档位 1→2→3→0→1…
|
||||||
* @return 无
|
* @return 无
|
||||||
@@ -68,10 +45,25 @@ uint8_t app_function_is_power_on(void);
|
|||||||
void usr_on_key_short(void);
|
void usr_on_key_short(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 业务层长按 3s 回调(key_manager 触发):请求软关机
|
* @brief 业务层"按住满 5s"回调(key_manager 触发,20ms 中断上下文)
|
||||||
|
* @note 只切提示灯,不清绑定
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void usr_on_key_long(void);
|
void usr_on_key_pair_hint(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 业务层"按满 5s 后松手"回调(key_manager 触发,20ms 中断上下文)
|
||||||
|
* @note 只置标志:清绑定要写 VM,由 app_function_loop 在任务上下文执行
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void usr_on_key_pair_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 业务层"按住满 12s"回调(key_manager 触发,20ms 中断上下文)
|
||||||
|
* @note 只置标志:usr_app_ota_init 由 app_function_loop 在任务上下文执行
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void usr_on_key_ota_start(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 出厂重置:清业务 VM 与 RAM,保留 BLE 配对(规格书 14 章)
|
* @brief 出厂重置:清业务 VM 与 RAM,保留 BLE 配对(规格书 14 章)
|
||||||
|
|||||||
+30
-5
@@ -2,10 +2,9 @@
|
|||||||
* @file app_led.c
|
* @file app_led.c
|
||||||
* @brief CBR3 灯效适配:单灯 PC2,OTA/配对/常亮
|
* @brief CBR3 灯效适配:单灯 PC2,OTA/配对/常亮
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V1.1.0,新增 s_pair_hint:长按满 5s 到松手提交配对这段窗口内维持
|
||||||
* @history
|
* 配对快闪,避免被 app_led_run 叠上开机常亮
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹,删红绿双通道/充电/低电/空电)
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "app_led.h"
|
#include "app_led.h"
|
||||||
@@ -16,6 +15,7 @@
|
|||||||
|
|
||||||
static uint8_t s_initialized;
|
static uint8_t s_initialized;
|
||||||
static uint8_t s_ota; /* 1=OTA 灯效中,app_led_run 不再叠其它灯 */
|
static uint8_t s_ota; /* 1=OTA 灯效中,app_led_run 不再叠其它灯 */
|
||||||
|
static uint8_t s_pair_hint; /* 1=长按已满 5s 但还没松手提交配对,维持配对快闪 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 重新播放一次「一次性/限时」灯效,让它从第 0 帧重新开始
|
* @brief 重新播放一次「一次性/限时」灯效,让它从第 0 帧重新开始
|
||||||
@@ -64,6 +64,30 @@ void app_led_hint_power_on(void)
|
|||||||
led_restart(LED_EVENT_STANDBY);
|
led_restart(LED_EVENT_STANDBY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 长按满 5s:挂配对快闪,提示"松手即配网,继续按到 12s 进 OTA"
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void app_led_hint_pair(void)
|
||||||
|
{
|
||||||
|
if (!s_initialized || s_ota) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s_pair_hint = 1;
|
||||||
|
LED_EventAllDelete();
|
||||||
|
bsp_led_set(0);
|
||||||
|
LED_EventAdd(LED_EVENT_PAIRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 结束"将配网"提示,交回 app_led_run 按 app_pair 状态接管
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void app_led_clear_pair_hint(void)
|
||||||
|
{
|
||||||
|
s_pair_hint = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 进入 OTA:清掉其它灯,挂 200ms 闪一直闪
|
* @brief 进入 OTA:清掉其它灯,挂 200ms 闪一直闪
|
||||||
* @return 无
|
* @return 无
|
||||||
@@ -74,6 +98,7 @@ void app_led_request_ota(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s_ota = 1;
|
s_ota = 1;
|
||||||
|
s_pair_hint = 0; /* 已改判 OTA,撤销配网提示 */
|
||||||
LED_EventAllDelete();
|
LED_EventAllDelete();
|
||||||
bsp_led_set(0);
|
bsp_led_set(0);
|
||||||
LED_EventAdd(LED_EVENT_OTA);
|
LED_EventAdd(LED_EVENT_OTA);
|
||||||
@@ -122,7 +147,7 @@ void app_led_run(uint16_t dt, uint8_t power_on)
|
|||||||
if (!power_on) {
|
if (!power_on) {
|
||||||
LED_EventDelete(LED_EVENT_STANDBY);
|
LED_EventDelete(LED_EVENT_STANDBY);
|
||||||
LED_EventDelete(LED_EVENT_PAIRING);
|
LED_EventDelete(LED_EVENT_PAIRING);
|
||||||
} else if (app_pair_is_active()) {
|
} else if (s_pair_hint || app_pair_is_active()) {
|
||||||
LED_EventAdd(LED_EVENT_PAIRING);
|
LED_EventAdd(LED_EVENT_PAIRING);
|
||||||
LED_EventDelete(LED_EVENT_STANDBY);
|
LED_EventDelete(LED_EVENT_STANDBY);
|
||||||
} else if (!LED_IsEventExist(LED_EVENT_PAIR_OK) && !LED_IsEventExist(LED_EVENT_PAIR_FAIL)) {
|
} else if (!LED_IsEventExist(LED_EVENT_PAIR_OK) && !LED_IsEventExist(LED_EVENT_PAIR_FAIL)) {
|
||||||
|
|||||||
+16
-4
@@ -2,10 +2,9 @@
|
|||||||
* @file app_led.h
|
* @file app_led.h
|
||||||
* @brief CBR3 灯效:单灯 PC2,OTA/配对/常亮按优先级
|
* @brief CBR3 灯效:单灯 PC2,OTA/配对/常亮按优先级
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V1.1.0,新增长按 5s 的"将配网"提示灯(配对改由运行态长按触发,
|
||||||
* @history
|
* 需要在按住期间给反馈)
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹,删红绿双通道/充电/低电)
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __APP_LED_H__
|
#ifndef __APP_LED_H__
|
||||||
@@ -38,6 +37,19 @@ void app_led_run(uint16_t dt, uint8_t power_on);
|
|||||||
*/
|
*/
|
||||||
void app_led_hint_power_on(void);
|
void app_led_hint_power_on(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 长按满 5s 的"松手即配网"提示:清掉其它灯,挂配对快闪
|
||||||
|
* @note 此时还没清绑定(要等松手),只是给按住的用户一个反馈
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void app_led_hint_pair(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 结束"将配网"提示(配对会话已由 app_pair 接管,或改判为 OTA)
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void app_led_clear_pair_hint(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 进入 OTA:清掉其它灯,挂 200ms 闪一直闪
|
* @brief 进入 OTA:清掉其它灯,挂 200ms 闪一直闪
|
||||||
* @return 无
|
* @return 无
|
||||||
|
|||||||
@@ -2,12 +2,9 @@
|
|||||||
* @file app_mode.c
|
* @file app_mode.c
|
||||||
* @brief CBR3 工作模式实现(P1):通风 25/5 循环、强力 15min 一轮
|
* @brief CBR3 工作模式实现(P1):通风 25/5 循环、强力 15min 一轮
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.1.0
|
* @version V1.1.0,实现状态机(规格书第 9 章):通风 25/5、强力 15min 后停、
|
||||||
* @history
|
* 手动档快照、退出语义、开机从周期头
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 stub)
|
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1 实现状态机(规格书第 9 章):
|
|
||||||
* 通风 25/5、强力 15min 后停、手动档快照、退出语义、开机从周期头
|
|
||||||
*
|
*
|
||||||
* @note 模式激活时强制覆盖风扇档位(通风=1 档、强力=3 档、通风停段=0),
|
* @note 模式激活时强制覆盖风扇档位(通风=1 档、强力=3 档、通风停段=0),
|
||||||
* DP2 由 app_fan_get_gear 上报真实档位(app_function_poll 同步)。
|
* DP2 由 app_fan_get_gear 上报真实档位(app_function_poll 同步)。
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 工作模式:通风(25/5 循环)/ 强力(15min 一轮)
|
* @brief CBR3 工作模式:通风(25/5 循环)/ 强力(15min 一轮)
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(P0 仅接口与 stub,P1 实现状态机)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 仅接口与 stub,P1 实现状态机)
|
|
||||||
*
|
*
|
||||||
* @note P1 语义(规格书第 9 章):mode=1 强制 1 档开 25min 停 5min 循环;
|
* @note P1 语义(规格书第 9 章):mode=1 强制 1 档开 25min 停 5min 循环;
|
||||||
* mode=2 强制 3 档跑 15min 后风扇 0、mode 回 0。短按切档走
|
* mode=2 强制 3 档跑 15min 后风扇 0、mode 回 0。短按切档走
|
||||||
|
|||||||
+12
-15
@@ -2,11 +2,8 @@
|
|||||||
* @file app_nvm.c
|
* @file app_nvm.c
|
||||||
* @brief CBR3 VM 持久化实现(P1):mode/fan_gear/条件/定时/使能
|
* @brief CBR3 VM 持久化实现(P1):mode/fan_gear/条件/定时/使能
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.1.0
|
* @version V1.1.0,实现:3 个 VM item + 防抖 + 立即写
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 stub)
|
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1 实现:3 个 VM item + 防抖 + 立即写
|
|
||||||
*
|
*
|
||||||
* @note VM item 分配在 syscfg 用户自定义区 [1~49](syscfg_id.h 已占用
|
* @note VM item 分配在 syscfg 用户自定义区 [1~49](syscfg_id.h 已占用
|
||||||
* CFG_USER_PAIR_INFO=2 / CFG_USER_TIM_FLAG=3 / VM_ALARM*=4~24 /
|
* CFG_USER_PAIR_INFO=2 / CFG_USER_TIM_FLAG=3 / VM_ALARM*=4~24 /
|
||||||
@@ -19,7 +16,7 @@
|
|||||||
* 减少 flash 磨损;首次上电(magic 不符)保持 gDevData 全 0 默认。
|
* 减少 flash 磨损;首次上电(magic 不符)保持 gDevData 全 0 默认。
|
||||||
*
|
*
|
||||||
* 写入时机(规格书第 13 章):APP 改配置后(mark_dirty)、档位/模式
|
* 写入时机(规格书第 13 章):APP 改配置后(mark_dirty)、档位/模式
|
||||||
* 稳定变化(500ms 防抖)、软关机前(save 立即写)。
|
* 稳定变化(500ms 防抖)。
|
||||||
*
|
*
|
||||||
* ⚠⚠ 上下文硬约束(2026-08-31 复位事故定论,勿再踩):
|
* ⚠⚠ 上下文硬约束(2026-08-31 复位事故定论,勿再踩):
|
||||||
* usr_timer_add() 是**异步接口**,回调在**硬件定时器中断上下文**执行
|
* usr_timer_add() 是**异步接口**,回调在**硬件定时器中断上下文**执行
|
||||||
@@ -29,14 +26,14 @@
|
|||||||
* 绝对不能调 syscfg_write**(VM 擦写 flash 栈用量大且中断里做
|
* 绝对不能调 syscfg_write**(VM 擦写 flash 栈用量大且中断里做
|
||||||
* flash 操作 → 栈溢出软复位;实测 APP 下发数据后 500ms 必崩)。
|
* flash 操作 → 栈溢出软复位;实测 APP 下发数据后 500ms 必崩)。
|
||||||
* - 真正写入由 app_nvm_flush() 在 usr_timer_loop()(BLE 线程、
|
* - 真正写入由 app_nvm_flush() 在 usr_timer_loop()(BLE 线程、
|
||||||
* 任务上下文、栈充足)执行;usr_poweroff_request_hook 里的
|
* 任务上下文、栈充足)执行。
|
||||||
* app_nvm_save() 也必须保证在任务上下文被调用(见 app_function_loop)。
|
|
||||||
* 另:nvm_write_item 的比较缓冲改 static,再省 128B 栈。
|
* 另:nvm_write_item 的比较缓冲改 static,再省 128B 栈。
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "app_nvm.h"
|
#include "app_nvm.h"
|
||||||
#include "app_mode.h"
|
#include "app_mode.h"
|
||||||
#include "app_fan.h"
|
#include "app_fan.h"
|
||||||
|
#include "app_defer.h"
|
||||||
#include "jb_product.h"
|
#include "jb_product.h"
|
||||||
#include "board_pin.h"
|
#include "board_pin.h"
|
||||||
#include "system/includes.h"
|
#include "system/includes.h"
|
||||||
@@ -81,8 +78,9 @@ typedef struct {
|
|||||||
|
|
||||||
#if BOARD_NVM_ENABLE
|
#if BOARD_NVM_ENABLE
|
||||||
static uint8_t s_dirty; /**< 1=防抖计时中 */
|
static uint8_t s_dirty; /**< 1=防抖计时中 */
|
||||||
static uint8_t s_need_save; /**< 1=防抖已满,待任务上下文落盘 */
|
|
||||||
static uint16_t s_deb_ms; /**< 防抖计时 */
|
static uint16_t s_deb_ms; /**< 防抖计时 */
|
||||||
|
/* 防抖已满时用 app_defer_request(APP_DEFER_NVM_SAVE) 打标志,真正落盘
|
||||||
|
* 由 app_nvm_flush() 在任务上下文里 app_defer_take() 消费,见文件头说明 */
|
||||||
|
|
||||||
/* 上次已同步到 VM 的状态快照:变化检测基准(覆盖按键/APP/模式引擎所有入口) */
|
/* 上次已同步到 VM 的状态快照:变化检测基准(覆盖按键/APP/模式引擎所有入口) */
|
||||||
static uint8_t s_last_gear;
|
static uint8_t s_last_gear;
|
||||||
@@ -222,7 +220,7 @@ void app_nvm_init(void)
|
|||||||
}
|
}
|
||||||
s_dirty = 0;
|
s_dirty = 0;
|
||||||
s_deb_ms = 0;
|
s_deb_ms = 0;
|
||||||
s_need_save = 0;
|
app_defer_cancel(APP_DEFER_NVM_SAVE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +252,7 @@ void app_nvm_save(void)
|
|||||||
nvm_write_time();
|
nvm_write_time();
|
||||||
s_dirty = 0;
|
s_dirty = 0;
|
||||||
s_deb_ms = 0;
|
s_deb_ms = 0;
|
||||||
s_need_save = 0;
|
app_defer_cancel(APP_DEFER_NVM_SAVE);
|
||||||
nvm_sync_snapshot();
|
nvm_sync_snapshot();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -358,7 +356,7 @@ void app_nvm_tick(uint16_t dt)
|
|||||||
if (s_deb_ms >= CBR3_VM_DEBOUNCE_MS) {
|
if (s_deb_ms >= CBR3_VM_DEBOUNCE_MS) {
|
||||||
s_deb_ms = 0;
|
s_deb_ms = 0;
|
||||||
s_dirty = 0;
|
s_dirty = 0;
|
||||||
s_need_save = 1; /* 只置标志:等任务上下文 app_nvm_flush 真正落盘 */
|
app_defer_request(APP_DEFER_NVM_SAVE); /* 只置标志:真正落盘在 app_nvm_flush */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -374,10 +372,9 @@ void app_nvm_flush(void)
|
|||||||
#if !BOARD_NVM_ENABLE
|
#if !BOARD_NVM_ENABLE
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
if (!s_need_save) {
|
if (!app_defer_take(APP_DEFER_NVM_SAVE)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s_need_save = 0;
|
|
||||||
app_nvm_save();
|
app_nvm_save();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -417,7 +414,7 @@ void app_nvm_reset(void)
|
|||||||
syscfg_write(CFG_USER_CBR3_TIME, &tf, sizeof(tf));
|
syscfg_write(CFG_USER_CBR3_TIME, &tf, sizeof(tf));
|
||||||
s_dirty = 0;
|
s_dirty = 0;
|
||||||
s_deb_ms = 0;
|
s_deb_ms = 0;
|
||||||
s_need_save = 0;
|
app_defer_cancel(APP_DEFER_NVM_SAVE);
|
||||||
log_info("nvm factory reset, business vm cleared (pairing kept)\n");
|
log_info("nvm factory reset, business vm cleared (pairing kept)\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-11
@@ -2,17 +2,13 @@
|
|||||||
* @file app_nvm.h
|
* @file app_nvm.h
|
||||||
* @brief CBR3 VM 持久化(P1 起):mode/fan_gear/条件/定时/使能
|
* @brief CBR3 VM 持久化(P1 起):mode/fan_gear/条件/定时/使能
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.1.0
|
* @version V1.1.0,实现:3 个 VM item(状态/条件/定时)+ 500ms 防抖写入 +
|
||||||
* @history
|
* 立即写接口
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 仅接口与 stub)
|
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1 实现:3 个 VM item(状态/条件/定时)+ 500ms
|
|
||||||
* 防抖写入 + 立即写接口
|
|
||||||
*
|
*
|
||||||
* @note 存:mode、fan_gear、cond_en、cond_config1~7、time_en、time_config1~7、
|
* @note 存:mode、fan_gear、cond_en、cond_config1~7、time_en、time_config1~7、
|
||||||
* fault_en、alarm_en。不存:DP0、条件作废标志、模式已运行秒数、原始采样。
|
* fault_en、alarm_en。不存:DP0、条件作废标志、模式已运行秒数、原始采样。
|
||||||
* 写 VM 时机:APP 改配置后、单次定时自毁、软关机前、档位/模式稳定变化
|
* 写 VM 时机:APP 改配置后、单次定时自毁、档位/模式稳定变化(500ms 防抖)。
|
||||||
* (500ms 防抖)。
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __APP_NVM_H__
|
#ifndef __APP_NVM_H__
|
||||||
@@ -27,9 +23,8 @@
|
|||||||
void app_nvm_init(void);
|
void app_nvm_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 立即保存全部业务字段到 VM(软关机前等关键时机调用)
|
* @brief 立即保存全部业务字段到 VM
|
||||||
* @note syscfg 写入不能在裸中断里调用;本函数由业务时基回调触发,
|
* @note syscfg 写入不能在裸中断里调用;只由 app_nvm_flush()(任务上下文)调用
|
||||||
* 与 SDK norflash 缓存同步(sys_timeout 回调)同级,可安全执行
|
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void app_nvm_save(void);
|
void app_nvm_save(void);
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief 配对会话计时实现
|
* @brief 配对会话计时实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.25
|
* @date 2026.08.25
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布,实现配对会话计时与成功/超时判定
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.25, cyWu, 首次发布,实现配对会话计时与成功/超时判定
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "app_pair.h"
|
#include "app_pair.h"
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief 配对会话计时:开机配对窗口是否成功/超时,与 BLE 配对本身解耦
|
* @brief 配对会话计时:开机配对窗口是否成功/超时,与 BLE 配对本身解耦
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.25
|
* @date 2026.08.25
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布,实现配对会话计时与成功/超时判定
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.25, cyWu, 首次发布,实现配对会话计时与成功/超时判定
|
|
||||||
*
|
*
|
||||||
* @note 真正的 BLE 广播/绑定逻辑在 usr_le_code;本模块只负责“进入配对后
|
* @note 真正的 BLE 广播/绑定逻辑在 usr_le_code;本模块只负责“进入配对后
|
||||||
* 120s 内 usr_get_pair_flag() 是否变 1”这件事,纯状态,不碰灯/按键。
|
* 120s 内 usr_get_pair_flag() 是否变 1”这件事,纯状态,不碰灯/按键。
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* @file app_power.c
|
|
||||||
* @brief CBR3 软关机生命周期实现:无电池、无充电
|
|
||||||
* @author cyWu <1917507415@qq.com>
|
|
||||||
* @date 2026.08.29
|
|
||||||
* @version V1.0.0
|
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹精简:删 USB/充电/电量/低电)
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "app_power.h"
|
|
||||||
#include "system/includes.h"
|
|
||||||
|
|
||||||
#define LOG_TAG_CONST APP
|
|
||||||
#define LOG_TAG "[APP_PWR]"
|
|
||||||
#define LOG_INFO_ENABLE
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
/** 电源模块总状态 */
|
|
||||||
typedef struct {
|
|
||||||
uint8_t req_poweroff;
|
|
||||||
AppPowerHook_t on_request;
|
|
||||||
AppPowerHook_t on_finalize;
|
|
||||||
} AppPowerCtx_t;
|
|
||||||
|
|
||||||
static AppPowerCtx_t s_power;
|
|
||||||
|
|
||||||
static void power_do_poweroff(void *priv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化电源模块状态
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_power_init(void)
|
|
||||||
{
|
|
||||||
s_power.req_poweroff = 0;
|
|
||||||
s_power.on_request = NULL;
|
|
||||||
s_power.on_finalize = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注册深睡请求的两段式回调
|
|
||||||
* @param on_request 刚请求深睡时调用(停风扇;灯由调用方按关机类型决定)
|
|
||||||
* @param on_finalize 延时到点后调用(真正进深睡,不会返回)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_power_set_hooks(AppPowerHook_t on_request, AppPowerHook_t on_finalize)
|
|
||||||
{
|
|
||||||
s_power.on_request = on_request;
|
|
||||||
s_power.on_finalize = on_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 请求深睡(按键 3s 等):立即触发 on_request 钩子,50ms 后触发 on_finalize
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_power_request_poweroff(void)
|
|
||||||
{
|
|
||||||
if (s_power.req_poweroff) {
|
|
||||||
return; /* 已经在关机流程里,不要重复挂定时器 */
|
|
||||||
}
|
|
||||||
s_power.req_poweroff = 1;
|
|
||||||
log_info("request deep off\n");
|
|
||||||
if (s_power.on_request) {
|
|
||||||
s_power.on_request(); /* 立刻停风扇、灯全灭 */
|
|
||||||
}
|
|
||||||
sys_timeout_add(NULL, power_do_poweroff, 50); /* 给 GPIO 落稳一点再真正掉电 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 查询深睡请求是否已发起
|
|
||||||
* @return 1=已发起,0=未发起
|
|
||||||
*/
|
|
||||||
uint8_t app_power_poweroff_pending(void)
|
|
||||||
{
|
|
||||||
return s_power.req_poweroff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 当前这次关机是否为空电路径(本产品无电池,恒 0)
|
|
||||||
* @return 0
|
|
||||||
*/
|
|
||||||
uint8_t app_power_empty_off_pending(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 50ms 延时到点:真正进入深睡
|
|
||||||
* @param priv 未使用
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
static void power_do_poweroff(void *priv)
|
|
||||||
{
|
|
||||||
(void)priv;
|
|
||||||
log_info("enter deep off\n");
|
|
||||||
if (s_power.on_finalize) {
|
|
||||||
s_power.on_finalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* @file app_power.h
|
|
||||||
* @brief CBR3 软关机生命周期:无电池、无充电,只保留 request/finalize
|
|
||||||
* @author cyWu <1917507415@qq.com>
|
|
||||||
* @date 2026.08.29
|
|
||||||
* @version V1.0.0
|
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹精简:删 USB/充电/电量/低电)
|
|
||||||
*
|
|
||||||
* @note 本产品 USB 常电、无电池,插电不会自动开机,必须长按 3s。
|
|
||||||
* SDK 层 TCFG_CHARGE 相关配置保留为板级模板默认,但业务层完全不
|
|
||||||
* 参与充电/电量逻辑(规格书第 0 章第 3 条)。
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __APP_POWER_H__
|
|
||||||
#define __APP_POWER_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/** 深睡请求的钩子:on_request 立刻停执行体并按关机类型处理灯;on_finalize 真正掉电 */
|
|
||||||
typedef void (*AppPowerHook_t)(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化电源模块状态
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_power_init(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注册深睡请求的两段式回调
|
|
||||||
* @param on_request 刚请求深睡时调用(停风扇;灯由调用方按关机类型决定)
|
|
||||||
* @param on_finalize 延时到点后调用(真正进深睡,不会返回)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_power_set_hooks(AppPowerHook_t on_request, AppPowerHook_t on_finalize);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 请求深睡(按键 3s 等):立即触发 on_request 钩子,50ms 后触发 on_finalize
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
void app_power_request_poweroff(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 查询深睡请求是否已发起(发起后其它模块应停止响应新操作)
|
|
||||||
* @return 1=已发起,0=未发起
|
|
||||||
*/
|
|
||||||
uint8_t app_power_poweroff_pending(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 当前这次关机是否为空电路径(本产品无电池,恒 0,保留接口)
|
|
||||||
* @return 0
|
|
||||||
*/
|
|
||||||
uint8_t app_power_empty_off_pending(void);
|
|
||||||
|
|
||||||
#endif /* __APP_POWER_H__ */
|
|
||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 温湿度采集实现
|
* @brief CBR3 温湿度采集实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "app_th.h"
|
#include "app_th.h"
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 温湿度采集:2s 周期、失败计数、最近有效值
|
* @brief CBR3 温湿度采集:2s 周期、失败计数、最近有效值
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
*
|
*
|
||||||
* @note 规格书 8.4:条件"持续时长"只在本次采样成功且比较成立时累加;
|
* @note 规格书 8.4:条件"持续时长"只在本次采样成功且比较成立时累加;
|
||||||
* 采样失败不累加、不清零;连续 3 次失败显示 "--" 且 fault_code=2。
|
* 采样失败不累加、不清零;连续 3 次失败显示 "--" 且 fault_code=2。
|
||||||
|
|||||||
@@ -2,14 +2,10 @@
|
|||||||
* @file app_timer_task.c
|
* @file app_timer_task.c
|
||||||
* @brief CBR3 定时引擎(P2):7 组 8 字节定时窗,RTC 门闩
|
* @brief CBR3 定时引擎(P2):7 组 8 字节定时窗,RTC 门闩
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V2.0.0
|
* @version V2.0.0,完整定时引擎(规格书第 11 章):RTC 门闩(未对时一律不
|
||||||
* @history
|
* 跑)/对时补窗/7 组窗判断(跨午夜、星期位图)/窗内切模式/结束收口
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 stub)
|
* (风扇 0 mode 0)/单次自毁清使能写 VM
|
||||||
* - V1.1.0, 2026.08.31, cyWu, P1:set_en/set_config 存 VM(引擎仍关)
|
|
||||||
* - V2.0.0, 2026.08.31, cyWu, P2 实现完整定时引擎(规格书第 11 章):
|
|
||||||
* RTC 门闩(未对时一律不跑)/对时补窗/7 组窗判断(跨午夜、星期位图)/
|
|
||||||
* 窗内切模式/结束收口(风扇 0 mode 0)/单次自毁清使能写 VM
|
|
||||||
*
|
*
|
||||||
* @note 运行上下文:app_timer_run 由 usr_timer_loop(500ms,任务上下文)
|
* @note 运行上下文:app_timer_run 由 usr_timer_loop(500ms,任务上下文)
|
||||||
* 调用——窗判断分钟级精度足够,且单次自毁要写 VM(禁止中断上下文)。
|
* 调用——窗判断分钟级精度足够,且单次自毁要写 VM(禁止中断上下文)。
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 定时引擎(P2):7 组 8 字节定时窗,RTC 门闩
|
* @brief CBR3 定时引擎(P2):7 组 8 字节定时窗,RTC 门闩
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(P0 仅接口与 stub)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 仅接口与 stub)
|
|
||||||
*
|
*
|
||||||
* @note 文件名避开 usr_rtc。字节布局见规格书 11.1:Byte0=使能 Byte1=模式
|
* @note 文件名避开 usr_rtc。字节布局见规格书 11.1:Byte0=使能 Byte1=模式
|
||||||
* Byte2=类型(0单次/1每天/2每周) Byte3=星期位图 Byte4-5=开始时/分
|
* Byte2=类型(0单次/1每天/2每周) Byte3=星期位图 Byte4-5=开始时/分
|
||||||
|
|||||||
+1
-3
@@ -3,9 +3,7 @@
|
|||||||
* @brief 按键状态机实现
|
* @brief 按键状态机实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.25
|
* @date 2026.08.25
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布,实现按键短按/长按/释放状态机
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.25, cyWu, 首次发布,实现按键短按/长按/释放状态机
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|||||||
+1
-3
@@ -3,9 +3,7 @@
|
|||||||
* @brief 按键状态机:短按 / 长按 / 释放
|
* @brief 按键状态机:短按 / 长按 / 释放
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.25
|
* @date 2026.08.25
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布,实现按键短按/长按/释放状态机
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.25, cyWu, 首次发布,实现按键短按/长按/释放状态机
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __KEY_H__
|
#ifndef __KEY_H__
|
||||||
|
|||||||
+50
-31
@@ -1,11 +1,9 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* @file key_manager.c
|
* @file key_manager.c
|
||||||
* @brief CBR3 按键:读 PB1,短按切档、长按 3s 关机交给 usr_jb_main
|
* @brief CBR3 按键:读 PB1,短按切档;按住分级 5s 配对 / 12s OTA
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V3.0.0,直接复用 key.c 原生长按/连按/释放事件做按住分级
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹,短按语义改切档)
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "system/includes.h"
|
#include "system/includes.h"
|
||||||
@@ -18,10 +16,11 @@
|
|||||||
#define LOG_INFO_ENABLE
|
#define LOG_INFO_ENABLE
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
/** 模块状态,替代原来 2 个散落的 static */
|
/** 模块状态 */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t initialized;
|
uint8_t initialized;
|
||||||
uint8_t boot_key_lock; /**< 1=开机判定时键还按着,等松开才认短按/长按 */
|
uint8_t boot_key_lock; /**< 1=上电时键还按着,等松开才认短按(不挡长按分级) */
|
||||||
|
uint8_t ota_fired; /**< 1=已到点触发 OTA,本次按住松手不再提交配对 */
|
||||||
} KeyManagerCtx_t;
|
} KeyManagerCtx_t;
|
||||||
|
|
||||||
static KeyManagerCtx_t s_km;
|
static KeyManagerCtx_t s_km;
|
||||||
@@ -36,25 +35,13 @@ static uint8_t key_user_read(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 松开:清掉开机按着键的锁
|
* @brief 短按(SHORT_Event,松手时刻 <5s):上电未松手前忽略,否则切档
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
static void key_user_release(void)
|
|
||||||
{
|
|
||||||
if (s_km.boot_key_lock) {
|
|
||||||
s_km.boot_key_lock = 0;
|
|
||||||
log_info("boot key released\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 短按:开机未松手前忽略
|
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
static void key_user_short(void)
|
static void key_user_short(void)
|
||||||
{
|
{
|
||||||
if (s_km.boot_key_lock) {
|
if (s_km.boot_key_lock) {
|
||||||
s_km.boot_key_lock = 0; /* 开机松手当成释放,不当短按切档 */
|
s_km.boot_key_lock = 0; /* 上电松手当成释放,不当短按切档 */
|
||||||
log_info("boot key released\n");
|
log_info("boot key released\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -62,15 +49,44 @@ static void key_user_short(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 长按 3s:开机未松手前忽略,避免开机手还按着就关机
|
* @brief 长按到点(LONG_Event,满 5s 仍按住):挂配对提示灯
|
||||||
|
* @note ⚠ 跑在 usr_timer 20ms(硬件定时器中断上下文):只准打标志 + 切灯效
|
||||||
|
* 事件(纯 RAM)。清绑定(写 VM)留给 app_function_loop(任务上下文)。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
static void key_user_long(void)
|
static void key_user_pair_hint(void)
|
||||||
{
|
{
|
||||||
if (s_km.boot_key_lock) {
|
usr_on_key_pair_hint();
|
||||||
return; /* 开机手还按着,忽略这次 3s 长按,避免一开机就关机 */
|
|
||||||
}
|
}
|
||||||
usr_on_key_long();
|
|
||||||
|
/**
|
||||||
|
* @brief 连按到点(LAST_Event,满 12s 仍按住,到点即触发不等松手):进 OTA
|
||||||
|
* @note ⚠ 同上,只置标志;usr_app_ota_init 由 app_function_loop 执行。
|
||||||
|
* key.c 的 keyHandle 对 LAST_Event 不清 eventType,松手前每 20ms 都会
|
||||||
|
* 再派发一次,这里用 ota_fired 挡住重复调用。
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
static void key_user_ota_start(void)
|
||||||
|
{
|
||||||
|
if (s_km.ota_fired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s_km.ota_fired = 1;
|
||||||
|
usr_on_key_ota_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 释放(RELEASE_Event,只有按满 ≥5s 才会触发):未进 OTA 则提交配对
|
||||||
|
* @note 按满 12s 已触发 OTA 的这次按住,松手不再提交配对(ota_fired 拦住)。
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
static void key_user_release(void)
|
||||||
|
{
|
||||||
|
s_km.boot_key_lock = 0;
|
||||||
|
if (!s_km.ota_fired) {
|
||||||
|
usr_on_key_pair_start();
|
||||||
|
}
|
||||||
|
s_km.ota_fired = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static keyCategory_t s_keys[USR_KEY_COUNT] = {
|
static keyCategory_t s_keys[USR_KEY_COUNT] = {
|
||||||
@@ -78,12 +94,13 @@ static keyCategory_t s_keys[USR_KEY_COUNT] = {
|
|||||||
.fsm.keyShield = KEY_ENABLE,
|
.fsm.keyShield = KEY_ENABLE,
|
||||||
.fsm.keyDownLevel = Bit_SET,
|
.fsm.keyDownLevel = Bit_SET,
|
||||||
.fsm.eventType = NULL_Event,
|
.fsm.eventType = NULL_Event,
|
||||||
.fsm.keyLongTime = BOARD_KEY_POWER_MS,
|
.fsm.keyLongTime = BOARD_KEY_PAIR_MS, /* 满 5s 仍按住 -> longPressCb */
|
||||||
.fsm.keyLastTime = (BOARD_KEY_POWER_MS + 7000), /* 大于长按即可,不使用持续按 */
|
.fsm.keyLastTime = BOARD_KEY_OTA_MS, /* 满 12s 仍按住 -> lastPressCb */
|
||||||
.fsm.keyReadValue = key_user_read,
|
.fsm.keyReadValue = key_user_read,
|
||||||
.func.ShortPressCb = key_user_short,
|
.func.ShortPressCb = key_user_short,
|
||||||
.func.longPressCb = key_user_long,
|
|
||||||
.func.releasePressCb = key_user_release,
|
.func.releasePressCb = key_user_release,
|
||||||
|
.func.longPressCb = key_user_pair_hint,
|
||||||
|
.func.lastPressCb = key_user_ota_start,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,18 +115,20 @@ void user_key_init(void)
|
|||||||
}
|
}
|
||||||
keyParaInit(s_keys);
|
keyParaInit(s_keys);
|
||||||
s_km.boot_key_lock = 0;
|
s_km.boot_key_lock = 0;
|
||||||
|
s_km.ota_fired = 0;
|
||||||
s_km.initialized = 1;
|
s_km.initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 开机判定结束后:键还按着则锁住,松开才认短按/长按
|
* @brief 上电后:键还按着则锁住短按,松开才认短按
|
||||||
|
* @note 只锁短按,**不锁长按分级**:上电就按住 5s 进配对是受支持的用法。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void user_key_lock_if_held(void)
|
void user_key_lock_if_held(void)
|
||||||
{
|
{
|
||||||
reset_key_Status(USR_KEY_USER);
|
reset_key_Status(USR_KEY_USER);
|
||||||
if (bsp_key_is_pressed()) {
|
if (bsp_key_is_pressed()) {
|
||||||
s_km.boot_key_lock = 1; /* 开机手还按着,等松开才认短按/长按,避免立刻关机 */
|
s_km.boot_key_lock = 1; /* 上电手还按着,等松开才认短按,避免一上电就切档 */
|
||||||
log_info("boot key held, wait release\n");
|
log_info("boot key held, wait release\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* @file key_manager.h
|
* @file key_manager.h
|
||||||
* @brief CBR3 单按键:短按切档,长按 3s 关机;开机 3s/5s/12s 不走本库
|
* @brief CBR3 单按键:短按切档,按住分级 5s 配对 / 12s OTA(无长按关机)
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V3.0.0,直接复用 key.c 原生长按/连按/释放事件做按住分级
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹,语义改切档/关机)
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __KEY_MANAGER_H__
|
#ifndef __KEY_MANAGER_H__
|
||||||
@@ -20,10 +18,24 @@
|
|||||||
void usr_on_key_short(void);
|
void usr_on_key_short(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 业务层长按 3s 回调(app_function 实现)
|
* @brief 业务层"按住满 5s"回调(app_function 实现):切配对提示灯,尚未清绑定
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void usr_on_key_long(void);
|
void usr_on_key_pair_hint(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 业务层"按满 5s 后松手"回调(app_function 实现):提交配对
|
||||||
|
* @note 只置标志;清绑定(写 VM)在 app_function_loop(任务上下文)执行
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void usr_on_key_pair_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 业务层"按住满 12s"回调(app_function 实现):到点即进 OTA
|
||||||
|
* @note 只置标志;usr_app_ota_init 在 app_function_loop(任务上下文)执行
|
||||||
|
* @return 无
|
||||||
|
*/
|
||||||
|
void usr_on_key_ota_start(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 装载按键表
|
* @brief 装载按键表
|
||||||
@@ -32,7 +44,7 @@ void usr_on_key_long(void);
|
|||||||
void user_key_init(void);
|
void user_key_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 开机判定结束后:若键还按着则锁住,松开才认短按/长按
|
* @brief 上电后:若键还按着则锁住短按,松开才认短按(不挡长按分级)
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void user_key_lock_if_held(void);
|
void user_key_lock_if_held(void);
|
||||||
|
|||||||
+1
-3
@@ -3,9 +3,7 @@
|
|||||||
* @brief LED 事件框架实现:只改 ledMask 对应通道,红绿互不抢
|
* @brief LED 事件框架实现:只改 ledMask 对应通道,红绿互不抢
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.25
|
* @date 2026.08.25
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布,实现按通道掩码独立开关的 LED 事件框架
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.25, cyWu, 首次发布,实现按通道掩码独立开关的 LED 事件框架
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
|
|||||||
+1
-5
@@ -3,11 +3,7 @@
|
|||||||
* @brief LED 事件框架:按通道掩码独立开关
|
* @brief LED 事件框架:按通道掩码独立开关
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.31
|
* @date 2026.08.31
|
||||||
* @version V1.2.0
|
* @version V1.2.0,CBR3 单灯:裁掉充电/低电/空电等门夹事件
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.25, cyWu, 首次发布,实现按通道掩码独立开关的 LED 事件框架
|
|
||||||
* - V1.1.0, 2026.08.27, cyWu, 新增 LED_EVENT_BOOT_REJECT
|
|
||||||
* - V1.2.0, 2026.08.31, cyWu, CBR3 单灯:裁掉充电/低电/空电等门夹事件
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __LED_H__
|
#ifndef __LED_H__
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 灯事件:单灯 PC2,高优先级覆盖低优先级
|
* @brief CBR3 灯事件:单灯 PC2,高优先级覆盖低优先级
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(移植门夹,删红绿双通道改单灯)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹,删红绿双通道改单灯)
|
|
||||||
*
|
*
|
||||||
* @note 灯效优先级(见规格书第 6 章,高者覆盖):
|
* @note 灯效优先级(见规格书第 6 章,高者覆盖):
|
||||||
* OTA(200ms 闪) > 配对中(100ms 快闪) / 配对结果 > 正常开机常亮。
|
* OTA(200ms 闪) > 配对中(100ms 快闪) / 配对结果 > 正常开机常亮。
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 单 LED(PC2)通道与事件表
|
* @brief CBR3 单 LED(PC2)通道与事件表
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(单灯版,删红绿双通道)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(单灯版,删红绿双通道)
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __LED_MANAGER_H__
|
#ifndef __LED_MANAGER_H__
|
||||||
|
|||||||
+33
-129
@@ -2,21 +2,23 @@
|
|||||||
* @file usr_jb_main.c
|
* @file usr_jb_main.c
|
||||||
* @brief CBR3 业务组合根:只做"先后调用谁、谁通知谁",不含具体业务算法
|
* @brief CBR3 业务组合根:只做"先后调用谁、谁通知谁",不含具体业务算法
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.31
|
||||||
* @version V1.0.0
|
* @version V2.3.0,上电即开机(无 app_boot);5s 配对 / 12s OTA 由 key_manager
|
||||||
* @history
|
* 长按分级触发;关机=拔电,已删除全部 app_power 软关机基础设施及
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹:删电池/USB,加风扇/显示/传感)
|
* DP0 开关相关死代码(power 恒 1,写死在 app_function_init);
|
||||||
|
* 删除 usr_timer_pick_mode/rearm 动态休眠调度(Type-C 长供电不
|
||||||
|
* 需要低功耗,且 app_disp_scan 常驻 priority=1 已让系统永远无法
|
||||||
|
* 休眠,该机制本来就没有实际效果),业务定时器改为一次性固定注册
|
||||||
*
|
*
|
||||||
* @note 协议生成文件 jb_product.c 不要填业务。APP 下行写 gDevData。
|
* @note 协议生成文件 jb_product.c 不要填业务。APP 下行写 gDevData。
|
||||||
* usr_timer_loop 由 BLE 回调,勿再注册第二份。
|
* usr_timer_loop 由 BLE 回调,勿再注册第二份。
|
||||||
* 具体业务逻辑去对应模块找:
|
* 具体业务逻辑去对应模块找:
|
||||||
* app_boot —— 开机 3s/5s/12s 按键判定
|
* key_manager —— 短按切档 + 按住 5s 配对 / 12s OTA 分级
|
||||||
* app_power —— 软关机请求(无电池/充电)
|
|
||||||
* app_pair —— 配对会话计时
|
* app_pair —— 配对会话计时
|
||||||
* app_fan —— 风扇档位
|
* app_fan —— 风扇档位
|
||||||
* app_th —— AHT20 采样
|
* app_th —— AHT20 采样
|
||||||
* app_disp —— 数码管显示
|
* app_disp —— 数码管显示
|
||||||
* app_function —— 按键动作 + DP 同步
|
* app_function —— 按键动作 + DP 同步 + 配对/OTA 动作落地
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "system/includes.h"
|
#include "system/includes.h"
|
||||||
@@ -32,9 +34,7 @@
|
|||||||
#include "usr_le_product.h"
|
#include "usr_le_product.h"
|
||||||
#include "usr_le_api.h"
|
#include "usr_le_api.h"
|
||||||
#include "bsp_hw.h"
|
#include "bsp_hw.h"
|
||||||
#include "app_power.h"
|
|
||||||
#include "app_pair.h"
|
#include "app_pair.h"
|
||||||
#include "app_boot.h"
|
|
||||||
#include "app_function.h"
|
#include "app_function.h"
|
||||||
#include "app_fan.h"
|
#include "app_fan.h"
|
||||||
#include "app_th.h"
|
#include "app_th.h"
|
||||||
@@ -46,7 +46,6 @@
|
|||||||
#include "app_nvm.h"
|
#include "app_nvm.h"
|
||||||
#include "app_led.h"
|
#include "app_led.h"
|
||||||
#include "key_manager.h"
|
#include "key_manager.h"
|
||||||
#include "asm/power/power_api.h"
|
|
||||||
|
|
||||||
#define LOG_TAG_CONST APP
|
#define LOG_TAG_CONST APP
|
||||||
#define LOG_TAG "[USR_JB]"
|
#define LOG_TAG "[USR_JB]"
|
||||||
@@ -65,128 +64,39 @@ const uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN] = {
|
|||||||
|
|
||||||
#define USR_TIMER_IDLE_MS 20 /**< 全局统一节拍(规格书第 3 章,禁止再开 1ms ISR) */
|
#define USR_TIMER_IDLE_MS 20 /**< 全局统一节拍(规格书第 3 章,禁止再开 1ms ISR) */
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 业务节拍档位
|
|
||||||
* @note 全系统只用一种节拍周期(USR_TIMER_IDLE_MS),区别只在"能不能休眠"
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
USR_TICK_IDLE = 0, /**< 可休眠 */
|
|
||||||
USR_TICK_BLOCK_SLEEP /**< 禁止休眠(按键按住/风扇转/关机流程/配对/OTA) */
|
|
||||||
} UsrTickMode_t;
|
|
||||||
|
|
||||||
/** 调度器状态 */
|
|
||||||
typedef struct {
|
|
||||||
int timer_id;
|
|
||||||
UsrTickMode_t mode;
|
|
||||||
} UsrSchedulerCtx_t;
|
|
||||||
|
|
||||||
static UsrSchedulerCtx_t s_sched;
|
|
||||||
|
|
||||||
static void usr_timer_tick(void *priv);
|
static void usr_timer_tick(void *priv);
|
||||||
static void usr_timer_rearm(UsrTickMode_t mode);
|
|
||||||
static void usr_log_boot_version(void);
|
static void usr_log_boot_version(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 软关机请求钩子:先落盘当前 mode/gear/配置,再停风扇、灯全灭
|
* @brief 业务定时器:固定 USR_TIMER_IDLE_MS 一拍,priority=1 常驻注册
|
||||||
* @note ⚠ app_nvm_save() 必须在 app_function_stop_all() 之前调用:
|
|
||||||
* stop_all 会把 mode/gear 清 0,先存才能保住用户最后的运行状态
|
|
||||||
* (规格书 13 章:软关机前写 VM,开机恢复上次 mode/gear)
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
static void usr_poweroff_request_hook(void)
|
|
||||||
{
|
|
||||||
app_nvm_save(); /* 软关机前立即写 VM(不等待 500ms 防抖) */
|
|
||||||
app_function_stop_all();
|
|
||||||
app_led_clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 软关机最终钩子:50ms 到点,真正进入深睡
|
|
||||||
* @note 不走 sys_enter_soft_poweroff():那是耳机 SDK 的优雅关机流程,实测慢。
|
|
||||||
* 本产品无 DAC/音频,直接进软关机(规格书 5.1:风扇 0、数码管锁存灭、
|
|
||||||
* LED 灭、BLE 停)。
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
static void usr_poweroff_finalize_hook(void)
|
|
||||||
{
|
|
||||||
bsp_hw_enter_sleep_io();
|
|
||||||
power_set_soft_poweroff();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 按当前业务状态判断能不能休眠
|
|
||||||
* @note 按键按住、风扇转、关机流程、配对中、OTA 灯效中 → 不能睡
|
|
||||||
* @return 本次应使用的档位
|
|
||||||
*/
|
|
||||||
static UsrTickMode_t usr_timer_pick_mode(void)
|
|
||||||
{
|
|
||||||
if (bsp_key_is_pressed() || app_power_poweroff_pending()
|
|
||||||
|| (app_fan_get_gear() != 0) || app_mode_get_active()
|
|
||||||
|| app_pair_is_active() || app_led_is_ota()) {
|
|
||||||
return USR_TICK_BLOCK_SLEEP;
|
|
||||||
}
|
|
||||||
return USR_TICK_IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 切换业务定时器。priority=1 时系统无法 sleep;节拍周期恒为 USR_TIMER_IDLE_MS
|
|
||||||
* @param mode 目标档位
|
|
||||||
* @return 无
|
|
||||||
*/
|
|
||||||
static void usr_timer_rearm(UsrTickMode_t mode)
|
|
||||||
{
|
|
||||||
if (s_sched.timer_id) {
|
|
||||||
usr_timer_del((u16)s_sched.timer_id);
|
|
||||||
s_sched.timer_id = 0;
|
|
||||||
}
|
|
||||||
s_sched.mode = mode;
|
|
||||||
s_sched.timer_id = (int)usr_timer_add(NULL, usr_timer_tick, USR_TIMER_IDLE_MS,
|
|
||||||
(mode == USR_TICK_BLOCK_SLEEP) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 业务定时器:固定 USR_TIMER_IDLE_MS 一拍;忙时禁睡,空闲可睡
|
|
||||||
* @param priv 未使用
|
* @param priv 未使用
|
||||||
* @note ⚠ 运行在硬件定时器时基上下文:禁止阻塞等待、禁止耗时操作。
|
* @note ⚠ 运行在硬件定时器时基上下文:禁止阻塞等待、禁止耗时操作。
|
||||||
* 关机请走 app_power 的钩子,不要在这里直接 power_set_soft_poweroff。
|
* priority 固定 1、只在 usr_jb_init 注册一次、永不重挂:本产品
|
||||||
|
* Type-C 长供电,不需要低功耗;且 app_disp_scan(CT1642 4ms 扫描)
|
||||||
|
* 本就以 priority=1 常驻,系统本来就永远无法进入低功耗,动态切换
|
||||||
|
* 这里的 priority 没有任何实际效果,纯属多余的复杂度。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
static void usr_timer_tick(void *priv)
|
static void usr_timer_tick(void *priv)
|
||||||
{
|
{
|
||||||
uint16_t dt = USR_TIMER_IDLE_MS;
|
uint16_t dt = USR_TIMER_IDLE_MS;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
UsrTickMode_t want;
|
|
||||||
|
|
||||||
(void)priv;
|
(void)priv;
|
||||||
for (i = 0; i < dt; i++) {
|
for (i = 0; i < dt; i++) {
|
||||||
jbTimerIrq();
|
jbTimerIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!app_power_poweroff_pending()) {
|
user_key_scan(dt); /* 内部完成 5s/12s 长按分级,只置标志 */
|
||||||
user_key_scan(dt);
|
user_key_handle(); /* 派发短按:切档 */
|
||||||
user_key_handle(); /* 长按 3s 会在这里同步触发 app_power_request_poweroff() */
|
app_th_poll(dt); /* 每2s采集一次温湿度 */
|
||||||
}
|
|
||||||
|
|
||||||
app_th_poll(dt); /* 内部 2s 才真正采;IO 分离后采集与显示互不干扰 */
|
|
||||||
app_mode_run(dt); /* 通风/强力状态机(20ms 计时精度;条件/定时在 500ms 任务上下文) */
|
app_mode_run(dt); /* 通风/强力状态机(20ms 计时精度;条件/定时在 500ms 任务上下文) */
|
||||||
app_fan_run(dt); /* P0 无动作 */
|
|
||||||
app_disp_run(dt); /* 刷新显示(告警闪烁) */
|
app_disp_run(dt); /* 刷新显示(告警闪烁) */
|
||||||
app_function_poll(); /* 同步 DP */
|
app_function_poll(); /* 同步 DP */
|
||||||
app_nvm_tick(dt); /* 档位/模式/配置变化检测 + 500ms 防抖计时(不写 flash!) */
|
app_nvm_tick(dt); /* 档位/模式/配置变化检测 + 500ms 防抖计时(不写 flash!) */
|
||||||
|
|
||||||
/* OTA 灯效期间最高优先级;关机流程中灯灭 */
|
/* OTA 灯效期间最高优先级;power_on 恒 1(DP0 预留不当开关,规格书 0 章第 5 条) */
|
||||||
if (app_led_is_ota()) {
|
app_led_run(dt, 1);
|
||||||
app_led_run(dt, app_function_is_power_on());
|
|
||||||
} else if (app_power_poweroff_pending()) {
|
|
||||||
app_led_clear();
|
|
||||||
} else {
|
|
||||||
app_led_run(dt, app_function_is_power_on());
|
|
||||||
}
|
|
||||||
|
|
||||||
want = usr_timer_pick_mode(); /* 判断能不能休眠 */
|
|
||||||
if (want != s_sched.mode) {
|
|
||||||
usr_timer_rearm(want);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,31 +113,25 @@ static void usr_log_boot_version(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 业务初始化(在 BLE 栈起来之前由 app_main 调用)
|
* @brief 业务初始化(在 BLE 栈起来之前由 app_main 调用)
|
||||||
* @note 内部会等按键 3s/5s/12s;不足 3s 直接深睡,不会启动业务定时器。
|
* @note ⚠ 上电即开机(规格书 5.1,2026-08-31 改):不再等待按键,插电/冷启动
|
||||||
* app_led_init() 排在 app_boot_wait_key() 前面:3s/5s 提示灯要用
|
* 直接进入工作态。5s 配对 / 12s OTA 改由运行态 key_manager 长按分级
|
||||||
* LED 事件表(规格书 5.2)。boot 深睡分支不返回,后面初始化不会浪费。
|
* 触发,动作在 app_function_loop(任务上下文)落地,故此处无需判定。
|
||||||
|
* app_led_init() 仍排在最前:后面模块的日志/灯效都依赖事件表已装载。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
void usr_jb_init(void)
|
void usr_jb_init(void)
|
||||||
{
|
{
|
||||||
usr_log_boot_version(); /* UART 已在 app_main 起来,按键判定前就能看到版本 */
|
usr_log_boot_version(); /* UART 已在 app_main 起来,最先能看到版本 */
|
||||||
|
|
||||||
bsp_hw_init();
|
bsp_hw_init();
|
||||||
app_led_init(); /* 提前到按键判定之前:3s 常亮/5s 配对闪都要用灯效事件表 */
|
app_led_init(); /* 先于一切业务:灯效事件表要最先装载 */
|
||||||
|
|
||||||
app_boot_wait_key(); /* 深睡分支不会返回;返回即代表确定要开机 */
|
|
||||||
|
|
||||||
jbInit();
|
jbInit();
|
||||||
userInit();
|
userInit();
|
||||||
if (usr_var.usr_goto_updata) {
|
|
||||||
/* 开机 12s 已进 OTA:立刻挂 200ms 闪 */
|
|
||||||
app_led_request_ota();
|
|
||||||
}
|
|
||||||
|
|
||||||
app_fan_init();
|
app_fan_init();
|
||||||
app_disp_init();
|
app_disp_init();
|
||||||
/* CT1642 无内部扫描 RAM,4ms 快节拍轮询 4 位。priority=1 会挡住系统 sleep,
|
|
||||||
* USB 常电产品故意如此:管子必须持续扫描,否则肉眼闪。勿改成 priority=0。 */
|
|
||||||
usr_timer_add(NULL, app_disp_scan, BOARD_DISP_SCAN_MS, 1);
|
usr_timer_add(NULL, app_disp_scan, BOARD_DISP_SCAN_MS, 1);
|
||||||
app_th_init();
|
app_th_init();
|
||||||
app_mode_init();
|
app_mode_init();
|
||||||
@@ -237,16 +141,16 @@ void usr_jb_init(void)
|
|||||||
app_nvm_init();
|
app_nvm_init();
|
||||||
app_nvm_load();
|
app_nvm_load();
|
||||||
|
|
||||||
app_power_init();
|
|
||||||
app_power_set_hooks(usr_poweroff_request_hook, usr_poweroff_finalize_hook);
|
|
||||||
app_function_init();
|
app_function_init();
|
||||||
|
|
||||||
user_key_init();
|
user_key_init();
|
||||||
|
/* 上电时键若还按着:只锁短按(避免一上电就切档),长按 5s/12s 分级照常生效,
|
||||||
|
* 所以"插电时就按住 5s 进配对"这一用法仍然成立 */
|
||||||
user_key_lock_if_held();
|
user_key_lock_if_held();
|
||||||
app_function_power_on_silent();
|
|
||||||
|
|
||||||
usr_timer_rearm(USR_TICK_IDLE);
|
/* priority=1 常驻注册,永不重挂(Type-C 长供电不需要低功耗,见 usr_timer_tick) */
|
||||||
log_info("timer idle %ums, sleep ok\n", (unsigned)USR_TIMER_IDLE_MS);
|
usr_timer_add(NULL, usr_timer_tick, USR_TIMER_IDLE_MS, 1);
|
||||||
|
log_info("timer started, period=%ums\n", (unsigned)USR_TIMER_IDLE_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -267,7 +171,7 @@ void usr_jb_le_recieve_data(u8 *data, u16 len)
|
|||||||
* (BLE 线程,栈充足),与 20ms 的 usr_timer_tick(usr_timer_add 异步
|
* (BLE 线程,栈充足),与 20ms 的 usr_timer_tick(usr_timer_add 异步
|
||||||
* 接口 = 硬件定时器中断上下文,栈极小)不同。
|
* 接口 = 硬件定时器中断上下文,栈极小)不同。
|
||||||
* **所有重量级/自动化引擎必须放这里**:条件/定时引擎(500ms 粒度对
|
* **所有重量级/自动化引擎必须放这里**:条件/定时引擎(500ms 粒度对
|
||||||
* 2s 采样与分钟级时长足够,且单次自毁要写 VM)、VM 落盘、关机收口。
|
* 2s 采样与分钟级时长足够,且单次自毁要写 VM)、VM 落盘、配对/OTA 落地。
|
||||||
* 禁止放进 usr_timer_tick——曾因在 20ms 中断里调 syscfg_write 栈溢出软复位。
|
* 禁止放进 usr_timer_tick——曾因在 20ms 中断里调 syscfg_write 栈溢出软复位。
|
||||||
* @return 无
|
* @return 无
|
||||||
*/
|
*/
|
||||||
@@ -277,5 +181,5 @@ void usr_timer_loop(void)
|
|||||||
jbProtocolHandle(&gDevData);
|
jbProtocolHandle(&gDevData);
|
||||||
app_cond_run(500); /* 条件引擎(任务上下文;条件/定时仲裁见 app_arbiter) */
|
app_cond_run(500); /* 条件引擎(任务上下文;条件/定时仲裁见 app_arbiter) */
|
||||||
app_timer_run(500); /* 定时引擎(任务上下文;RTC 门闩 + 窗判断) */
|
app_timer_run(500); /* 定时引擎(任务上下文;RTC 门闩 + 窗判断) */
|
||||||
app_function_loop(); /* 任务上下文:VM 防抖落盘 + 延后关机收口 */
|
app_function_loop(); /* 任务上下文:VM 防抖落盘 + 配对/OTA 动作落地 */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 温湿度风扇板级引脚、电平与时序(换板只改本文件)
|
* @brief CBR3 温湿度风扇板级引脚、电平与时序(换板只改本文件)
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(P0 Bring-up)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 Bring-up)
|
|
||||||
*
|
*
|
||||||
* @note 产品 GPIO 全部集中到本文件;板级 board_jl701n_demo_cfg.h 只保留
|
* @note 产品 GPIO 全部集中到本文件;板级 board_jl701n_demo_cfg.h 只保留
|
||||||
* UART0_TX=PG6 一项改动。CT1642 用 PG0(CLK)/PG1(DATA),AHT20 用
|
* UART0_TX=PG6 一项改动。CT1642 用 PG0(CLK)/PG1(DATA),AHT20 用
|
||||||
@@ -54,10 +52,15 @@
|
|||||||
/* 按键 / 开机 */
|
/* 按键 / 开机 */
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
|
|
||||||
#define BOARD_KEY_CLICK_MS 1000 /**< 开机后:按下 <1s 松开为短按切档 */
|
/**
|
||||||
#define BOARD_KEY_POWER_MS 3000 /**< 关机态:按住 3s 开机;开机态:按住 3s 关机 */
|
* 直接作为 key.c 状态机的 keyLongTime/keyLastTime 使用:
|
||||||
#define BOARD_KEY_PAIR_MS 5000 /**< 关机态:按住 5s 开机并进配对 */
|
* 松手时刻 <BOARD_KEY_PAIR_MS → SHORT_Event,切档(见 5.3)
|
||||||
#define BOARD_KEY_OTA_MS 12000 /**< 关机态:按住 12s 开机并进 OTA */
|
* 按住满 BOARD_KEY_PAIR_MS → LONG_Event(仍按住),切配对提示灯
|
||||||
|
* 按住满 BOARD_KEY_OTA_MS → LAST_Event(仍按住,到点即触发),进 OTA
|
||||||
|
* 按满 5s~12s 后松手 → RELEASE_Event,提交配对
|
||||||
|
*/
|
||||||
|
#define BOARD_KEY_PAIR_MS 5000 /**< keyLongTime:满 5s 挂配对提示灯 */
|
||||||
|
#define BOARD_KEY_OTA_MS 12000 /**< keyLastTime:满 12s 到点直接进 OTA */
|
||||||
#define BOARD_KEY_DEBOUNCE_MS 20 /**< 按键消抖 */
|
#define BOARD_KEY_DEBOUNCE_MS 20 /**< 按键消抖 */
|
||||||
#define BOARD_PAIR_TIMEOUT_MS (120u * 1000u) /**< 配对超时 120s,失败后保持开机 */
|
#define BOARD_PAIR_TIMEOUT_MS (120u * 1000u) /**< 配对超时 120s,失败后保持开机 */
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,9 @@
|
|||||||
* @brief CBR3 AHT20 软件 I2C 驱动实现
|
* @brief CBR3 AHT20 软件 I2C 驱动实现
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.3
|
* @version V1.0.3,IO 分离:AHT20 独占 PC4(SCL)/PC5(SDA),无总线共享锁,
|
||||||
* @history
|
* 采集一次完成;修复 SCL 高电平期间推挽输出 SDA 导致的假 STOP,
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
* 补 0x71 校准检查 + 0xBE 初始化
|
||||||
* - V1.0.1, 2026.08.29, cyWu, 修复 SCL 高电平期间推挽输出 SDA 导致的假 STOP
|
|
||||||
* (读数据必 CRC fail 的根因);补 AHT20 0x71 校准检查 + 0xBE 初始化
|
|
||||||
* - V1.0.2, 2026.08.29, cyWu, 排障结束:回退诊断代码(电平自检/地址扫描/IN 直读),
|
|
||||||
* 保留时序修复、内部上拉依赖、总线恢复、0x71/0xBE 初始化流程
|
|
||||||
* - V1.0.3, 2026.08.29, cyWu, IO 分离:AHT20 独占 PC4(SCL)/PC5(SDA),删除
|
|
||||||
* bsp_bus 共线锁与 measure_start/finish 拆分锁,采集恢复一次完成;
|
|
||||||
* PC4/PC5 上拉配置从 bsp_bus_init 移入本文件 init
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "bsp_aht20.h"
|
#include "bsp_aht20.h"
|
||||||
|
|||||||
@@ -3,13 +3,8 @@
|
|||||||
* @brief CBR3 AHT20 温湿度传感器:软件 I2C + 测量 + CRC8
|
* @brief CBR3 AHT20 温湿度传感器:软件 I2C + 测量 + CRC8
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.3
|
* @version V1.0.3,IO 分离:AHT20 独占 PC4(SCL)/PC5(SDA),无总线共享锁,
|
||||||
* @history
|
* 恢复一次完成采集;含 SCL 高电平假 STOP 修复与 0x71 校准检查
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
* - V1.0.1, 2026.08.29, cyWu, 修复 SCL 高电平期间推挽输出 SDA 导致的假 STOP
|
|
||||||
* - V1.0.2, 2026.08.29, cyWu, 回退诊断代码,保留时序修复/上拉/总线恢复/0x71 校准
|
|
||||||
* - V1.0.3, 2026.08.29, cyWu, IO 分离:AHT20 独占 PC4(SCL)/PC5(SDA),删除
|
|
||||||
* bsp_bus 共线锁与 measure_start/finish 拆分锁,恢复一次完成采集
|
|
||||||
*
|
*
|
||||||
* @note I2C 7 位地址 0x38(写 0x70 / 读 0x71)。测量命令 0xAC 0x33 0x00,
|
* @note I2C 7 位地址 0x38(写 0x70 / 读 0x71)。测量命令 0xAC 0x33 0x00,
|
||||||
* 等 ≥80ms 后读 7 字节:Status + 20bit 湿度 + 20bit 温度 + CRC8。
|
* 等 ≥80ms 后读 7 字节:Status + 20bit 湿度 + 20bit 温度 + CRC8。
|
||||||
|
|||||||
@@ -3,12 +3,7 @@
|
|||||||
* @brief CBR3 CT1642 类数码管驱动实现(软件移位)
|
* @brief CBR3 CT1642 类数码管驱动实现(软件移位)
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.1
|
* @version V1.0.1,IO 分离:CT1642 独立 PG0=CLK/PG1=DATA,无总线共享机制
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
* - V1.0.1, 2026.08.29, cyWu, IO 分离:CT1642 独立 PG0=CLK/PG1=DATA,删除
|
|
||||||
* bsp_bus 共线机制;删调试遗留 latch/show4/scan_seg/scan_com,
|
|
||||||
* 新增 bsp_ct1642_init()
|
|
||||||
*
|
*
|
||||||
* @note 驱动协议严格参照 CT1642 手册(与 CSDN yitx 一致):
|
* @note 驱动协议严格参照 CT1642 手册(与 CSDN yitx 一致):
|
||||||
* 一帧 = 18bit,CLK 上升沿采样 DATA(DATA 只在 CLK=低时改变):
|
* 一帧 = 18bit,CLK 上升沿采样 DATA(DATA 只在 CLK=低时改变):
|
||||||
|
|||||||
@@ -3,12 +3,8 @@
|
|||||||
* @brief CBR3 CT1642 类数码管驱动:18bit 移位、锁存、送出
|
* @brief CBR3 CT1642 类数码管驱动:18bit 移位、锁存、送出
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.1
|
* @version V1.0.1,IO 分离:CT1642 独立 PG0=CLK/PG1=DATA(飞线),AHT20
|
||||||
* @history
|
* 独占 PC4/PC5,无总线共享机制
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布
|
|
||||||
* - V1.0.1, 2026.08.29, cyWu, IO 分离:CT1642 独立 PG0=CLK/PG1=DATA(飞线),
|
|
||||||
* AHT20 独占 PC4/PC5,删除 bsp_bus 共线机制;删调试遗留
|
|
||||||
* latch/show4/scan_seg/scan_com,新增 bsp_ct1642_init()
|
|
||||||
*
|
*
|
||||||
* @note PG0=CLK,PG1=DATA,独立引脚、无总线锁,可随时调用。
|
* @note PG0=CLK,PG1=DATA,独立引脚、无总线锁,可随时调用。
|
||||||
* 协议:一帧 18bit(C1-C4 位选 + 6 位保留 + Q2-Q9 段码),CLK 上升沿采样
|
* 协议:一帧 18bit(C1-C4 位选 + 6 位保留 + Q2-Q9 段码),CLK 上升沿采样
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 板级 GPIO / MCPWM:LED、按键、风扇
|
* @brief CBR3 板级 GPIO / MCPWM:LED、按键、风扇
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(移植门夹:删电机/充电/电量,改单 LED + 风扇 PWM)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹:删电机/充电/电量,改单 LED + 风扇 PWM)
|
|
||||||
*
|
*
|
||||||
* @note CT1642 在 PG0/PG1、AHT20 在 PC4/PC5,各自独立驱动,
|
* @note CT1642 在 PG0/PG1、AHT20 在 PC4/PC5,各自独立驱动,
|
||||||
* bsp_hw 只管 LED/KEY/FAN,不碰这两组脚。
|
* bsp_hw 只管 LED/KEY/FAN,不碰这两组脚。
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
* @brief CBR3 板级硬件:LED / 按键 / 风扇 PWM
|
* @brief CBR3 板级硬件:LED / 按键 / 风扇 PWM
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.29
|
* @date 2026.08.29
|
||||||
* @version V1.0.0
|
* @version V1.0.0,首次发布(移植门夹:删电机/充电/电量,改单 LED + 风扇 PWM)
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(移植门夹:删电机/充电/电量,改单 LED + 风扇 PWM)
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __BSP_HW_H__
|
#ifndef __BSP_HW_H__
|
||||||
|
|||||||
@@ -3,10 +3,7 @@
|
|||||||
* @brief 板级 RTC 外设实现(BR28 硬件 rtc_dev_ops)
|
* @brief 板级 RTC 外设实现(BR28 硬件 rtc_dev_ops)
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.19
|
* @date 2026.08.19
|
||||||
* @version V1.1.0
|
* @version V1.1.0,从模组固件移植至 SOC SDK,精简公共接口与缓存逻辑
|
||||||
* @history
|
|
||||||
* - V1.0.0, 2026.08.19, cyWu, 从模组固件移植至 SOC SDK
|
|
||||||
* - V1.1.0, 2026.08.19, cyWu, 精简公共接口与缓存逻辑
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "system/includes.h"
|
#include "system/includes.h"
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
* @brief 板级 RTC:硬件对时 + 客户读本地日历
|
* @brief 板级 RTC:硬件对时 + 客户读本地日历
|
||||||
* @author cyWu <1917507415@qq.com>
|
* @author cyWu <1917507415@qq.com>
|
||||||
* @date 2026.08.19
|
* @date 2026.08.19
|
||||||
* @version V1.1.0
|
* @version V1.1.0,从模组固件移植至 SOC SDK;精简接口,usr_rtc_get_time
|
||||||
* @history
|
* 返回本地日历
|
||||||
* - V1.0.0, 2026.08.19, cyWu, 从模组固件移植至 SOC SDK
|
|
||||||
* - V1.1.0, 2026.08.19, cyWu, 精简接口;usr_rtc_get_time 返回本地日历
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef __USR_RTC_H__
|
#ifndef __USR_RTC_H__
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ copy ..\..\ota.bin .
|
|||||||
copy ..\..\anc_coeff.bin .
|
copy ..\..\anc_coeff.bin .
|
||||||
copy ..\..\anc_gains.bin .
|
copy ..\..\anc_gains.bin .
|
||||||
|
|
||||||
..\..\isd_download.exe ..\..\isd_config.ini -tonorflash -dev br28 -boot 0x120000 -div8 -wait 300 -uboot ..\..\uboot.boot -app ..\..\app.bin -res ..\..\cfg_tool.bin tone.cfg p11_code.bin -uboot_compress
|
..\..\isd_download.exe ..\..\isd_config.ini -tonorflash -dev br28 -boot 0x120000 -div8 -wait 300 -uboot ..\..\uboot.boot -app ..\..\app.bin -res ..\..\cfg_tool.bin tone.cfg p11_code.bin -uboot_compress -key RS-5B88.key
|
||||||
|
|
||||||
:: -format all -key RS-5B88.key
|
:: -format all -key RS-5B88.key
|
||||||
::-reboot 2500
|
::-reboot 2500
|
||||||
|
|||||||
Reference in New Issue
Block a user