5 Комити

Аутор SHA1 Порука Датум
  ywh c134491907 标记了未完成项 пре 1 месец
  ywh d2ab7d6c0a 修复了变频后计数不准的问题 пре 1 месец
  ywh f4a2216504 变频代码 пре 1 месец
  ywh a81228b629 加入EXT信号 пре 1 месец
  ywh ec2aa94775 修复EXT 硬件 pending 竞态 пре 1 месец
7 измењених фајлова са 1152 додато и 142 уклоњено
  1. BIN
      Document/PLSR_document/更新的需求/实现PLSR指令(2026) - 需求明确版.pdf
  2. +505
    -21
      EWARM/Modbus.ewp
  3. BIN
      HostComputer/__pycache__/bin_to_time_freq.cpython-314.pyc
  4. +33
    -12
      HostComputer/bin_to_time_freq.py
  5. +403
    -51
      PLSR/Src/plsr.c
  6. +6
    -1
      PLSR/Src/plsr_platform.h
  7. +205
    -57
      PLSR/Src/plsr_platform_f407.c

BIN
Document/PLSR_document/更新的需求/实现PLSR指令(2026) - 需求明确版.pdf Прегледај датотеку


+ 505
- 21
EWARM/Modbus.ewp Прегледај датотеку

@@ -1263,22 +1263,16 @@
</group>
</group>
<group>
<name>PLSR</name>
<file>
<name>$PROJ_DIR$\..\PLSR\Inc\plsr.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_internal.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_platform.h</name>
</file>
<name>Modbus</name>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.h</name>
<name>$PROJ_DIR$\..\Modbus\Src\modbus_rtu_slave.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.c</name>
<name>$PROJ_DIR$\..\Modbus\Inc\modbus_rtu_slave.h</name>
</file>
</group>
<group>
<name>PLSR</name>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr.c</name>
<configuration>
@@ -1289,6 +1283,248 @@
<version>35</version>
<wantNonLocal>0</wantNonLocal>
<debug>1</debug>
<option>
<name>CCOptimizationNoSizeConstraints</name>
<state>0</state>
</option>
<option>
<name>CCDefines</name>
<state>USE_HAL_DRIVER</state>
<state>STM32F407xx</state>
<state>PLSR_DEBUG_TIMING=1</state>
</option>
<option>
<name>CCPreprocFile</name>
<state>0</state>
</option>
<option>
<name>CCPreprocComments</name>
<state>0</state>
</option>
<option>
<name>CCPreprocLine</name>
<state>0</state>
</option>
<option>
<name>CCListCFile</name>
<state>0</state>
</option>
<option>
<name>CCListCMnemonics</name>
<state>0</state>
</option>
<option>
<name>CCListCMessages</name>
<state>0</state>
</option>
<option>
<name>CCListAssFile</name>
<state>0</state>
</option>
<option>
<name>CCListAssSource</name>
<state>0</state>
</option>
<option>
<name>CCEnableRemarks</name>
<state>0</state>
</option>
<option>
<name>CCDiagSuppress</name>
<state></state>
</option>
<option>
<name>CCDiagRemark</name>
<state></state>
</option>
<option>
<name>CCDiagWarning</name>
<state></state>
</option>
<option>
<name>CCDiagError</name>
<state></state>
</option>
<option>
<name>CCObjPrefix</name>
<state>1</state>
</option>
<option>
<name>CCAllowList</name>
<version>1</version>
<state>11111110</state>
</option>
<option>
<name>CCDebugInfo</name>
<state>1</state>
</option>
<option>
<name>IEndianMode</name>
<state>1</state>
</option>
<option>
<name>IProcessor</name>
<state>1</state>
</option>
<option>
<name>IExtraOptionsCheck</name>
<state>0</state>
</option>
<option>
<name>IExtraOptions</name>
<state></state>
</option>
<option>
<name>CCLangConformance</name>
<state>0</state>
</option>
<option>
<name>CCSignedPlainChar</name>
<state>1</state>
</option>
<option>
<name>CCRequirePrototypes</name>
<state>0</state>
</option>
<option>
<name>CCDiagWarnAreErr</name>
<state>0</state>
</option>
<option>
<name>CCCompilerRuntimeInfo</name>
<state>0</state>
</option>
<option>
<name>IFpuProcessor</name>
<state>1</state>
</option>
<option>
<name>OutputFile</name>
<state>$FILE_BNAME$.o</state>
</option>
<option>
<name>CCLibConfigHeader</name>
<state>1</state>
</option>
<option>
<name>PreInclude</name>
<state></state>
</option>
<option>
<name>CompilerMisraOverride</name>
<state>0</state>
</option>
<option>
<name>CCIncludePath2</name>
<state>$PROJ_DIR$/../USB_DEVICE/App</state>
<state>$PROJ_DIR$/../USB_DEVICE/Target</state>
<state>$PROJ_DIR$/../Core/Inc</state>
<state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc</state>
<state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy</state>
<state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Inc</state>
<state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc</state>
<state>$PROJ_DIR$/../Drivers/CMSIS/Device/ST/STM32F4xx/Include</state>
<state>$PROJ_DIR$/../Drivers/CMSIS/Include</state>
<state>$PROJ_DIR$\..\Modbus\Inc</state>
<state>$PROJ_DIR$\..\PLSR\Inc</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU\ARM-Cortex-M4\IAR</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-LIB</state>
<state>$PROJ_DIR$\..\Modbus\Inc</state>
</option>
<option>
<name>CCStdIncCheck</name>
<state>0</state>
</option>
<option>
<name>CCCodeSection</name>
<state>.text</state>
</option>
<option>
<name>IProcessorMode2</name>
<state>1</state>
</option>
<option>
<name>CompilerMisraRules98</name>
<version>0</version>
<state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
</option>
<option>
<name>CompilerMisraRules04</name>
<version>0</version>
<state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
</option>
<option>
<name>CCPosIndRopi</name>
<state>0</state>
</option>
<option>
<name>CCPosIndRwpi</name>
<state>0</state>
</option>
<option>
<name>CCPosIndNoDynInit</name>
<state>0</state>
</option>
<option>
<name>IccLang</name>
<state>0</state>
</option>
<option>
<name>IccCDialect</name>
<state>1</state>
</option>
<option>
<name>IccAllowVLA</name>
<state>0</state>
</option>
<option>
<name>IccStaticDestr</name>
<state>1</state>
</option>
<option>
<name>IccCppInlineSemantics</name>
<state>0</state>
</option>
<option>
<name>IccCmsis</name>
<state>1</state>
</option>
<option>
<name>IccFloatSemantics</name>
<state>0</state>
</option>
<option>
<name>CCNoLiteralPool</name>
<state>0</state>
</option>
<option>
<name>CCEncSource</name>
<state>0</state>
</option>
<option>
<name>CCEncOutput</name>
<state>0</state>
</option>
<option>
<name>CCEncOutputBom</name>
<state>1</state>
</option>
<option>
<name>CCEncInput</name>
<state>0</state>
</option>
<option>
<name>IccExceptions2</name>
<state>0</state>
</option>
<option>
<name>IccRTTI2</name>
<state>0</state>
</option>
<option>
<name>CCOptLevel</name>
<state>3</state>
@@ -1311,6 +1547,21 @@
</settings>
</configuration>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Inc\plsr.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_internal.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_platform.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\PLSR\Src\plsr_platform_f407.c</name>
<configuration>
@@ -1321,6 +1572,248 @@
<version>35</version>
<wantNonLocal>0</wantNonLocal>
<debug>1</debug>
<option>
<name>CCOptimizationNoSizeConstraints</name>
<state>0</state>
</option>
<option>
<name>CCDefines</name>
<state>USE_HAL_DRIVER</state>
<state>STM32F407xx</state>
<state>PLSR_DEBUG_TIMING=1</state>
</option>
<option>
<name>CCPreprocFile</name>
<state>0</state>
</option>
<option>
<name>CCPreprocComments</name>
<state>0</state>
</option>
<option>
<name>CCPreprocLine</name>
<state>0</state>
</option>
<option>
<name>CCListCFile</name>
<state>0</state>
</option>
<option>
<name>CCListCMnemonics</name>
<state>0</state>
</option>
<option>
<name>CCListCMessages</name>
<state>0</state>
</option>
<option>
<name>CCListAssFile</name>
<state>0</state>
</option>
<option>
<name>CCListAssSource</name>
<state>0</state>
</option>
<option>
<name>CCEnableRemarks</name>
<state>0</state>
</option>
<option>
<name>CCDiagSuppress</name>
<state></state>
</option>
<option>
<name>CCDiagRemark</name>
<state></state>
</option>
<option>
<name>CCDiagWarning</name>
<state></state>
</option>
<option>
<name>CCDiagError</name>
<state></state>
</option>
<option>
<name>CCObjPrefix</name>
<state>1</state>
</option>
<option>
<name>CCAllowList</name>
<version>1</version>
<state>11111110</state>
</option>
<option>
<name>CCDebugInfo</name>
<state>1</state>
</option>
<option>
<name>IEndianMode</name>
<state>1</state>
</option>
<option>
<name>IProcessor</name>
<state>1</state>
</option>
<option>
<name>IExtraOptionsCheck</name>
<state>0</state>
</option>
<option>
<name>IExtraOptions</name>
<state></state>
</option>
<option>
<name>CCLangConformance</name>
<state>0</state>
</option>
<option>
<name>CCSignedPlainChar</name>
<state>1</state>
</option>
<option>
<name>CCRequirePrototypes</name>
<state>0</state>
</option>
<option>
<name>CCDiagWarnAreErr</name>
<state>0</state>
</option>
<option>
<name>CCCompilerRuntimeInfo</name>
<state>0</state>
</option>
<option>
<name>IFpuProcessor</name>
<state>1</state>
</option>
<option>
<name>OutputFile</name>
<state>$FILE_BNAME$.o</state>
</option>
<option>
<name>CCLibConfigHeader</name>
<state>1</state>
</option>
<option>
<name>PreInclude</name>
<state></state>
</option>
<option>
<name>CompilerMisraOverride</name>
<state>0</state>
</option>
<option>
<name>CCIncludePath2</name>
<state>$PROJ_DIR$/../USB_DEVICE/App</state>
<state>$PROJ_DIR$/../USB_DEVICE/Target</state>
<state>$PROJ_DIR$/../Core/Inc</state>
<state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc</state>
<state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy</state>
<state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Inc</state>
<state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc</state>
<state>$PROJ_DIR$/../Drivers/CMSIS/Device/ST/STM32F4xx/Include</state>
<state>$PROJ_DIR$/../Drivers/CMSIS/Include</state>
<state>$PROJ_DIR$\..\Modbus\Inc</state>
<state>$PROJ_DIR$\..\PLSR\Inc</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU\ARM-Cortex-M4\IAR</state>
<state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-LIB</state>
<state>$PROJ_DIR$\..\Modbus\Inc</state>
</option>
<option>
<name>CCStdIncCheck</name>
<state>0</state>
</option>
<option>
<name>CCCodeSection</name>
<state>.text</state>
</option>
<option>
<name>IProcessorMode2</name>
<state>1</state>
</option>
<option>
<name>CompilerMisraRules98</name>
<version>0</version>
<state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
</option>
<option>
<name>CompilerMisraRules04</name>
<version>0</version>
<state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
</option>
<option>
<name>CCPosIndRopi</name>
<state>0</state>
</option>
<option>
<name>CCPosIndRwpi</name>
<state>0</state>
</option>
<option>
<name>CCPosIndNoDynInit</name>
<state>0</state>
</option>
<option>
<name>IccLang</name>
<state>0</state>
</option>
<option>
<name>IccCDialect</name>
<state>1</state>
</option>
<option>
<name>IccAllowVLA</name>
<state>0</state>
</option>
<option>
<name>IccStaticDestr</name>
<state>1</state>
</option>
<option>
<name>IccCppInlineSemantics</name>
<state>0</state>
</option>
<option>
<name>IccCmsis</name>
<state>1</state>
</option>
<option>
<name>IccFloatSemantics</name>
<state>0</state>
</option>
<option>
<name>CCNoLiteralPool</name>
<state>0</state>
</option>
<option>
<name>CCEncSource</name>
<state>0</state>
</option>
<option>
<name>CCEncOutput</name>
<state>0</state>
</option>
<option>
<name>CCEncOutputBom</name>
<state>1</state>
</option>
<option>
<name>CCEncInput</name>
<state>0</state>
</option>
<option>
<name>IccExceptions2</name>
<state>0</state>
</option>
<option>
<name>IccRTTI2</name>
<state>0</state>
</option>
<option>
<name>CCOptLevel</name>
<state>3</state>
@@ -1344,13 +1837,4 @@
</configuration>
</file>
</group>
<group>
<name>Modbus</name>
<file>
<name>$PROJ_DIR$\..\Modbus\Src\modbus_rtu_slave.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\Modbus\Inc\modbus_rtu_slave.h</name>
</file>
</group>
</project>

