瀏覽代碼

修复EXT 硬件 pending 竞态

codex/plsr-2026-minimal
ywh 1 月之前
父節點
當前提交
ec2aa94775
共有 3 個文件被更改,包括 146 次插入16 次删除
  1. +112
    -15
      PLSR/Src/plsr.c
  2. +4
    -1
      PLSR/Src/plsr_platform.h
  3. +30
    -0
      PLSR/Src/plsr_platform_f407.c

+ 112
- 15
PLSR/Src/plsr.c 查看文件

@@ -327,6 +327,10 @@ static volatile uint32_t PlsrSegmentElapsedMs;
static volatile uint32_t PlsrWaitElapsedMs; static volatile uint32_t PlsrWaitElapsedMs;
static volatile uint8_t PlsrExtPreviousLevel; static volatile uint8_t PlsrExtPreviousLevel;
static volatile uint8_t PlsrExtEdgePending; static volatile uint8_t PlsrExtEdgePending;
static volatile uint8_t PlsrExtEdgePendingSegment;
static volatile uint32_t PlsrExtEdgePendingEpoch;
static volatile uint8_t PlsrExtCaptureSegment;
static volatile uint32_t PlsrExtCaptureEpoch;
static volatile uint8_t PlsrWaitSignalArmedMask; static volatile uint8_t PlsrWaitSignalArmedMask;
static volatile uint8_t PlsrWaitSignalPendingMask; static volatile uint8_t PlsrWaitSignalPendingMask;
static volatile uint8_t PlsrStopRequested; static volatile uint8_t PlsrStopRequested;
@@ -2608,7 +2612,8 @@ static void PlsrServiceTimedStartPreparation(void)
|| (PlsrLastDirectionLevel != directionLevel)) ? 1U : 0U; || (PlsrLastDirectionLevel != directionLevel)) ? 1U : 0U;
coldStartBoundary = ((sourceWaitType == PLSR_WAIT_TIME) coldStartBoundary = ((sourceWaitType == PLSR_WAIT_TIME)
|| (sourceWaitType == PLSR_WAIT_SIGNAL) || (sourceWaitType == PLSR_WAIT_SIGNAL)
|| ((sourceWaitType == PLSR_ACT_TIME)
|| (((sourceWaitType == PLSR_ACT_TIME)
|| (sourceWaitType == PLSR_EXT_SIGNAL))
&& (sourceWaiting != 0U))) ? 1U : 0U; && (sourceWaiting != 0U))) ? 1U : 0U;
if ((coldStartBoundary == 0U) && (directionChanged == 0U)) if ((coldStartBoundary == 0U) && (directionChanged == 0U))
{ {
@@ -3431,6 +3436,8 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment(


PlsrSegmentEpoch++; PlsrSegmentEpoch++;
PlsrCurrentSegment = segmentNumber; PlsrCurrentSegment = segmentNumber;
PlsrExtCaptureSegment = segmentNumber;
PlsrExtCaptureEpoch = PlsrSegmentEpoch;
PlsrSegmentClockStarted = 0U; PlsrSegmentClockStarted = 0U;
PlsrSegmentElapsedMs = 0UL; PlsrSegmentElapsedMs = 0UL;
PlsrWaitElapsedMs = 0UL; PlsrWaitElapsedMs = 0UL;
@@ -3449,7 +3456,6 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment(
PlsrShortProfile.nextPeriod = 0U; PlsrShortProfile.nextPeriod = 0U;
PlsrDirectionDelayActive = 0U; PlsrDirectionDelayActive = 0U;
PlsrDirectionDelayRemainingMs = 0U; PlsrDirectionDelayRemainingMs = 0U;
PlsrExtEdgePending = 0U;
PlsrRemainingPulses = magnitude; PlsrRemainingPulses = magnitude;
PlsrCountPositive = positive; PlsrCountPositive = positive;
PlsrActTimedCutPlanned = PlsrTimedStart.nextActTimedCut; PlsrActTimedCutPlanned = PlsrTimedStart.nextActTimedCut;
@@ -3697,8 +3703,12 @@ static uint8_t PlsrStartSegment(uint8_t segmentNumber,
magnitude = (displacement < 0) ? (uint64_t)(-displacement) magnitude = (displacement < 0) ? (uint64_t)(-displacement)
: (uint64_t)displacement; : (uint64_t)displacement;


criticalState = PlsrPlatformEnterCritical();
PlsrSegmentEpoch++; PlsrSegmentEpoch++;
PlsrCurrentSegment = segmentNumber; PlsrCurrentSegment = segmentNumber;
PlsrExtCaptureSegment = segmentNumber;
PlsrExtCaptureEpoch = PlsrSegmentEpoch;
PlsrPlatformExitCritical(criticalState);
PlsrSegmentClockStarted = 0U; PlsrSegmentClockStarted = 0U;
PlsrSegmentElapsedMs = 0UL; PlsrSegmentElapsedMs = 0UL;
PlsrWaitElapsedMs = 0UL; PlsrWaitElapsedMs = 0UL;
@@ -3725,7 +3735,6 @@ static uint8_t PlsrStartSegment(uint8_t segmentNumber,
} }
PlsrDirectionDelayActive = 0U; PlsrDirectionDelayActive = 0U;
PlsrDirectionDelayRemainingMs = 0U; PlsrDirectionDelayRemainingMs = 0U;
PlsrExtEdgePending = 0U;
PlsrExtPreviousLevel = PlsrExtPreviousLevel =
PlsrPlatformReadInput((uint8_t)PlsrActiveConfig.extInput); PlsrPlatformReadInput((uint8_t)PlsrActiveConfig.extInput);


@@ -3873,6 +3882,7 @@ static void PlsrFinishCompleted(void)
PlsrSegmentClockStarted = 0U; PlsrSegmentClockStarted = 0U;
PlsrDirectionDelayActive = 0U; PlsrDirectionDelayActive = 0U;
PlsrDirectionDelayRemainingMs = 0U; PlsrDirectionDelayRemainingMs = 0U;
PlsrExtCaptureSegment = 0U;
PlsrExtEdgePending = 0U; PlsrExtEdgePending = 0U;
PlsrStopRequested = 0U; PlsrStopRequested = 0U;
PlsrStopPulsesRemaining = 0U; PlsrStopPulsesRemaining = 0U;
@@ -3913,6 +3923,7 @@ static void PlsrFinishStopped(void)
PlsrSegmentClockStarted = 0U; PlsrSegmentClockStarted = 0U;
PlsrDirectionDelayActive = 0U; PlsrDirectionDelayActive = 0U;
PlsrDirectionDelayRemainingMs = 0U; PlsrDirectionDelayRemainingMs = 0U;
PlsrExtCaptureSegment = 0U;
PlsrExtEdgePending = 0U; PlsrExtEdgePending = 0U;
PlsrStopRequested = 0U; PlsrStopRequested = 0U;
PlsrStopPulsesRemaining = 0U; PlsrStopPulsesRemaining = 0U;
@@ -3953,6 +3964,7 @@ static void PlsrEnterError(PLSR_ERROR error)
PlsrSegmentClockStarted = 0U; PlsrSegmentClockStarted = 0U;
PlsrDirectionDelayActive = 0U; PlsrDirectionDelayActive = 0U;
PlsrDirectionDelayRemainingMs = 0U; PlsrDirectionDelayRemainingMs = 0U;
PlsrExtCaptureSegment = 0U;
PlsrExtEdgePending = 0U; PlsrExtEdgePending = 0U;
PlsrStopRequested = 0U; PlsrStopRequested = 0U;
PlsrStopPulsesRemaining = 0U; PlsrStopPulsesRemaining = 0U;
@@ -4508,6 +4520,9 @@ void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput,
{ {
PLSR_COUNTED_BOUNDARY_EVENT *event; PLSR_COUNTED_BOUNDARY_EVENT *event;
uint8_t writeIndex; uint8_t writeIndex;
uint8_t previousExtSegment;
uint8_t hardwareExtPending;
uint32_t previousExtEpoch;


if (pulseOutput != (uint8_t)PlsrActiveConfig.pulseOutput) if (pulseOutput != (uint8_t)PlsrActiveConfig.pulseOutput)
{ {
@@ -4534,6 +4549,27 @@ void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput,
event->nextSegment = PlsrHandoffPlan.nextSegment; event->nextSegment = PlsrHandoffPlan.nextSegment;
event->positive = PlsrHandoffPlan.positive; event->positive = PlsrHandoffPlan.positive;
event->nextActTimedCut = PlsrHandoffPlan.nextActTimedCut; event->nextActTimedCut = PlsrHandoffPlan.nextActTimedCut;
previousExtSegment = PlsrExtCaptureSegment;
previousExtEpoch = PlsrExtCaptureEpoch;
hardwareExtPending = PlsrPlatformTakeInputExtiPending(
(uint8_t)PlsrActiveConfig.extInput);
if (hardwareExtPending != 0U)
{
/* The lower-priority EXTI ISR has not run yet. The natural boundary
consumes this source-segment edge, so discard any matching software
latch as well and do not let either reach the next segment. */
PlsrExtEdgePending = 0U;
}
else if ((PlsrExtEdgePending != 0U)
&& (PlsrExtEdgePendingSegment == previousExtSegment)
&& (PlsrExtEdgePendingEpoch == previousExtEpoch))
{
/* The EXTI ISR already captured the source-segment edge. Natural
completion satisfies EXT_OR_COMPLETE, preventing a double step. */
PlsrExtEdgePending = 0U;
}
PlsrExtCaptureSegment = event->nextSegment;
PlsrExtCaptureEpoch = previousExtEpoch + 1UL;
#if defined(__ICCARM__) #if defined(__ICCARM__)
__DMB(); __DMB();
#endif #endif
@@ -4661,7 +4697,6 @@ static void PlsrExecServiceCountedBoundaryEvent(void)
PlsrActiveConfig.segments[nextSegment - 1U].frequencyHz; PlsrActiveConfig.segments[nextSegment - 1U].frequencyHz;
} }
PlsrDeferredFrequencyPending = 0U; PlsrDeferredFrequencyPending = 0U;
PlsrExtEdgePending = 0U;
PlsrExtPreviousLevel = PlsrExtPreviousLevel =
PlsrPlatformReadInput((uint8_t)PlsrActiveConfig.extInput); PlsrPlatformReadInput((uint8_t)PlsrActiveConfig.extInput);
PlsrCopyShortProfile(&PlsrShortProfile, PlsrCopyShortProfile(&PlsrShortProfile,
@@ -4929,12 +4964,16 @@ static PLSR_PLATFORM_QUEUE_RESULT PlsrTryContinuousHandoff(void)
return PLSR_PLATFORM_QUEUE_APPLIED; return PLSR_PLATFORM_QUEUE_APPLIED;
} }


/* EXTI only records a WAIT edge. Motion state transitions and timer startup
remain in the task context. The armed mask prevents an edge from an idle
or unrelated input from releasing a later segment. */
/* EXTI only records an input edge. Motion state transitions and timer
operations remain in the task context. WAIT uses an armed mask; EXT binds
the edge to the active segment epoch so a stale edge cannot cut a later
segment. */
void PlsrWaitInputExtiIrq(uint8_t inputSelection) void PlsrWaitInputExtiIrq(uint8_t inputSelection)
{ {
uint8_t bit; uint8_t bit;
uint8_t captureSegment;
uint32_t captureEpoch;
uint16_t waitType;


if (inputSelection > 1U) if (inputSelection > 1U)
{ {
@@ -4945,6 +4984,25 @@ void PlsrWaitInputExtiIrq(uint8_t inputSelection)
{ {
PlsrWaitSignalPendingMask |= bit; PlsrWaitSignalPendingMask |= bit;
} }
captureEpoch = PlsrExtCaptureEpoch;
captureSegment = PlsrExtCaptureSegment;
if ((PlsrActiveConfig.outputMode != PLSR_OUTPUT_PULSE_DIR)
|| (inputSelection != (uint8_t)PlsrActiveConfig.extInput)
|| (captureSegment == 0U)
|| (captureSegment > PlsrActiveConfig.segmentCount))
{
return;
}
waitType = PlsrActiveConfig.segments[captureSegment - 1U].waitType;
if (((waitType == PLSR_EXT_SIGNAL)
|| (waitType == PLSR_EXT_OR_COMPLETE))
&& (captureEpoch == PlsrExtCaptureEpoch)
&& (captureSegment == PlsrExtCaptureSegment))
{
PlsrExtEdgePendingSegment = captureSegment;
PlsrExtEdgePendingEpoch = captureEpoch;
PlsrExtEdgePending = 1U;
}
} }


static void PlsrArmWaitSignal(uint8_t inputSelection) static void PlsrArmWaitSignal(uint8_t inputSelection)
@@ -5009,8 +5067,10 @@ static void PlsrHandleBoundary(uint8_t extEdge)
{ {
const PLSR_SEGMENT_CONFIG *segment; const PLSR_SEGMENT_CONFIG *segment;
uint32_t criticalState; uint32_t criticalState;
uint32_t currentEpoch;
uint8_t wasCut = PlsrBoundaryWasCut; uint8_t wasCut = PlsrBoundaryWasCut;
uint8_t preserveTimedStart; uint8_t preserveTimedStart;
uint8_t currentSegment;


PlsrPlatformStopPulse((uint8_t)PlsrActiveConfig.pulseOutput); PlsrPlatformStopPulse((uint8_t)PlsrActiveConfig.pulseOutput);
PlsrBoundaryPending = 0U; PlsrBoundaryPending = 0U;
@@ -5074,10 +5134,18 @@ static void PlsrHandleBoundary(uint8_t extEdge)
segment = &PlsrActiveConfig.segments[PlsrCurrentSegment - 1U]; segment = &PlsrActiveConfig.segments[PlsrCurrentSegment - 1U];
if (wasCut != 0U) if (wasCut != 0U)
{ {
PlsrTransitionToNext(
uint8_t allowCarry =
((segment->waitType == PLSR_ACT_TIME) ((segment->waitType == PLSR_ACT_TIME)
|| (PlsrActiveConfig.sendMode == PLSR_SEND_SUBSEQUENT)) || (PlsrActiveConfig.sendMode == PLSR_SEND_SUBSEQUENT))
? 1U : 0U);
? 1U : 0U;

if ((PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR)
&& ((segment->waitType == PLSR_EXT_SIGNAL)
|| (segment->waitType == PLSR_EXT_OR_COMPLETE)))
{
allowCarry = 1U;
}
PlsrTransitionToNext(allowCarry);
return; return;
} }


@@ -5117,6 +5185,17 @@ static void PlsrHandleBoundary(uint8_t extEdge)
break; break;


case PLSR_EXT_SIGNAL: case PLSR_EXT_SIGNAL:
criticalState = PlsrPlatformEnterCritical();
currentEpoch = PlsrSegmentEpoch;
currentSegment = PlsrCurrentSegment;
if ((PlsrExtEdgePending != 0U)
&& (PlsrExtEdgePendingEpoch == currentEpoch)
&& (PlsrExtEdgePendingSegment == currentSegment))
{
extEdge = 1U;
PlsrExtEdgePending = 0U;
}
PlsrPlatformExitCritical(criticalState);
if (extEdge != 0U) if (extEdge != 0U)
{ {
PlsrTransitionToNext(0U); PlsrTransitionToNext(0U);
@@ -5353,6 +5432,10 @@ uint8_t PlsrInit(void)
PlsrSegmentClockStarted = 0U; PlsrSegmentClockStarted = 0U;
PlsrExtPreviousLevel = 0U; PlsrExtPreviousLevel = 0U;
PlsrExtEdgePending = 0U; PlsrExtEdgePending = 0U;
PlsrExtEdgePendingSegment = 0U;
PlsrExtEdgePendingEpoch = 0UL;
PlsrExtCaptureSegment = 0U;
PlsrExtCaptureEpoch = 0UL;
PlsrWaitSignalArmedMask = 0U; PlsrWaitSignalArmedMask = 0U;
PlsrWaitSignalPendingMask = 0U; PlsrWaitSignalPendingMask = 0U;
PlsrStopRequested = 0U; PlsrStopRequested = 0U;
@@ -5586,6 +5669,7 @@ static void PlsrExecuteClear(void)
PlsrBoundaryWasCut = 0U; PlsrBoundaryWasCut = 0U;
PlsrDirectionDelayActive = 0U; PlsrDirectionDelayActive = 0U;
PlsrDirectionDelayRemainingMs = 0U; PlsrDirectionDelayRemainingMs = 0U;
PlsrExtCaptureSegment = 0U;
PlsrExtEdgePending = 0U; PlsrExtEdgePending = 0U;
PlsrShortProfile.active = 0U; PlsrShortProfile.active = 0U;
PlsrProfileQueueReset(); PlsrProfileQueueReset();
@@ -5801,18 +5885,23 @@ void PlsrPoll1ms(void)


criticalState = PlsrPlatformEnterCritical(); criticalState = PlsrPlatformEnterCritical();
pollEpoch = PlsrSegmentEpoch; pollEpoch = PlsrSegmentEpoch;
activeSegmentNumber = PlsrCurrentSegment;
extLevel = PlsrPlatformReadInput((uint8_t)PlsrActiveConfig.extInput); extLevel = PlsrPlatformReadInput((uint8_t)PlsrActiveConfig.extInput);
extEdge = ((extLevel != 0U) && (PlsrExtPreviousLevel == 0U)) ? 1U : 0U; extEdge = ((extLevel != 0U) && (PlsrExtPreviousLevel == 0U)) ? 1U : 0U;
PlsrExtPreviousLevel = extLevel; PlsrExtPreviousLevel = extLevel;
if (PlsrExtEdgePending != 0U) if (PlsrExtEdgePending != 0U)
{ {
extEdge = 1U;
if ((PlsrExtEdgePendingEpoch == pollEpoch)
&& (PlsrExtEdgePendingSegment == activeSegmentNumber))
{
extEdge = 1U;
}
PlsrExtEdgePending = 0U;
} }
PlsrPlatformExitCritical(criticalState); PlsrPlatformExitCritical(criticalState);


if (PlsrBoundaryPending != 0U) if (PlsrBoundaryPending != 0U)
{ {
PlsrExtEdgePending = 0U;
PlsrHandleBoundary(extEdge); PlsrHandleBoundary(extEdge);
PlsrPollPersistenceDelay(); PlsrPollPersistenceDelay();
return; return;
@@ -5832,9 +5921,18 @@ void PlsrPoll1ms(void)


if (PlsrDirectionDelayActive != 0U) if (PlsrDirectionDelayActive != 0U)
{ {
if (extEdge != 0U)
{
PlsrExtEdgePending = 1U;
activeSegmentNumber = PlsrCurrentSegment;
if ((extEdge != 0U)
&& (activeSegmentNumber != 0U)
&& (activeSegmentNumber <= PlsrActiveConfig.segmentCount)
&& ((PlsrActiveConfig.segments[activeSegmentNumber - 1U].waitType
== PLSR_EXT_SIGNAL)
|| (PlsrActiveConfig.segments[
activeSegmentNumber - 1U].waitType
== PLSR_EXT_OR_COMPLETE)))
{
PlsrRequestCut(pollEpoch);
return;
} }
if (PlsrDirectionDelayRemainingMs != 0U) if (PlsrDirectionDelayRemainingMs != 0U)
{ {
@@ -5868,7 +5966,6 @@ void PlsrPoll1ms(void)
PlsrPlatformExitCritical(criticalState); PlsrPlatformExitCritical(criticalState);
return; return;
} }
PlsrExtEdgePending = 0U;
if (PlsrSegmentClockStarted != 0U) if (PlsrSegmentClockStarted != 0U)
{ {
PlsrSegmentElapsedMs++; PlsrSegmentElapsedMs++;


+ 4
- 1
PLSR/Src/plsr_platform.h 查看文件

@@ -118,7 +118,7 @@ uint8_t PlsrExecTakeCountedRunIrq(
void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput, void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput,
uint32_t completedPulses); uint32_t completedPulses);
void PlsrExecCountedStreamFaultIrq(uint8_t pulseOutput); 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); void PlsrWaitInputExtiIrq(uint8_t inputSelection);
PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformLoadPreparedFromIrq( PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformLoadPreparedFromIrq(
uint8_t pulseOutput, uint8_t pulseOutput,
@@ -145,6 +145,9 @@ PLSR_PLATFORM_STOP_RESULT PlsrPlatformRequestStopLocked(
uint8_t PlsrPlatformQueueFinalArmFromIrq(uint8_t pulseOutput); uint8_t PlsrPlatformQueueFinalArmFromIrq(uint8_t pulseOutput);
void PlsrPlatformStopPulse(uint8_t pulseOutput); void PlsrPlatformStopPulse(uint8_t pulseOutput);
uint8_t PlsrPlatformReadInput(uint8_t inputSelection); 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); uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload);
PLSR_PLATFORM_SERVICE_RESULT PlsrPlatformServicePersistence(void); PLSR_PLATFORM_SERVICE_RESULT PlsrPlatformServicePersistence(void);


+ 30
- 0
PLSR/Src/plsr_platform_f407.c 查看文件

@@ -893,6 +893,12 @@ uint8_t PlsrPlatformReadInput(uint8_t inputSelection)
return (inputSelection <= 1U) ? PlsrHostInputs[inputSelection] : 0U; return (inputSelection <= 1U) ? PlsrHostInputs[inputSelection] : 0U;
} }


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

uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload) uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload)
{ {
if ((payload == NULL) || (PlsrHostPersistentValid == 0U)) if ((payload == NULL) || (PlsrHostPersistentValid == 0U))
@@ -4284,6 +4290,30 @@ uint8_t PlsrPlatformReadInput(uint8_t inputSelection)
return 0U; 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) uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload)
{ {
PLSR_FLASH_SECTOR_SCAN scanA; PLSR_FLASH_SECTOR_SCAN scanA;


Loading…
取消
儲存