Ver código fonte

修复bkp存储失败问题

Signed-off-by: hanyongwei <2043702190@qq.com>
dev1
hanyongwei 3 semanas atrás
pai
commit
f2e8d00daf
9 arquivos alterados com 1239 adições e 1217 exclusões
  1. +2
    -2
      app/main.c
  2. +1175
    -1176
      iar/plsr.dep
  3. +6
    -0
      modbus/modbus_rtu.c
  4. +2
    -3
      plsr/command/plsr_command.c
  5. +13
    -5
      plsr/param/plsr_param.c
  6. +13
    -8
      plsr/param/plsr_param.h
  7. +22
    -13
      plsr/plsr.c
  8. +6
    -5
      plsr/plsr.h
  9. +0
    -5
      plsr/run_control/plsr_run_control.c

+ 2
- 2
app/main.c Ver arquivo

@@ -97,8 +97,8 @@ int main(void)
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP); OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);


/* /*
* 参数块任务:Pend 信号量 → ApplyFromHold → PersistPoll
* 分帧写完后由 OnHoldWrite Post,尽快落盘,不堵在 PlsrTask 里
* 参数块任务:Pend → ApplyFromHold → SaveParamsFromHold → ExportToHold
* 分帧写完后由 OnHoldWrite Post;Save 落 BKP,Export 仅供读回钳位结果
*/ */
OSTaskCreateExt(PlsrParamBlockTask, OSTaskCreateExt(PlsrParamBlockTask,
NULL, NULL,


+ 1175
- 1176
iar/plsr.dep
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 6
- 0
modbus/modbus_rtu.c Ver arquivo

@@ -67,7 +67,13 @@ void ModbusSlaveTask(void *pArg)


(void)pArg; (void)pArg;


/*
* ModbusDataInit 会 memset 整个 g_hold_reg,冲掉 PlsrInit 里 PersistLoad/Export 的结果。
* 须立刻 Export:用已 Apply 的 s_cfg/s_seg 填回公共+段参数,供 FC03 读与后续 START。
* (监控区另由 PlsrPersistTickMonitor 每节拍从运行态回填。)
*/
ModbusDataInit(); ModbusDataInit();
PlsrParamBlockExportToHold();
ModbusPortInit(); ModbusPortInit();


while (1) while (1)


+ 2
- 3
plsr/command/plsr_command.c Ver arquivo

@@ -64,7 +64,6 @@ void PlsrCommandSetFault(uint16_t code)
{ {
s_fault = code; s_fault = code;
WriteHoldReg(PLSR_MON_ERR, code); WriteHoldReg(PLSR_MON_ERR, code);
PlsrPersistNotifyMonitorChanged();
} }


/** @brief 清故障(见 plsr_command.h) */ /** @brief 清故障(见 plsr_command.h) */
@@ -72,7 +71,6 @@ void PlsrCommandClearFault(void)
{ {
s_fault = PLSR_ERR_NONE; s_fault = PLSR_ERR_NONE;
WriteHoldReg(PLSR_MON_ERR, PLSR_ERR_NONE); WriteHoldReg(PLSR_MON_ERR, PLSR_ERR_NONE);
PlsrPersistNotifyMonitorChanged();
} }


/** @brief 读故障镜像(见 plsr_command.h) */ /** @brief 读故障镜像(见 plsr_command.h) */
@@ -147,7 +145,8 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
if (seg != (PlsrSeg_t *)0) if (seg != (PlsrSeg_t *)0)
{ {
seg->freq_hz = (int32_t)f; seg->freq_hz = (int32_t)f;
PlsrPersistNotifyCommonChanged(); /* 动态改频:段表 dirty,Poll 写入 BKPSRAM */
/* 运行中改频:立即只把该段频率双字写入 BKP,不等整包参数落盘 */
PlsrPersistSaveSegFreqToBkp(seg0, f);
} }


s_live_freq_hz = f; s_live_freq_hz = f;


+ 13
- 5
plsr/param/plsr_param.c Ver arquivo

@@ -15,7 +15,8 @@
* *
* 与其它模块关系 * 与其它模块关系
* Modbus FC10 应答路径调用 OnHoldWrite;Command START 也会同步 ApplyFromHold; * Modbus FC10 应答路径调用 OnHoldWrite;Command START 也会同步 ApplyFromHold;
* Persist 仅保存公共参数;段表每次由上位机全量下发。
* Persist:Apply 成功后 SaveParamsFromHold 整包落 BKP;运行中改频单独落频率双字;
* ExportToHold 只把钳位后的结构体摊回 hold(读回 / 抗 ModbusDataInit 清零),不负责写 BKP。
*/ */
#include "plsr_param.h" #include "plsr_param.h"
#include "plsr_persist.h" #include "plsr_persist.h"
@@ -283,13 +284,19 @@ uint8_t PlsrParamBlockApplyFromHold(void)
seg->jump_seg = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP)); seg->jump_seg = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP));
} }