BIN
HostComputer/__pycache__/bin_to_time_freq.cpython-314.pyc Прегледај датотеку


+ 33
- 12
HostComputer/bin_to_time_freq.py Прегледај датотеку

@@ -111,8 +111,12 @@ def plot_show(path, fs, thresh, ymax, save_path=None):
fig, ax = plt.subplots(figsize=(15, 7))
fig.subplots_adjust(bottom=0.10, top=0.92)

# 全脉冲散点
ax.plot(t * 1000, freq, '.', ms=1.5, color='C0', alpha=0.5, zorder=1)
# 全脉冲散点:复用 artist,重绘时按可见范围抽稀(大文件流畅)
MAX_VISIBLE_POINTS = 5000 # 可见范围内最多绘制的点数,超过则等间隔抽稀
(scatter,) = ax.plot([], [], '.', ms=1.5, color='C0', alpha=0.5, zorder=1)
tx_ms = t * 1000
x_full = tx_ms
y_full = freq
ax.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02)
ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08)
ax.set_title("%s 时频曲线(%d 脉冲,活动时长 %.0f ms)" % (
@@ -145,6 +149,19 @@ def plot_show(path, fs, thresh, ymax, save_path=None):
zorder=6, visible=False)
hover_last = {'idx': -1, 'visible': False}

# 可见范围内抽稀绘制散点(大文件性能优化)
def update_scatter():
x0, x1 = ax.get_xlim()
mask = (x_full >= x0) & (x_full <= x1)
n_vis = int(np.count_nonzero(mask))
if n_vis > MAX_VISIBLE_POINTS:
# 等间隔抽稀:取 n_vis 中的 MAX_VISIBLE_POINTS 个
step = (n_vis + MAX_VISIBLE_POINTS - 1) // MAX_VISIBLE_POINTS
idx = np.flatnonzero(mask)[::step]
else:
idx = np.flatnonzero(mask)
scatter.set_data(x_full[idx], y_full[idx])

def on_scroll(event):
if event.inaxes is not ax or event.xdata is None:
return
@@ -167,6 +184,7 @@ def plot_show(path, fs, thresh, ymax, save_path=None):
if n1 - n0 < 1e-6:
return
ax.set_xlim(n0, n1)
update_scatter()
fig.canvas.draw_idle()

def on_press(event):
@@ -187,28 +205,29 @@ def plot_show(path, fs, thresh, ymax, save_path=None):
dy = event.ydata - state['press_y']
ax.set_xlim(x0 - dx, x1 - dx)
ax.set_ylim(y0 - dy, y1 - dy)
update_scatter()
fig.canvas.draw_idle()
return
# 悬停:找可见范围内距鼠标最近的脉冲点(屏幕像素距离 < 20px 才高亮)
x0, x1 = ax.get_xlim()
tx_ms = t * 1000
mask = (tx_ms >= x0) & (tx_ms <= x1)
mask = (x_full >= x0) & (x_full <= x1)
if not np.any(mask):
hl_marker.set_visible(False)
hl_text.set_visible(False)
if hover_last['visible']:
hl_marker.set_visible(False)
hl_text.set_visible(False)
fig.canvas.draw_idle()
hover_last['visible'] = False
fig.canvas.draw_idle()
return
px, py = ax.transData.transform(np.column_stack([tx_ms[mask], freq[mask]])).T
px, py = ax.transData.transform(np.column_stack([x_full[mask], y_full[mask]])).T
dist = np.hypot(px - event.x, py - event.y)
k = int(np.argmin(dist))
if dist[k] <= 20.0:
idx = int(np.flatnonzero(mask)[k])
hl_marker.set_data([tx_ms[idx]], [freq[idx]])
hl_marker.set_data([x_full[idx]], [y_full[idx]])
hl_text.set_text("脉冲 #%d\nt = %.3f ms\nf = %.0f Hz"
% (idx + 1, tx_ms[idx], freq[idx]))
hl_text.set_position((tx_ms[idx] + (x1 - x0) * 0.01,
freq[idx] + (ax.get_ylim()[1] - ax.get_ylim()[0]) * 0.02))
% (idx + 1, x_full[idx], y_full[idx]))
hl_text.set_position((x_full[idx] + (x1 - x0) * 0.01,
y_full[idx] + (ax.get_ylim()[1] - ax.get_ylim()[0]) * 0.02))
hl_marker.set_visible(True)
hl_text.set_visible(True)
if hover_last['idx'] != idx or not hover_last['visible']:
@@ -229,8 +248,10 @@ def plot_show(path, fs, thresh, ymax, save_path=None):
if event.dblclick:
ax.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02)
ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08)
update_scatter()
fig.canvas.draw_idle()

