新增 usr_app 产品逻辑:手动>定时>条件仲裁、条件控温湿、定时任务、数码管显示、 按键/LED、风扇档位、NVM 掉电恢复、配对与开关机,上电按规格恢复上次状态。 新增 usr_periph:AHT20、CT1642、板级引脚与硬件封装;见宝协议 cond_config 改为 7 字节编解码,并接入产品 DP。 补充《温湿度风扇_固件需求规格书》,工程加入对应源文件。 .gitignore 忽略 WorkBuddy/Cursor 本地会话
133 lines
4.4 KiB
C
133 lines
4.4 KiB
C
/******************************************************************************
|
||
* @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);
|
||
}
|
||
}
|