PlsrPersistNotifyCommonChanged();
return 1U; return 1U;
} }


/** /**
* @brief 运行映像 → 全部相关保持寄存器(含未使用段槽位) * @brief 运行映像 → 全部相关保持寄存器(含未使用段槽位)
*
* @details 用途(与落 BKP 无关)
* 1. Apply 钳位后摊回 hold,使「读 PLC」与运行结构体一致;
* 2. ModbusDataInit() memset 清 hold 后,把已 Apply 的 s_cfg/s_seg 填回,
* 否则上位机读公共/段参数全 0,START 也会用空 hold 再次 Apply 冲掉结构体。
*
* @note 0x100F 保留字写 0;段表写满 PLSR_SEG_MAX 槽,避免读回脏数据 * @note 0x100F 保留字写 0;段表写满 PLSR_SEG_MAX 槽,避免读回脏数据
* @note 落 BKP 请用 PlsrPersistSaveParamsFromHold(读 hold 原值),不依赖本函数
*/ */
void PlsrParamBlockExportToHold(void) void PlsrParamBlockExportToHold(void)
{ {
@@ -406,8 +413,8 @@ void PlsrParamBlockInit(void)
* @brief 参数块任务(见 plsr_param.h) * @brief 参数块任务(见 plsr_param.h)
* *
* for(;;) 为 uC/OS 任务标准死循环: * for(;;) 为 uC/OS 任务标准死循环:
* OSSemPend 永久等待 → ApplyFromHold → 写 XFER_OK 并尽快 PersistPoll
* (不等 PlsrTask,缩短参数落盘延迟)
* OSSemPend → ApplyFromHold → SaveParamsFromHold → ExportToHold
* Save 用 hold 中上位机刚写入的值落 BKP;Export 仅把钳位结果摊回 hold 供读回
* Apply 失败则写 XFER_FAIL 与当前 recv 帧号。 * Apply 失败则写 XFER_FAIL 与当前 recv 帧号。
*/ */
void PlsrParamBlockTask(void *pArg) void PlsrParamBlockTask(void *pArg)
@@ -427,7 +434,8 @@ void PlsrParamBlockTask(void *pArg)
if (PlsrParamBlockApplyFromHold() != 0U) if (PlsrParamBlockApplyFromHold() != 0U)
{ {
PlsrParamSetXferStatus(PLSR_PARAM_XFER_OK, 0U); PlsrParamSetXferStatus(PLSR_PARAM_XFER_OK, 0U);
PlsrPersistPoll(); /* 分帧收齐后尽快落盘,不等 PlsrTask */
PlsrPersistSaveParamsFromHold(); /* hold 原值 → BKP(不依赖 Export) */
PlsrParamBlockExportToHold(); /* 钳位后映像 → hold,供 Modbus 读回 */
} }
else else
{ {


+ 13
- 8
plsr/param/plsr_param.h Ver arquivo

@@ -12,14 +12,15 @@
* - modbus_rtu / modbus_data :ReadHoldReg / WriteHoldReg * - modbus_rtu / modbus_data :ReadHoldReg / WriteHoldReg
* - plsr_command :启动前 ApplyFromHold;运行中写频改 s_seg[].freq_hz * - plsr_command :启动前 ApplyFromHold;运行中写频改 s_seg[].freq_hz
* - plsr_run_control :GetCfg / GetSeg / GetSegCount / GetStartSeg * - plsr_run_control :GetCfg / GetSeg / GetSegCount / GetStartSeg
* - plsr_persist :Apply 成功后 NotifyCommonChanged,落盘公共+段表+监控
* - PlsrParamBlockTask :独立 uC/OS 任务,等信号量后 Apply + PersistPoll
* - plsr_persist :Apply 成功后 SaveParamsFromHold;动态改频 SaveSegFreqToBkp
* - PlsrParamBlockTask :独立 uC/OS 任务,等信号量后 Apply + 整包落 BKP
* *
* 关键数据流 * 关键数据流
* 上位机写公共帧@0x1000 → OnHoldWrite 开传输 expect=1+N * 上位机写公共帧@0x1000 → OnHoldWrite 开传输 expect=1+N
* 上位机写段帧@0x1100+ → recv++;收齐 → OSSemPost * 上位机写段帧@0x1100+ → recv++;收齐 → OSSemPost
* ParamBlockTask → ApplyFromHold → 结构体更新 → PersistNotify → 状态 OK
* 上电:InitDefault → PersistLoad 覆盖公共+段表 → ExportToHold
* ParamBlockTask → ApplyFromHold → SaveParamsFromHold → ExportToHold → 状态 OK
* 上电:PersistLoad → ApplyFromHold → … ModbusDataInit 清 hold …
* → ExportToHold(填回参数)+ TickMonitor(填回监控)
* *
* 协议概要 * 协议概要
* - 公共帧:0x1000~0x1013(20 字),0x1009=段数 N,预期总帧=1+N * - 公共帧:0x1000~0x1013(20 字),0x1009=段数 N,预期总帧=1+N
@@ -194,7 +195,7 @@ uint16_t PlsrParamGetStartSeg(void);
void PlsrParamBlockInit(void); void PlsrParamBlockInit(void);


/** /**
* @brief 参数块任务:阻塞等信号量 → ApplyFromHold → 状态 OK/FAIL → PersistPoll
* @brief 参数块任务:阻塞等信号量 → ApplyFromHold → SaveParamsFromHold → ExportToHold
* @param pArg 未使用 * @param pArg 未使用
* @note for(;;) 死循环为 RTOS 任务常态;空循环体是错觉(花括号内有 Pend/Apply) * @note for(;;) 死循环为 RTOS 任务常态;空循环体是错觉(花括号内有 Pend/Apply)
*/ */
@@ -211,13 +212,17 @@ void PlsrParamBlockOnHoldWrite(uint16_t start_addr, uint16_t quantity);
/** /**
* @brief 保持寄存器 → s_cfg / s_seg * @brief 保持寄存器 → s_cfg / s_seg
* @return 1=成功(当前恒为 1;完整校验/故障码待扩展) * @return 1=成功(当前恒为 1;完整校验/故障码待扩展)
* @note 副作用:NotifyCommonChanged 标记 BKPSRAM 待存
* @note 成功后由 ParamBlockTask 调用 SaveParamsFromHold 整包落 BKP
*/ */
uint8_t PlsrParamBlockApplyFromHold(void); uint8_t PlsrParamBlockApplyFromHold(void);


/** /**
* @brief s_cfg / s_seg → 保持寄存器(供 0x03 读回)
* @note 调用时机:上电 Export、PlsrTask 首次延迟后再次 Export
* @brief s_cfg / s_seg → 保持寄存器(供 FC03 读回 / START 前 hold 有效)
* @note 调用时机:
* - ParamBlockTask:Apply+Save 之后,把钳位结果摊回 hold
* - ModbusDataInit 清 hold 之后立刻 Export
* - PlsrTask 首次延时后再 Export(双保险)
* @note 本函数不写 BKP;落盘用 SaveParamsFromHold
*/ */
void PlsrParamBlockExportToHold(void); void PlsrParamBlockExportToHold(void);




+ 22
- 13
plsr/plsr.c Ver arquivo

@@ -10,10 +10,11 @@
* 本文件仅依赖 plsr.h 及各子模块头文件,不被其它 plsr 模块反向引用。 * 本文件仅依赖 plsr.h 及各子模块头文件,不被其它 plsr 模块反向引用。
* *
* 关键数据流 * 关键数据流
* PlsrInit 顺序:Param 默认 → PersistLoad(BKP→hold) → ApplyFromHold →
* PlsrInit 顺序:PersistLoad(BKP→hold) → ApplyFromHold →
* PulseDriver → RunControl → RestoreRuntime → ExportToHold → * PulseDriver → RunControl → RestoreRuntime → ExportToHold →
* CommandInit → RestoreMonitor → PersistPoll
* PlsrTask 循环:TickMs → DebouncePoll → CommandPoll → PersistPoll → WakePend
* CommandInit → RestoreMonitor → TickMonitor
* (随后 ModbusDataInit 可能清 hold,须再 Export + TickMonitor)
* PlsrTask 循环:TickMs → DebouncePoll → CommandPoll → TickMonitor → WakePend
*/ */
#include "plsr.h" #include "plsr.h"
#include "plsr_pulse_driver.h" #include "plsr_pulse_driver.h"
@@ -26,20 +27,25 @@


/** /**
* @brief 子系统初始化(见 plsr.h) * @brief 子系统初始化(见 plsr.h)
*
* 顺序要点
* PersistLoad → Apply:BKP 进结构体;
* Export:先填 hold(随后 ModbusDataInit 仍可能清零,故任务里再 Export);
* RestoreRuntime / TickMonitor:累计脉冲进运行态并与 BKP 对齐。
*/ */
void PlsrInit(void) void PlsrInit(void)
{ {
//PlsrParamInitDefault(); //PlsrParamInitDefault();
PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */ PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */
(void)PlsrParamBlockApplyFromHold();
(void)PlsrParamBlockApplyFromHold(); /* hold → s_cfg / s_seg[] */
PlsrPulseDriverInit(); PlsrPulseDriverInit();
PlsrSignalIoInit(); PlsrSignalIoInit();
PlsrRunControlInit(); PlsrRunControlInit();
PlsrPersistRestoreRuntime(); /* 0x2000 累计 → run_control */
PlsrParamBlockExportToHold(); /* 运行映像与 hold 对齐,供 Modbus 读 */
PlsrPersistRestoreRuntime(); /* hold 0x2000 累计 → run_control(须在 DataInit 清 hold 前) */
PlsrParamBlockExportToHold(); /* 结构体 → hold;Modbus 清零后须再 Export */
PlsrCommandInit(); PlsrCommandInit();
PlsrPersistRestoreMonitor(); /* 恢复故障码;0x3000/运行态强制空闲 */ PlsrPersistRestoreMonitor(); /* 恢复故障码;0x3000/运行态强制空闲 */
PlsrPersistPoll(); /* 消费 Restore 置的 dirty */
PlsrPersistTickMonitor(); /* 监控区 hold+BKP 与运行态对齐 */
} }


/** /**
@@ -110,22 +116,25 @@ void PlsrTask(void *pArg)
while(1) while(1)
{ {
/* /*
* 首次进入:Modbus 从站上电常会清零保持寄存器。
* 延迟 ~300ms 后再 Export + CommandInit,避免默认映像被冲掉。
* 首次进入:ModbusSlaveTask 启动时 ModbusDataInit 会 memset(g_hold_reg)。
* 延迟让出 CPU 后再次 Export:把已从 BKP Apply 的运行映像摊回 hold,
* 否则读 PLC 公共/段为 0,START 的 ApplyFromHold 也会用空 hold 覆盖结构体。
* TickMonitor:清 hold 后立刻把累计等监控量刷回 hold+BKP。
*/ */
if (s_booted == 0U) if (s_booted == 0U)
{ {
OSTimeDly(30U); /* ~300ms @ 100Hz tick */
PlsrParamBlockExportToHold();
OSTimeDly(3U); /* ~30ms @ 100Hz tick;让出 CPU 给 Modbus 完成 DataInit */
PlsrParamBlockExportToHold(); /* 参数区 hold ← s_cfg/s_seg */
PlsrCommandInit(); PlsrCommandInit();
PlsrPersistRestoreMonitor(); /* 若仍有 pending;无则空操作 */
PlsrPersistRestoreMonitor();
PlsrPersistTickMonitor(); /* 监控区 hold+BKP ← 运行态 */
s_booted = 1U; s_booted = 1U;
} }


PlsrRunControlTickMs(); /* 优先:WAIT/换向到期立刻开表 */ PlsrRunControlTickMs(); /* 优先:WAIT/换向到期立刻开表 */
PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */ PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */
PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 */ PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 */
PlsrPersistPoll(); /* BKPSRAM:消费 dirty(累计脉冲限频落盘) */
PlsrPersistTickMonitor(); /* 监控区:运行态→hold→BKP(每 OS 节拍) */


/* /*
* 换向 / WAIT 时间:WakePend(0) 只等 TIM5 Post(墙钟≈设定 ms)。 * 换向 / WAIT 时间:WakePend(0) 只等 TIM5 Post(墙钟≈设定 ms)。


+ 6
- 5
plsr/plsr.h Ver arquivo

@@ -9,19 +9,20 @@
* *
* 与其它模块关系 * 与其它模块关系
* - plsr_param :运行参数映像(公共 + 段表),Modbus 保持寄存器 ↔ 结构体 * - plsr_param :运行参数映像(公共 + 段表),Modbus 保持寄存器 ↔ 结构体
* - plsr_persist :公共参数 Flash 掉电保存(不含段表
* - plsr_persist :BKPSRAM 掉电保存(公共+段表、动态频率、监控区
* - plsr_command :Modbus 监控区 0x2000~0x2006、控制区 0x3000 指令解析 * - plsr_command :Modbus 监控区 0x2000~0x2006、控制区 0x3000 指令解析
* - plsr_run_control:段状态机、等待策略、加减速执行、故障诊断 * - plsr_run_control:段状态机、等待策略、加减速执行、故障诊断
* - plsr_pulse_driver:TIM PWM 脉冲 + Y3 方向 GPIO * - plsr_pulse_driver:TIM PWM 脉冲 + Y3 方向 GPIO
* - plsr_signal_io :WAIT/EXT 外部输入、TIM5 延时 * - plsr_signal_io :WAIT/EXT 外部输入、TIM5 延时
* *
* 关键数据流 * 关键数据流
* 上电:PlsrInit → 默认参数 → Flash 覆盖公共参数 → 驱动/IO/运行控制初始化
* → 参数导出到保持寄存器 → 指令模块初始化
* 周期:PlsrTask → CommandPoll → PersistPoll → RunControlTickMs
* → WakePend(1)(TIM5 WAIT/ACT 到期 SemPost 可立刻唤醒)
* 上电:PlsrInit → PersistLoad(BKP→hold) → ApplyFromHold → 驱动/IO/RunControl
* → RestoreRuntime → ExportToHold → CommandInit → RestoreMonitor → TickMonitor
* →(ModbusDataInit 清 hold 后再次 Export + TickMonitor)
* 周期:PlsrTask TickMs Debounce → CommandPoll → TickMonitor → WakePend
* 脉冲:TIM UPDATE 中断 → PlsrOnPulseIsr → RunControl 计数 + 逐拍改频 * 脉冲:TIM UPDATE 中断 → PlsrOnPulseIsr → RunControl 计数 + 逐拍改频
* 启动:PlsrStart → RunControlStart → 段序/方向 + 曲线规划 + PWM 输出 * 启动:PlsrStart → RunControlStart → 段序/方向 + 曲线规划 + PWM 输出
* 写参:分帧收齐 → ParamBlockTask Apply → SaveParamsFromHold → ExportToHold
*/ */
#ifndef PLSR_H #ifndef PLSR_H
#define PLSR_H #define PLSR_H


+ 0
- 5
plsr/run_control/plsr_run_control.c Ver arquivo

@@ -54,7 +54,6 @@
#include "plsr_pulse_driver.h" #include "plsr_pulse_driver.h"
#include "plsr_command.h" #include "plsr_command.h"
#include "plsr_signal_io.h" #include "plsr_signal_io.h"
#include "plsr_persist.h"
#include "ucos_ii.h" #include "ucos_ii.h"
#include <stdint.h> #include <stdint.h>


@@ -1225,7 +1224,6 @@ static void PlsrRunControlFinishAll(void)
s_wait_expire_req = 0U; s_wait_expire_req = 0U;
s_act_time_ms = 0U; s_act_time_ms = 0U;
s_last_period_wait = 0U; s_last_period_wait = 0U;
PlsrPersistNotifyMonitorChanged(); /* 全部结束:落盘累计与空闲状态 */
} }


/** /**
@@ -1555,7 +1553,6 @@ void PlsrRunControlStop(void)
s_wait_expire_req = 0U;/*段后等待到期请求标志*/ s_wait_expire_req = 0U;/*段后等待到期请求标志*/
s_act_time_ms = 0U;/*本段 ACT 定时时长*/ s_act_time_ms = 0U;/*本段 ACT 定时时长*/
s_last_period_wait = 0U; s_last_period_wait = 0U;
PlsrPersistNotifyMonitorChanged(); /* 停机:立刻落盘累计/状态 */
} }


/** @brief 运行中改频(见 plsr_run_control.h) */ /** @brief 运行中改频(见 plsr_run_control.h) */
@@ -1735,7 +1732,6 @@ void PlsrRunControlOnPulseIsr(void)
{ {
s_acc_pulse--; s_acc_pulse--;
} }
PlsrPersistNotifyAccPulseDirty();


/* /*
* ACT 到期切段只在脉冲边界执行,避免半个 PWM 周期改段。 * ACT 到期切段只在脉冲边界执行,避免半个 PWM 周期改段。
@@ -1858,7 +1854,6 @@ void PlsrRunControlClearAccPulse(void)
s_acc_pulse = 0; s_acc_pulse = 0;
s_abs_origin = 0; s_abs_origin = 0;
s_abs_origin_locked = 0U; /* 下次 Start 重新锁定原点 */ s_abs_origin_locked = 0U; /* 下次 Start 重新锁定原点 */
PlsrPersistNotifyMonitorChanged();
} }


/** @brief 上电恢复累计(见 plsr_run_control.h) */ /** @brief 上电恢复累计(见 plsr_run_control.h) */


Carregando…
Cancelar
Salvar