update_scatter()
fig.canvas.mpl_connect('scroll_event', on_scroll)
fig.canvas.mpl_connect('button_press_event', on_press)
fig.canvas.mpl_connect('button_release_event', on_release)


+ 403
- 51
PLSR/Src/plsr.c
Разлика између датотеке није приказан због своје велике величине
Прегледај датотеку


+ 6
- 1
PLSR/Src/plsr_platform.h Прегледај датотеку

@@ -93,7 +93,9 @@ uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput);
uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput,
uint32_t *activeFrequencyHz);
uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput,
uint64_t *observedPulses,
uint32_t *committedPulses,
uint64_t *committedTimeUs,
uint32_t *tailFrequencyHz,
uint8_t *startsNextSegment);
uint8_t PlsrPlatformFiniteProgress(uint8_t pulseOutput,
@@ -118,7 +120,7 @@ uint8_t PlsrExecTakeCountedRunIrq(
void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput,
uint32_t completedPulses);
void PlsrExecCountedStreamFaultIrq(uint8_t pulseOutput);
/* EXTI callback: records only an armed WAIT input edge. */
/* EXTI callback: records an armed WAIT or active EXT input edge. */
void PlsrWaitInputExtiIrq(uint8_t inputSelection);
PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformLoadPreparedFromIrq(
uint8_t pulseOutput,
@@ -145,6 +147,9 @@ PLSR_PLATFORM_STOP_RESULT PlsrPlatformRequestStopLocked(
uint8_t PlsrPlatformQueueFinalArmFromIrq(uint8_t pulseOutput);
void PlsrPlatformStopPulse(uint8_t pulseOutput);
uint8_t PlsrPlatformReadInput(uint8_t inputSelection);
/* Called from the counted-boundary IRQ before the EXT capture context moves
to the next segment. Returns and clears a rising edge pending in EXTI. */
uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection);

uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload);
PLSR_PLATFORM_SERVICE_RESULT PlsrPlatformServicePersistence(void);


+ 205
- 57
PLSR/Src/plsr_platform_f407.c Прегледај датотеку

@@ -551,22 +551,35 @@ uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput,
}

uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput,
uint64_t *observedPulses,
uint32_t *committedPulses,
uint64_t *committedTimeUs,
uint32_t *tailFrequencyHz,
uint8_t *startsNextSegment)
{
uint32_t remaining;
uint32_t frequencyHz;

if ((pulseOutput > 3U) || (committedPulses == NULL)
|| (tailFrequencyHz == NULL) || (startsNextSegment == NULL)
if ((pulseOutput > 3U) || (observedPulses == NULL)
|| (committedPulses == NULL)
|| (committedTimeUs == NULL) || (tailFrequencyHz == NULL)
|| (startsNextSegment == NULL)
|| (PlsrHostFiniteActive[pulseOutput] == 0U))
{
return 0U;
}
remaining = PlsrHostFiniteTarget[pulseOutput]
- PlsrHostFiniteEmitted[pulseOutput];
frequencyHz = PlsrHostFrequency[pulseOutput];
if (frequencyHz == 0UL)
{
return 0U;
}
*observedPulses = PlsrHostObservedPulses[pulseOutput];
*committedPulses = remaining;
*tailFrequencyHz = PlsrHostQueuedFrequency[pulseOutput];
*committedTimeUs = ((uint64_t)remaining * 1000000ULL
+ frequencyHz - 1UL) / frequencyHz;
*tailFrequencyHz = frequencyHz;
*startsNextSegment = 0U;
return 1U;
}
@@ -893,6 +906,12 @@ uint8_t PlsrPlatformReadInput(uint8_t inputSelection)
return (inputSelection <= 1U) ? PlsrHostInputs[inputSelection] : 0U;
}

uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection)
{
(void)inputSelection;
return 0U;
}

uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload)
{
if ((payload == NULL) || (PlsrHostPersistentValid == 0U))
@@ -1574,8 +1593,8 @@ static void PlsrFiniteArmNextStepPrepare(uint8_t pulseOutput,
TIM_TypeDef *counter,
uint32_t blockPulses);
static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput);
static void PlsrFiniteCutAtFallingEdge(uint8_t pulseOutput);
static void PlsrFiniteStopAtFallingEdge(uint8_t pulseOutput);
static void PlsrFiniteCutAtIdleBoundary(uint8_t pulseOutput);
static void PlsrFiniteStopAtIdleBoundary(uint8_t pulseOutput);

static uint8_t PlsrFinalArmJobOutput(uint8_t pulseOutput)
{
@@ -2364,11 +2383,86 @@ static uint64_t PlsrCounterCurrentRaw(uint8_t pulseOutput)
}
}

/* Return completed pulses in the active PUL/DIR run. The one-pulse block
preload is an implementation detail, and a pending counter update means
the current block has completed even if its IRQ has not run yet. */
static uint32_t PlsrFiniteCompletedPulsesSnapshot(uint8_t pulseOutput)
{
uint8_t index = PlsrCounterIndexByOutput[pulseOutput];
TIM_TypeDef *counter;
uint32_t target;
uint32_t remainingBefore;
uint32_t remainingAfter;
uint32_t statusBefore;
uint32_t statusAfter;
uint32_t count;
uint32_t blockCount;
uint32_t completed;

if (index >= PLSR_COUNTER_COUNT)
{
return 0UL;
}
counter = PlsrCounters[index];
for (;;)
{
remainingBefore = PlsrFiniteRemainingPulses[pulseOutput];
statusBefore = counter->SR & TIM_SR_UIF;
count = (uint16_t)counter->CNT;
statusAfter = counter->SR & TIM_SR_UIF;
remainingAfter = PlsrFiniteRemainingPulses[pulseOutput];
if ((remainingBefore == remainingAfter)
&& (statusBefore == statusAfter))
{
break;
}
}

target = PlsrFiniteTargetPulses[pulseOutput];
if (remainingAfter > target)
{
return 0UL;
}
completed = target - remainingAfter;
if (statusAfter != 0UL)
{
blockCount = (remainingAfter > PLSR_COUNTER_BLOCK_PULSES)
? PLSR_COUNTER_BLOCK_PULSES : remainingAfter;
if (count > (remainingAfter - blockCount))
{
count = remainingAfter - blockCount;
}
blockCount += count;
}
else if (count >= PlsrFiniteCounterPreload[pulseOutput])
{
blockCount = count - PlsrFiniteCounterPreload[pulseOutput];
}
else
{
blockCount = 0UL;
}
if (blockCount > remainingAfter)
{
blockCount = remainingAfter;
}
return completed + blockCount;
}

