精简 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:
+33
-129
@@ -2,21 +2,23 @@
|
||||
* @file usr_jb_main.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,加风扇/显示/传感)
|
||||
* @date 2026.08.31
|
||||
* @version V2.3.0,上电即开机(无 app_boot);5s 配对 / 12s OTA 由 key_manager
|
||||
* 长按分级触发;关机=拔电,已删除全部 app_power 软关机基础设施及
|
||||
* DP0 开关相关死代码(power 恒 1,写死在 app_function_init);
|
||||
* 删除 usr_timer_pick_mode/rearm 动态休眠调度(Type-C 长供电不
|
||||
* 需要低功耗,且 app_disp_scan 常驻 priority=1 已让系统永远无法
|
||||
* 休眠,该机制本来就没有实际效果),业务定时器改为一次性固定注册
|
||||
*
|
||||
* @note 协议生成文件 jb_product.c 不要填业务。APP 下行写 gDevData。
|
||||
* usr_timer_loop 由 BLE 回调,勿再注册第二份。
|
||||
* 具体业务逻辑去对应模块找:
|
||||
* app_boot —— 开机 3s/5s/12s 按键判定
|
||||
* app_power —— 软关机请求(无电池/充电)
|
||||
* key_manager —— 短按切档 + 按住 5s 配对 / 12s OTA 分级
|
||||
* app_pair —— 配对会话计时
|
||||
* app_fan —— 风扇档位
|
||||
* app_th —— AHT20 采样
|
||||
* app_disp —— 数码管显示
|
||||
* app_function —— 按键动作 + DP 同步
|
||||
* app_function —— 按键动作 + DP 同步 + 配对/OTA 动作落地
|
||||
******************************************************************************/
|
||||
|
||||
#include "system/includes.h"
|
||||
@@ -32,9 +34,7 @@
|
||||
#include "usr_le_product.h"
|
||||
#include "usr_le_api.h"
|
||||
#include "bsp_hw.h"
|
||||
#include "app_power.h"
|
||||
#include "app_pair.h"
|
||||
#include "app_boot.h"
|
||||
#include "app_function.h"
|
||||
#include "app_fan.h"
|
||||
#include "app_th.h"
|
||||
@@ -46,7 +46,6 @@
|
||||
#include "app_nvm.h"
|
||||
#include "app_led.h"
|
||||
#include "key_manager.h"
|
||||
#include "asm/power/power_api.h"
|
||||
|
||||
#define LOG_TAG_CONST APP
|
||||
#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) */
|
||||
|
||||
/**
|
||||
* @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_rearm(UsrTickMode_t mode);
|
||||
static void usr_log_boot_version(void);
|
||||
|
||||
/**
|
||||
* @brief 软关机请求钩子:先落盘当前 mode/gear/配置,再停风扇、灯全灭
|
||||
* @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 一拍;忙时禁睡,空闲可睡
|
||||
* @brief 业务定时器:固定 USR_TIMER_IDLE_MS 一拍,priority=1 常驻注册
|
||||
* @param priv 未使用
|
||||
* @note ⚠ 运行在硬件定时器时基上下文:禁止阻塞等待、禁止耗时操作。
|
||||
* 关机请走 app_power 的钩子,不要在这里直接 power_set_soft_poweroff。
|
||||
* priority 固定 1、只在 usr_jb_init 注册一次、永不重挂:本产品
|
||||
* Type-C 长供电,不需要低功耗;且 app_disp_scan(CT1642 4ms 扫描)
|
||||
* 本就以 priority=1 常驻,系统本来就永远无法进入低功耗,动态切换
|
||||
* 这里的 priority 没有任何实际效果,纯属多余的复杂度。
|
||||
* @return 无
|
||||
*/
|
||||
static void usr_timer_tick(void *priv)
|
||||
{
|
||||
uint16_t dt = USR_TIMER_IDLE_MS;
|
||||
uint16_t i;
|
||||
UsrTickMode_t want;
|
||||
|
||||
(void)priv;
|
||||
for (i = 0; i < dt; i++) {
|
||||
jbTimerIrq();
|
||||
}
|
||||
|
||||
if (!app_power_poweroff_pending()) {
|
||||
user_key_scan(dt);
|
||||
user_key_handle(); /* 长按 3s 会在这里同步触发 app_power_request_poweroff() */
|
||||
}
|
||||
|
||||
app_th_poll(dt); /* 内部 2s 才真正采;IO 分离后采集与显示互不干扰 */
|
||||
user_key_scan(dt); /* 内部完成 5s/12s 长按分级,只置标志 */
|
||||
user_key_handle(); /* 派发短按:切档 */
|
||||
app_th_poll(dt); /* 每2s采集一次温湿度 */
|
||||
app_mode_run(dt); /* 通风/强力状态机(20ms 计时精度;条件/定时在 500ms 任务上下文) */
|
||||
app_fan_run(dt); /* P0 无动作 */
|
||||
app_disp_run(dt); /* 刷新显示(告警闪烁) */
|
||||
app_function_poll(); /* 同步 DP */
|
||||
app_nvm_tick(dt); /* 档位/模式/配置变化检测 + 500ms 防抖计时(不写 flash!) */
|
||||
|
||||
/* OTA 灯效期间最高优先级;关机流程中灯灭 */
|
||||
if (app_led_is_ota()) {
|
||||
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);
|
||||
}
|
||||
/* OTA 灯效期间最高优先级;power_on 恒 1(DP0 预留不当开关,规格书 0 章第 5 条) */
|
||||
app_led_run(dt, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,31 +113,25 @@ static void usr_log_boot_version(void)
|
||||
|
||||
/**
|
||||
* @brief 业务初始化(在 BLE 栈起来之前由 app_main 调用)
|
||||
* @note 内部会等按键 3s/5s/12s;不足 3s 直接深睡,不会启动业务定时器。
|
||||
* app_led_init() 排在 app_boot_wait_key() 前面:3s/5s 提示灯要用
|
||||
* LED 事件表(规格书 5.2)。boot 深睡分支不返回,后面初始化不会浪费。
|
||||
* @note ⚠ 上电即开机(规格书 5.1,2026-08-31 改):不再等待按键,插电/冷启动
|
||||
* 直接进入工作态。5s 配对 / 12s OTA 改由运行态 key_manager 长按分级
|
||||
* 触发,动作在 app_function_loop(任务上下文)落地,故此处无需判定。
|
||||
* app_led_init() 仍排在最前:后面模块的日志/灯效都依赖事件表已装载。
|
||||
* @return 无
|
||||
*/
|
||||
void usr_jb_init(void)
|
||||
{
|
||||
usr_log_boot_version(); /* UART 已在 app_main 起来,按键判定前就能看到版本 */
|
||||
usr_log_boot_version(); /* UART 已在 app_main 起来,最先能看到版本 */
|
||||
|
||||
bsp_hw_init();
|
||||
app_led_init(); /* 提前到按键判定之前:3s 常亮/5s 配对闪都要用灯效事件表 */
|
||||
|
||||
app_boot_wait_key(); /* 深睡分支不会返回;返回即代表确定要开机 */
|
||||
app_led_init(); /* 先于一切业务:灯效事件表要最先装载 */
|
||||
|
||||
jbInit();
|
||||
userInit();
|
||||
if (usr_var.usr_goto_updata) {
|
||||
/* 开机 12s 已进 OTA:立刻挂 200ms 闪 */
|
||||
app_led_request_ota();
|
||||
}
|
||||
|
||||
app_fan_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);
|
||||
app_th_init();
|
||||
app_mode_init();
|
||||
@@ -237,16 +141,16 @@ void usr_jb_init(void)
|
||||
app_nvm_init();
|
||||
app_nvm_load();
|
||||
|
||||
app_power_init();
|
||||
app_power_set_hooks(usr_poweroff_request_hook, usr_poweroff_finalize_hook);
|
||||
app_function_init();
|
||||
|
||||
user_key_init();
|
||||
/* 上电时键若还按着:只锁短按(避免一上电就切档),长按 5s/12s 分级照常生效,
|
||||
* 所以"插电时就按住 5s 进配对"这一用法仍然成立 */
|
||||
user_key_lock_if_held();
|
||||
app_function_power_on_silent();
|
||||
|
||||
usr_timer_rearm(USR_TICK_IDLE);
|
||||
log_info("timer idle %ums, sleep ok\n", (unsigned)USR_TIMER_IDLE_MS);
|
||||
/* priority=1 常驻注册,永不重挂(Type-C 长供电不需要低功耗,见 usr_timer_tick) */
|
||||
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 异步
|
||||
* 接口 = 硬件定时器中断上下文,栈极小)不同。
|
||||
* **所有重量级/自动化引擎必须放这里**:条件/定时引擎(500ms 粒度对
|
||||
* 2s 采样与分钟级时长足够,且单次自毁要写 VM)、VM 落盘、关机收口。
|
||||
* 2s 采样与分钟级时长足够,且单次自毁要写 VM)、VM 落盘、配对/OTA 落地。
|
||||
* 禁止放进 usr_timer_tick——曾因在 20ms 中断里调 syscfg_write 栈溢出软复位。
|
||||
* @return 无
|
||||
*/
|
||||
@@ -277,5 +181,5 @@ void usr_timer_loop(void)
|
||||
jbProtocolHandle(&gDevData);
|
||||
app_cond_run(500); /* 条件引擎(任务上下文;条件/定时仲裁见 app_arbiter) */
|
||||
app_timer_run(500); /* 定时引擎(任务上下文;RTC 门闩 + 窗判断) */
|
||||
app_function_loop(); /* 任务上下文:VM 防抖落盘 + 延后关机收口 */
|
||||
app_function_loop(); /* 任务上下文:VM 防抖落盘 + 配对/OTA 动作落地 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user