1、业务调度统一为 20ms 节拍,取消电机运转时的 1ms 高频定时器,避免配网后 BLE 收发与 1kHz 中断抢时序导致看门狗复位
2、调度器只保留可休眠/禁休眠两档,换向死区改由阈值检查判定,不再单独切 1ms 精度 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* @brief CBC2 业务组合根:只做“先后调用谁、谁通知谁”,不含具体业务算法
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.08.25
|
||||
* @version V2.0.0
|
||||
* @version V2.1.0
|
||||
* @history
|
||||
* - V1.0.0, 2026.08.21, cyWu, 首次发布
|
||||
* - V1.1.0, 2026.08.24, cyWu, 收口未接线模块;DP2 仅第 1 字节点动 1s
|
||||
@@ -13,6 +13,11 @@
|
||||
* - V1.5.0, 2026.08.25, cyWu, LED/按键改充电板事件库,红绿可同时亮
|
||||
* - V2.0.0, 2026.08.25, cyWu, 重构:电源/配对/开机/功能拆成独立模块,
|
||||
* 本文件只剩初始化顺序、1ms 调度、模块间接线
|
||||
* - V2.1.0, 2026.08.26, cyWu, 电机运转期间长期占用 1ms 硬件定时器中断,
|
||||
* 配网连接后与 BLE 协议栈抢时序触发看门狗复位;
|
||||
* 换向死区判定改用阈值检查而非精确计时,
|
||||
* 取消专门的 1ms 高频档,全系统统一 20ms 节拍,
|
||||
* 只保留"能不能休眠"这一个维度
|
||||
*
|
||||
* @note 协议生成文件 jb_product.c 不要填业务。APP 下行写 gDevData。
|
||||
* usr_timer_loop 由 BLE 回调,勿再注册第二份。
|
||||
@@ -61,18 +66,34 @@ const uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN] = {
|
||||
JB_PRODUCT_CODE[3], JB_PRODUCT_CODE[4], JB_PRODUCT_CODE[5]
|
||||
};
|
||||
|
||||
#define USR_TIMER_IDLE_MS 20 /**< 空闲节拍:可 sleep;按键 20ms 消抖对齐 */
|
||||
#define USR_TIMER_IDLE_MS 20 /**< 全局统一节拍:按键消抖、换向死区判定都按它对齐 */
|
||||
|
||||
/**
|
||||
* @brief 业务节拍档位
|
||||
* @note 全系统只用一种节拍周期(USR_TIMER_IDLE_MS),区别只在"能不能休眠",
|
||||
* 不存在专门的 1ms 高频档——之前为了电机换向死区(BOARD_MOTOR_REVERSE_MS)
|
||||
* 单独开过 1ms 硬件定时器中断,配网连接后跟 BLE 协议栈自己的收发/ACK
|
||||
* 处理抢时序,长时间叠加导致看门狗复位。
|
||||
* 换向死区的判定是"距上次换向是否已过 switch_ms"这种阈值检查,不是
|
||||
* 精确计时:用 20ms 节拍去查,查到时实际已经过了不少于 20ms,天然
|
||||
* 满足"至少 1ms"的死区要求,只会让保护更充分,不会失效。所以死区
|
||||
* 不需要专门的 1ms 精度,可以和其它业务共用同一个节拍。
|
||||
*/
|
||||
typedef enum {
|
||||
USR_TICK_IDLE = 0, /**< 可休眠 */
|
||||
USR_TICK_BLOCK_SLEEP /**< 禁止休眠(按键按住/玩法中/关机等待/电机运转,含换向死区)*/
|
||||
} UsrTickMode_t;
|
||||
|
||||
/** 调度器状态,替代原来 2 个散落的 static */
|
||||
typedef struct {
|
||||
int timer_id;
|
||||
uint8_t fast; /**< 1=1ms 高优(禁睡),0=空闲可休眠 */
|
||||
int timer_id;
|
||||
UsrTickMode_t mode;
|
||||
} UsrSchedulerCtx_t;
|
||||
|
||||
static UsrSchedulerCtx_t s_sched;
|
||||
|
||||
static void usr_timer_1_ms(void *priv);
|
||||
static void usr_timer_rearm(uint8_t fast);
|
||||
static void usr_timer_tick(void *priv);
|
||||
static void usr_timer_rearm(UsrTickMode_t mode);
|
||||
|
||||
/**
|
||||
* @brief USB 插拔的联动:插入即停电机,拔出即软关并刷新系统电源图标
|
||||
@@ -123,50 +144,49 @@ static void usr_poweroff_finalize_hook(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 电机/按键按住时用 1ms 高优定时器;空闲用可休眠节拍
|
||||
* @return 1=需要 1ms 高优,0=可休眠
|
||||
* @brief 按当前业务状态判断能不能休眠
|
||||
* @note 换向死区(bsp_motor_is_busy 已把它算进"忙")、点动、玩法、按键按住、
|
||||
* 关机等待,统一都是"不能睡",节拍周期都一样用 USR_TIMER_IDLE_MS,
|
||||
* 不再区分要不要 1ms
|
||||
* @return 本次应使用的档位
|
||||
*/
|
||||
static uint8_t usr_timer_should_fast(void)
|
||||
static UsrTickMode_t usr_timer_pick_mode(void)
|
||||
{
|
||||
if (app_function_is_hand_busy() || bsp_key_is_pressed() || app_power_poweroff_pending()) {
|
||||
return 1;
|
||||
if (bsp_key_is_pressed() || app_power_poweroff_pending()
|
||||
|| app_mode_get_active() || bsp_motor_is_busy()
|
||||
|| app_function_is_hand_busy()) {
|
||||
return USR_TICK_BLOCK_SLEEP;
|
||||
}
|
||||
if (app_mode_get_active() || bsp_motor_is_busy()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return USR_TICK_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 切换业务定时器。priority=1 时系统无法 sleep
|
||||
* @param fast 1=1ms 高优,0=空闲可休眠
|
||||
* @brief 切换业务定时器。priority=1 时系统无法 sleep;节拍周期恒为 USR_TIMER_IDLE_MS
|
||||
* @param mode 目标档位
|
||||
* @return 无
|
||||
*/
|
||||
static void usr_timer_rearm(uint8_t fast)
|
||||
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.fast = fast;
|
||||
if (fast) {
|
||||
s_sched.timer_id = (int)sys_hi_timer_add(NULL, usr_timer_1_ms, 1);
|
||||
} else {
|
||||
s_sched.timer_id = (int)sys_s_hi_timer_add(NULL, usr_timer_1_ms, USR_TIMER_IDLE_MS);
|
||||
}
|
||||
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 业务定时器:空闲可 sleep;玩法/点动时 1ms 且禁 sleep
|
||||
* @brief 业务定时器:固定 USR_TIMER_IDLE_MS 一拍;忙时禁睡,空闲可睡
|
||||
* @param priv 未使用
|
||||
* @note 禁止在这里直接 sys_enter_soft_poweroff,一律走 app_power 的深睡钩子
|
||||
* @return 无
|
||||
*/
|
||||
static void usr_timer_1_ms(void *priv)
|
||||
static void usr_timer_tick(void *priv)
|
||||
{
|
||||
uint16_t dt = s_sched.fast ? 1 : USR_TIMER_IDLE_MS;
|
||||
uint16_t dt = USR_TIMER_IDLE_MS;
|
||||
uint16_t i;
|
||||
uint8_t want;
|
||||
UsrTickMode_t want;
|
||||
AppPowerEvt_t pwr_evt;
|
||||
|
||||
(void)priv;
|
||||
@@ -191,15 +211,15 @@ static void usr_timer_1_ms(void *priv)
|
||||
app_led_run(dt, app_function_is_power_on());
|
||||
}
|
||||
|
||||
want = usr_timer_should_fast();
|
||||
if (want != s_sched.fast) {
|
||||
want = usr_timer_pick_mode();
|
||||
if (want != s_sched.mode) {
|
||||
usr_timer_rearm(want);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 业务初始化(在 BLE 栈起来之前由 app_main 调用)
|
||||
* @note 内部会等按键 3s/5s;不足 3s 直接深睡,不会启动 1ms 定时器。
|
||||
* @note 内部会等按键 3s/5s;不足 3s 直接深睡,不会启动业务定时器。
|
||||
* 按键判定只摸 bsp_hw 的裸 GPIO,不经过协议栈/灯效表/电机状态机,
|
||||
* 所以只有 bsp_hw_init() 需要排在它前面——一旦判定要睡回去,
|
||||
* boot_sleep() 原地喂狗不再返回,后面这些初始化不会被浪费。
|
||||
@@ -224,7 +244,7 @@ void usr_jb_init(void)
|
||||
user_key_lock_if_held();
|
||||
app_function_power_on_silent();
|
||||
|
||||
usr_timer_rearm(0);
|
||||
usr_timer_rearm(USR_TICK_IDLE);
|
||||
log_info("timer idle %ums, sleep ok\n", (unsigned)USR_TIMER_IDLE_MS);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user