static uint64_t PlsrCounterSnapshot(uint8_t pulseOutput)
{
uint64_t current = PlsrCounterCurrentRaw(pulseOutput);
uint64_t current;
uint64_t observed;

if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_PULSE_DIR)
&& (PlsrFiniteActive[pulseOutput] != 0U))
{
current = PlsrFiniteCompletedPulsesSnapshot(pulseOutput);
}
else
{
current = PlsrCounterCurrentRaw(pulseOutput);
}
if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_AB)
&& (current > 0UL))
{
@@ -3445,6 +3539,8 @@ uint8_t PlsrPlatformRetargetFiniteStop(uint8_t pulseOutput,
uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput)
{
TIM_TypeDef *timer;
uint32_t timerCompare;
uint32_t timerCount;
uint32_t criticalState;

if (pulseOutput > 3U)
@@ -3455,8 +3551,7 @@ uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput)
criticalState = PlsrPlatformEnterCritical();
if ((PlsrFiniteActive[pulseOutput] == 0U)
|| (PlsrFiniteStreamActive[pulseOutput] == 0U)
|| (PlsrCounterIndexByOutput[pulseOutput] >= PLSR_COUNTER_COUNT)
|| (PlsrFiniteRetargetPending[pulseOutput] != 0U))
|| (PlsrCounterIndexByOutput[pulseOutput] >= PLSR_COUNTER_COUNT))
{
PlsrPlatformExitCritical(criticalState);
return 0U;
@@ -3467,17 +3562,35 @@ uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput)
return 1U;
}

/* Do not allow a run already staged by the producer to cross the cut.
CC1 reaches the physical pulse's falling edge, where the output is
idle and can be stopped without shortening the high or low width. */
/* EXT supersedes an unpublished retarget and any producer-staged run. */
PlsrFiniteRetargetPending[pulseOutput] = 0U;
PlsrFiniteRetargetDrainPulses[pulseOutput] = 0UL;
PlsrFiniteStreamNextValid[pulseOutput] = 0U;
PlsrFiniteStreamNextStartsSegment[pulseOutput] = 0U;
PlsrFiniteStreamSourceDone[pulseOutput] = 1U;
PlsrFiniteStreamSourceFault[pulseOutput] = 0U;
PlsrFiniteTailStopPending[pulseOutput] = 1U;
timer = PlsrTimerMap[pulseOutput].timer;
timer->DIER &= ~TIM_DIER_CC1IE;
timer->SR = ~TIM_SR_CC1IF;
timer->DIER |= TIM_DIER_CC1IE;

