1、修复CBR0寿命与31天记录落盘失败(比较缓冲128→256)
2、APP换灯直接写DP3,DP4本版忽略;上电用restore灌RAM;读/全量打包权威剩余秒数
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
/******************************************************************************
|
||||
* @file app_light_life.c
|
||||
* @brief 灯泡剩余寿命(规格书 13.2 节):实际吸合扣秒 / DP4 复位 /
|
||||
* 到期告警 / DP3 60s 节流上报 / 边沿立刻落盘
|
||||
* @brief 灯泡剩余寿命(规格书 13.2 节):实际吸合扣秒 / APP 写 DP3 /
|
||||
* 到期告警 / 60s 节流上报 / 边沿立刻落盘
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.09.08
|
||||
* @version V1.0.0
|
||||
* @version V1.0.1
|
||||
*
|
||||
* @note 扣秒与运行记录同口径:只看 app_relay_get_actual()==1(过零后已吸合)。
|
||||
* 上下文分工(避免 ISR 写 VM / 切 BLE):
|
||||
@@ -13,7 +13,7 @@
|
||||
* - loop(500ms 任务):60s 节流同步 gDevData.lighe_remain_time;
|
||||
* 边沿立刻同步 + 推导 gDevData.alarm_code + 立刻落盘。
|
||||
* BOARD_LIGHT_LIFE_ENABLE=0:不扣秒、不置到期告警;DP3 走 VM/默认
|
||||
* 值原样上报(规格书 0.4 条)。
|
||||
* 值原样上报(规格书 13.2 / 第 0 章第 8 条)。
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
@@ -54,8 +54,10 @@ static void life_sync_gdata(uint8_t immediate)
|
||||
gDevData.alarm_code = (s_life.remain == 0) ? 1 : 0;
|
||||
|
||||
if (immediate) {
|
||||
app_nvm_save_runrec(); /* 寿命随 runrec item 落盘(规格书 13.2 边沿) */
|
||||
local_irq_disable();
|
||||
s_life.since_save = 0;
|
||||
local_irq_enable();
|
||||
app_nvm_save_runrec(); /* 寿命随 runrec item 落盘(规格书 13.2 边沿) */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -147,15 +149,19 @@ void app_light_life_loop(void)
|
||||
}
|
||||
|
||||
/* 平时落盘节奏:累计点灯满 600s 写一次(与运行记录同次可接受误差) */
|
||||
local_irq_disable();
|
||||
if (s_life.since_save >= BOARD_RUN_RECORD_SAVE_SEC) {
|
||||
s_life.since_save = 0;
|
||||
local_irq_enable();
|
||||
app_nvm_save_runrec();
|
||||
} else {
|
||||
local_irq_enable();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置剩余寿命(APP 写 DP3 / VM 恢复 / 出厂复位,任务上下文)
|
||||
* @brief 设置剩余寿命(APP 写 DP3 / 出厂复位,任务上下文)
|
||||
* @param remain 剩余寿命秒,0~0xFFFFFFFF 不封顶
|
||||
* @return 无
|
||||
*/
|
||||
@@ -165,6 +171,7 @@ void app_light_life_set_remain(uint32_t remain)
|
||||
local_irq_disable();
|
||||
s_life.remain = remain;
|
||||
s_life.since_sync = 0;
|
||||
s_life.since_save = 0;
|
||||
s_life.ms = 0;
|
||||
local_irq_enable();
|
||||
|
||||
@@ -172,19 +179,39 @@ void app_light_life_set_remain(uint32_t remain)
|
||||
gDevData.lighe_remain_time = remain;
|
||||
gDevData.alarm_code = (remain == 0) ? 1 : 0;
|
||||
app_nvm_save_runrec();
|
||||
s_life.since_save = 0;
|
||||
log_info("life set remain=%lu alarm=%d\n", (unsigned long)remain, gDevData.alarm_code);
|
||||
#else
|
||||
/* 模块关闭:仅按值回填(VM/默认原样上报,不扣秒不置告警,规格书 0.4) */
|
||||
/* 模块关闭:只回填 DP3,不因寿命置告警(规格书 13.2) */
|
||||
gDevData.lighe_remain_time = remain;
|
||||
if (remain == 0) {
|
||||
gDevData.alarm_code = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 灯泡复位(DP4 写 1 / 出厂复位):回额定值、告警清 0
|
||||
* @brief 上电从 VM 灌回剩余寿命(只改 RAM,不写 flash)
|
||||
* @param remain VM 中的剩余寿命秒
|
||||
* @return 无
|
||||
*/
|
||||
void app_light_life_restore(uint32_t remain)
|
||||
{
|
||||
#if BOARD_LIGHT_LIFE_ENABLE
|
||||
local_irq_disable();
|
||||
s_life.remain = remain;
|
||||
s_life.since_sync = 0;
|
||||
s_life.since_save = 0;
|
||||
s_life.ms = 0;
|
||||
s_life.need_sync = 0;
|
||||
s_life.need_edge = 0;
|
||||
local_irq_enable();
|
||||
gDevData.lighe_remain_time = remain;
|
||||
gDevData.alarm_code = (remain == 0) ? 1 : 0;
|
||||
log_info("life restore remain=%lu alarm=%d\n", (unsigned long)remain, gDevData.alarm_code);
|
||||
#else
|
||||
gDevData.lighe_remain_time = remain;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 寿命回到额定值(仅出厂复位 DP26 调用;APP 换灯请写 DP3)
|
||||
* @return 无
|
||||
*/
|
||||
void app_light_life_reset(void)
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
/******************************************************************************
|
||||
* @file app_light_life.h
|
||||
* @brief 灯泡剩余寿命(规格书 13.2 节,DP2/DP3/DP4/DP25)
|
||||
* @brief 灯泡剩余寿命(规格书 13.2 节,DP2/DP3/DP25;DP4 本版不用)
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.09.08
|
||||
* @version V1.0.0
|
||||
* @version V1.0.1
|
||||
*
|
||||
* @note 额定工时 2592000s(30 天),按继电器**实际吸合**每秒扣 1;
|
||||
* 扣到 0 停住不回绕,置 alarm_code=1(灯泡到期告警,粘住)但**不互锁**,
|
||||
* 灯仍可手动/定时/联动再开(第 12 章仲裁不参与)。
|
||||
* DP3 上报节流:平时满 60s 才同步一次 gDevData(协议层 2s 防抖后
|
||||
* 自然最多 60s 一包);到期 / DP4 / APP 写 DP3 / 出厂复位走边沿
|
||||
* **立刻**同步 + 落盘(任务上下文,禁止 ISR 写 VM)。
|
||||
* 剩余寿命持久化随运行记录 item(与 runrec 同写节奏 600s,边沿立刻)。
|
||||
* APP 换灯:直接写 DP3(通常写 2592000),不走 DP4。
|
||||
* DP3 上报节流:平时满 60s 才同步一次 gDevData;到期 / APP 写 DP3 /
|
||||
* 出厂复位走边沿立刻同步 + 落盘(任务上下文,禁止 ISR 写 VM)。
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __APP_LIGHT_LIFE_H__
|
||||
@@ -21,7 +20,7 @@
|
||||
|
||||
/**
|
||||
* @brief 初始化剩余寿命:RAM 复位为额定值,告警按值推导
|
||||
* @note 之后 app_nvm_load 若 VM 有效会调 app_light_life_set_remain 覆盖
|
||||
* @note 之后 app_nvm_load 若 VM 有效会调 app_light_life_restore 覆盖
|
||||
* @return 无
|
||||
*/
|
||||
void app_light_life_init(void);
|
||||
@@ -41,17 +40,25 @@ void app_light_life_tick(uint16_t dt);
|
||||
void app_light_life_loop(void);
|
||||
|
||||
/**
|
||||
* @brief 设置剩余寿命(APP 写 DP3 / VM 恢复 / 出厂复位共用,任务上下文)
|
||||
* @brief 设置剩余寿命(APP 写 DP3 / 出厂复位,任务上下文)
|
||||
* @param remain 剩余寿命秒,范围 0~0xFFFFFFFF 不封顶
|
||||
* @note 立刻生效:同步 gDevData + 推导 alarm_code + 立刻落盘 + 变化上报由
|
||||
* 协议层差分自动发出(2s 防抖后);remain>0 清到期告警,=0 置告警
|
||||
* @note 立刻生效:同步 gDevData + 推导 alarm_code + 立刻落盘;
|
||||
* remain>0 清到期告警,=0 置告警。上电灌 VM 请用 restore。
|
||||
* APP 换灯:写 DP3=2592000,不要写 DP4。
|
||||
* @return 无
|
||||
*/
|
||||
void app_light_life_set_remain(uint32_t remain);
|
||||
|
||||
/**
|
||||
* @brief 灯泡复位(DP4 写 1):剩余寿命回到额定值、告警清 0
|
||||
* @note WO 不上报;由 jb_product DP4 调用;边沿立刻落盘
|
||||
* @brief 上电从 VM 恢复剩余寿命(只改 RAM,不写 flash)
|
||||
* @param remain VM 中的剩余寿命秒
|
||||
* @return 无
|
||||
*/
|
||||
void app_light_life_restore(uint32_t remain);
|
||||
|
||||
/**
|
||||
* @brief 寿命回到额定值(仅出厂复位内部调用)
|
||||
* @note APP 换灯请写 DP3,本函数不接 DP4
|
||||
* @return 无
|
||||
*/
|
||||
void app_light_life_reset(void);
|
||||
|
||||
+20
-21
@@ -1,25 +1,20 @@
|
||||
/******************************************************************************
|
||||
* @file app_nvm.c
|
||||
* @brief CBR0 VM 持久化:heat_switch / linkage 20B / time_en /
|
||||
* time_config1~7 / run_record 31天 / fault_en / alarm_en
|
||||
* time_config1~7 / run_record 31天 / 剩余寿命 / fault_en / alarm_en
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.09.04
|
||||
* @version V1.1.0
|
||||
* @date 2026.09.08
|
||||
* @version V1.2.0
|
||||
* @history
|
||||
* - V1.2.0, 2026.09.08, cyWu, runrec item 含寿命 132B,比较缓冲改为 256
|
||||
* - V1.1.0, 2026.09.04, cyWu, P1 完整实现(4 item 存取 + 加热请求恢复)
|
||||
* - V1.0.0, 2026.09.04, cyWu, P0 空骨架
|
||||
*
|
||||
* @note VM item 分配在 syscfg 用户自定义区 [1~49](syscfg_id.h 已占用
|
||||
* CFG_USER_PAIR_INFO=2 / TIM_FLAG=3 / VM_ALARM*=4~24 /
|
||||
* DEVICE_STA=25 / PLAN_INFO1=26 / BATTERY_LEVEL=27),
|
||||
* 本产品从 28 开始:
|
||||
* CFG_USER_CBR0_STATE =28 状态(magic+ver+灯泡开关+使能,9B)
|
||||
* CFG_USER_CBR0_LINKAGE =29 联动配置 linkage_config(20B,P2 写)
|
||||
* CFG_USER_CBR0_TIME =30 定时配置 time_config[7][11](77B)
|
||||
* CFG_USER_CBR0_RUNREC =31 运行记录 31×uint32 + slot0 日期 +
|
||||
* 灯泡剩余寿命(132B,13.2 随 runrec 同写)
|
||||
* 拆 4 个 item:改灯开关只擦写 9B 小 item,不重写配置区,减少 flash
|
||||
* 磨损;首次上电(magic/ver 不符)保持 gDevData 全 0 默认。
|
||||
* @note VM item 从 28 起:STATE=28(10B)LINKAGE=29(20B)
|
||||
* TIME=30(77B)RUNREC=31(124B 秒数 + 4B 日期 + 4B 寿命 = 132B)。
|
||||
* 比较缓冲必须 ≥ 最大 item;加热垫是 128B,灯罩寿命多 4B,必须 256。
|
||||
* 首次上电 magic 无效:开关/定时/记录为 0,剩余寿命由
|
||||
* app_light_life_init 置额定 2,592,000(不是全 0)。
|
||||
*
|
||||
* 落盘基准 = 灯泡**请求**(app_relay_get_request,规格书 13 章"上次
|
||||
* 灯泡开关请求"),不是实际吸合态;上电按它恢复请求、等过零再吸合。
|
||||
@@ -58,6 +53,7 @@
|
||||
#define CBR0_VM_MAGIC 0xCB00
|
||||
#define CBR0_VM_VER 1
|
||||
#define CBR0_VM_DEBOUNCE_MS 500 /* 灯泡/使能稳定变化防抖(规格书 13 章) */
|
||||
#define CBR0_VM_CMP_BUF_LEN 256 /* ≥ RUNREC 132B;加热垫 128 会把本 item 静默丢掉 */
|
||||
|
||||
/** 状态 item(10 字节) */
|
||||
typedef struct {
|
||||
@@ -87,6 +83,8 @@ typedef struct {
|
||||
uint32_t lighe_remain_time; /**< 灯泡剩余寿命(随 runrec 同写节奏,13.2) */
|
||||
} __packed Cbr0RunrecVm_t;
|
||||
|
||||
typedef char cbr0_runrec_vm_fits[(sizeof(Cbr0RunrecVm_t) <= CBR0_VM_CMP_BUF_LEN) ? 1 : -1];
|
||||
|
||||
#if BOARD_NVM_ENABLE
|
||||
/** NVM 运行时:防抖落盘 + 已落盘状态快照(变化检测基准) */
|
||||
typedef struct {
|
||||
@@ -122,13 +120,13 @@ static void nvm_collect_time(Cbr0TimeVm_t *out)
|
||||
* @brief 写单个 item:先读回比较,内容相同跳过,避免无谓擦写 flash
|
||||
* @param item_id VM item id
|
||||
* @param buf 新数据
|
||||
* @param len 数据长度(≤128,比较缓冲大小)
|
||||
* @param len 数据长度(≤CBR0_VM_CMP_BUF_LEN)
|
||||
* @return 无
|
||||
*/
|
||||
static void nvm_write_item(u16 item_id, void *buf, u16 len)
|
||||
{
|
||||
/* static:比较缓冲不放栈上(省 128B 栈);本函数只在任务上下文调用,无重入 */
|
||||
static uint8_t old[128];
|
||||
/* static:比较缓冲不放栈上;只在任务上下文调用,无重入 */
|
||||
static uint8_t old[CBR0_VM_CMP_BUF_LEN];
|
||||
|
||||
if (len > sizeof(old)) {
|
||||
log_error("nvm item %d len %d too big\n", item_id, len);
|
||||
@@ -275,7 +273,8 @@ void app_nvm_save_runrec(void)
|
||||
/**
|
||||
* @brief 从 VM 加载并应用(开机由 usr_jb_init 调用)
|
||||
* @note 加热恢复 = 按上次**请求**恢复(等过零吸合,规格书 13 章 / 5.1);
|
||||
* 联动/定时/运行记录回填 gDevData。VM 无效(首次上电)保持全 0 默认。
|
||||
* 联动/定时/运行记录回填 gDevData。VM 无效时开关/定时/记录保持 0,
|
||||
* 剩余寿命保持 init 的额定值。
|
||||
* @return 无
|
||||
*/
|
||||
void app_nvm_load(void)
|
||||
@@ -316,8 +315,8 @@ void app_nvm_load(void)
|
||||
if (syscfg_read(CFG_USER_CBR0_RUNREC, &rf, sizeof(rf)) == (int)sizeof(rf)) {
|
||||
app_runrec_unpack(rf.run_record);
|
||||
app_runrec_set_slot0_date(rf.slot0_date);
|
||||
/* 灯泡剩余寿命覆盖 RAM 默认额定值(13.2;值相同不擦写 flash) */
|
||||
app_light_life_set_remain(rf.lighe_remain_time);
|
||||
/* 只灌 RAM,禁止走 set_remain(那会立刻再写 flash) */
|
||||
app_light_life_restore(rf.lighe_remain_time);
|
||||
}
|
||||
|
||||
gDevData.time_en = st.time_en ? 1 : 0;
|
||||
@@ -338,7 +337,7 @@ void app_nvm_load(void)
|
||||
* @note ⚠ 本函数跑在 usr_timer_add 的 20ms 回调里 = **硬件定时器中断上下文**
|
||||
* (异步接口,栈极小)。这里只允许做轻量比较与计时;真正的
|
||||
* syscfg_write 由 app_nvm_flush() 在 usr_timer_loop(任务上下文)执行。
|
||||
* 曾在此直接调 app_nvm_save 导致栈溢出软复位。
|
||||
* 禁止在此调 syscfg_write(中断栈不够)。
|
||||
* @return 无
|
||||
*/
|
||||
void app_nvm_tick(uint16_t dt)
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
* time_en / time_config1~7(11B) / run_record(31×uint32+日期+寿命) /
|
||||
* fault_en / alarm_en(规格书第 13 章)
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.09.04
|
||||
* @version V1.1.0,P0 = 空骨架(BOARD_NVM_ENABLE=0)
|
||||
* @date 2026.09.08
|
||||
* @version V1.2.0
|
||||
*
|
||||
* @note 存:灯泡开关(DP0)、linkage_config(20B, DP11)、time_en(DP12)、
|
||||
* time_config1~7(11B, DP13~19)、run_record(DP20:31×uint32 +
|
||||
* slot0 日期 + 灯泡剩余寿命 DP3)、fault_en(DP22)、alarm_en(DP24)。
|
||||
* 不存:DP1–6(温控/模式等易失)、DP9 当前温度(WO)、联动作废标志、
|
||||
* 不存:DP1/DP2/DP5–8(温控/模式等易失)、DP9 当前温度(WO)、联动作废标志、
|
||||
* 过零 pending、linkage_delete(DP10 脉冲)、BLE 三元组(出厂不清)。
|
||||
* 写 VM 时机:APP 改配置后(500ms 防抖);运行记录每累计 600s 一次、
|
||||
* 跨天旋转立刻写;寿命随 runrec 同写(到期/复位/写 DP3 边沿立刻)。
|
||||
@@ -70,7 +70,7 @@ void app_nvm_tick(uint16_t dt);
|
||||
void app_nvm_flush(void);
|
||||
|
||||
/**
|
||||
* @brief 标记业务字段有变化,防抖计时归零(档位/模式/配置变化时调用)
|
||||
* @brief 标记业务字段有变化,防抖计时归零(定时/使能/故障告警使能变化时调用)
|
||||
* @return 无
|
||||
*/
|
||||
void app_nvm_mark_dirty(void);
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ typedef enum {
|
||||
|
||||
/**
|
||||
* 优先级:高者覆盖低者(handler 返回 1 会拦下更低优先级)。
|
||||
* 加热垫红绿互斥:HEAT 只占最低槽,配对/结果/OTA 事件添加前先全清灯,
|
||||
* 加热灯罩红绿互斥:HEAT 只占最低槽,配对/结果/OTA 事件添加前先全清灯,
|
||||
* 结束后 app_led_run 按继电器实际态自动重新挂 HEAT(无需显式恢复)。
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
Reference in New Issue
Block a user