/* PWM1 is idle high before CCR1 and active low after CCR1. Freeze the
source briefly so the phase decision cannot turn a full pulse into a
short glitch. A low pulse is resumed and allowed to finish at update. */
timer->CR1 &= ~TIM_CR1_CEN;
__DSB();
timerCount = timer->CNT;
timerCompare = PlsrTimerActiveSetting[pulseOutput].compare;
if (timerCount < timerCompare)
{
PlsrFiniteCutAtIdleBoundary(pulseOutput);
}
else
{
timer->SR = ~TIM_SR_UIF;
timer->DIER |= TIM_DIER_UIE;
timer->CR1 |= TIM_CR1_CEN;
}
__DMB();
PlsrPlatformExitCritical(criticalState);
return 1U;
@@ -3503,17 +3616,23 @@ uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput,
}

uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput,
uint64_t *observedPulses,
uint32_t *committedPulses,
uint64_t *committedTimeUs,
uint32_t *tailFrequencyHz,
uint8_t *startsNextSegment)
{
TIM_TypeDef *counter;
uint32_t criticalState;
uint32_t blockCount;
uint32_t completed;
uint32_t frequencyHz;
uint32_t remaining;
uint64_t timeUs;
uint64_t observed;

if ((pulseOutput > 3U) || (committedPulses == NULL)
|| (tailFrequencyHz == NULL) || (startsNextSegment == NULL))
if ((pulseOutput > 3U) || (observedPulses == NULL)
|| (committedPulses == NULL)
|| (committedTimeUs == NULL) || (tailFrequencyHz == NULL)
|| (startsNextSegment == NULL))
{
return 0U;
}
@@ -3525,23 +3644,31 @@ uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput,
PlsrPlatformExitCritical(criticalState);
return 0U;
}
counter = PlsrCounters[PlsrCounterIndexByOutput[pulseOutput]];
blockCount = (uint16_t)counter->CNT;
if (blockCount >= PlsrFiniteCounterPreload[pulseOutput])
completed = PlsrFiniteCompletedPulsesSnapshot(pulseOutput);
remaining = PlsrFiniteTargetPulses[pulseOutput];
if (completed > remaining)
{
blockCount -= PlsrFiniteCounterPreload[pulseOutput];
completed = remaining;
}
observed = PlsrObservedPulseBase[pulseOutput] + completed;
if (observed < PlsrObservedPulsePublished[pulseOutput])
{
observed = PlsrObservedPulsePublished[pulseOutput];
}
else
{
blockCount = 0UL;
PlsrObservedPulsePublished[pulseOutput] = observed;
}
remaining = PlsrFiniteRemainingPulses[pulseOutput];
if (blockCount > remaining)
remaining -= completed;
frequencyHz = PlsrTimerActiveFrequencyHz[pulseOutput];
if (frequencyHz == 0UL)
{
blockCount = remaining;
PlsrPlatformExitCritical(criticalState);
return 0U;
}
remaining -= blockCount;
*tailFrequencyHz = PlsrTimerActiveFrequencyHz[pulseOutput];
timeUs = ((uint64_t)remaining * 1000000ULL
+ frequencyHz - 1UL) / frequencyHz;
*tailFrequencyHz = frequencyHz;
*startsNextSegment = 0U;
if (PlsrFiniteStreamNextValid[pulseOutput] != 0U)
{
@@ -3549,12 +3676,22 @@ uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput,

remaining = (nextPulses > (0xFFFFFFFFUL - remaining))
? 0xFFFFFFFFUL : remaining + nextPulses;
*tailFrequencyHz =
frequencyHz =
PlsrFiniteStreamNextSetting[pulseOutput].actualFrequencyHz;
if (frequencyHz == 0UL)
{
PlsrPlatformExitCritical(criticalState);
return 0U;
}
timeUs += ((uint64_t)nextPulses * 1000000ULL
+ frequencyHz - 1UL) / frequencyHz;
*tailFrequencyHz = frequencyHz;
*startsNextSegment =
PlsrFiniteStreamNextStartsSegment[pulseOutput];
}
*observedPulses = observed;
*committedPulses = remaining;
*committedTimeUs = timeUs;
PlsrPlatformExitCritical(criticalState);
return 1U;
}
@@ -4284,6 +4421,30 @@ uint8_t PlsrPlatformReadInput(uint8_t inputSelection)
return 0U;
}

uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection)
{
uint16_t pin;

if (inputSelection == 0U)
{
pin = GPIO_PIN_5;
}
else if (inputSelection == 1U)
{
pin = GPIO_PIN_12;
}
else
{
return 0U;
}
if (__HAL_GPIO_EXTI_GET_IT(pin) == RESET)
{
return 0U;
}
__HAL_GPIO_EXTI_CLEAR_IT(pin);
return 1U;
}

uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload)
{
PLSR_FLASH_SECTOR_SCAN scanA;
@@ -4659,7 +4820,8 @@ static void PlsrHandleTimerIrq(uint8_t pulseOutput)
&& (PlsrFiniteTailStopPending[pulseOutput] != 0U))
{
timer->SR = ~TIM_SR_CC1IF;
PlsrFiniteCutAtFallingEdge(pulseOutput);
timer->DIER &= ~TIM_DIER_CC1IE;
timer->DIER |= TIM_DIER_UIE;
goto irq_done;
}
#if PLSR_DEBUG_TIMING
@@ -4732,6 +4894,12 @@ static void PlsrHandleTimerIrq(uint8_t pulseOutput)
&& ((timer->DIER & TIM_DIER_UIE) != 0UL))
{
timer->SR = ~(TIM_SR_UIF | TIM_SR_CC1IF);
if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_PULSE_DIR)
&& (PlsrFiniteTailStopPending[pulseOutput] != 0U))
{
PlsrFiniteCutAtIdleBoundary(pulseOutput);
goto irq_done;
}
if ((PlsrFiniteActive[pulseOutput] != 0U)
&& (PlsrFiniteFrequencyPending[pulseOutput] != 0U))
{
@@ -5180,13 +5348,9 @@ static void PlsrFiniteCounterIrq(uint8_t pulseOutput,
counter->CR1 &= ~TIM_CR1_CEN;
counter->SMCR &= ~(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0);

/*
* An OC rising edge is the terminal pulse's falling edge because the
* output stage is active low. The target-count update IRQ therefore is
* already the safe idle boundary: stop here before CCR1 can start an
* extra terminal pulse.
*/
PlsrFiniteStopAtFallingEdge(pulseOutput);
/* The counter update is sourced by the PWM edge that returns the MCU pin
high. The terminal pulse is complete and the output is safely idle. */
PlsrFiniteStopAtIdleBoundary(pulseOutput);
}

static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput)
@@ -5235,32 +5399,16 @@ static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput)
PlsrCounterBegin(pulseOutput);
}

static void PlsrFiniteCutAtFallingEdge(uint8_t pulseOutput)
static void PlsrFiniteCutAtIdleBoundary(uint8_t pulseOutput)
{
uint8_t counterIndex = PlsrCounterIndexByOutput[pulseOutput];
TIM_TypeDef *counter = PlsrCounters[counterIndex];
uint32_t blockCount;
uint32_t completed;

/* Freeze the external counter at the same falling edge that makes the
pulse output idle, then convert the partial current run into the
terminal run consumed by PlsrPlatformTakeFiniteCompletion(). */
/* The source output is high here. Freeze the slave counter and publish
exactly the completed full pulses from the partial current run. */
PlsrCounterSuspend(pulseOutput);
blockCount = (uint16_t)counter->CNT;
if (blockCount >= PlsrFiniteCounterPreload[pulseOutput])
{
blockCount -= PlsrFiniteCounterPreload[pulseOutput];
}
else
{
blockCount = 0UL;
}
completed = PlsrFiniteTargetPulses[pulseOutput]
- PlsrFiniteRemainingPulses[pulseOutput] + blockCount;
if (completed > PlsrFiniteTargetPulses[pulseOutput])
{
completed = PlsrFiniteTargetPulses[pulseOutput];
}
completed = PlsrFiniteCompletedPulsesSnapshot(pulseOutput);

PlsrObservedPulseBase[pulseOutput] += completed;
PlsrObservedPulsePublished[pulseOutput] =
@@ -5276,10 +5424,10 @@ static void PlsrFiniteCutAtFallingEdge(uint8_t pulseOutput)
PlsrCounterOverflowPulses[counterIndex] = 0UL;
counter->CNT = 0UL;
counter->SR = 0UL;
PlsrFiniteStopAtFallingEdge(pulseOutput);
PlsrFiniteStopAtIdleBoundary(pulseOutput);
}

static void PlsrFiniteStopAtFallingEdge(uint8_t pulseOutput)
static void PlsrFiniteStopAtIdleBoundary(uint8_t pulseOutput)
{
TIM_TypeDef *timer = PlsrTimerMap[pulseOutput].timer;



Loading…
Откажи
Сачувај