|
|
@@ -152,6 +152,7 @@ typedef struct |
|
|
{ |
|
|
{ |
|
|
PLSR_PROFILE_ENTRY firstRun; |
|
|
PLSR_PROFILE_ENTRY firstRun; |
|
|
uint64_t magnitude; |
|
|
uint64_t magnitude; |
|
|
|
|
|
int64_t resolvedDisplacement; |
|
|
uint32_t sourceEpoch; |
|
|
uint32_t sourceEpoch; |
|
|
uint32_t queueGeneration; |
|
|
uint32_t queueGeneration; |
|
|
uint16_t generatedItems; |
|
|
uint16_t generatedItems; |
|
|
@@ -396,6 +397,7 @@ static uint32_t PlsrEffectiveStopFrequency(uint32_t segmentFrequencyHz); |
|
|
static uint8_t PlsrBeginSegmentOutput(uint32_t startFrequencyHz); |
|
|
static uint8_t PlsrBeginSegmentOutput(uint32_t startFrequencyHz); |
|
|
static void PlsrHandleBoundary(uint8_t extEdge); |
|
|
static void PlsrHandleBoundary(uint8_t extEdge); |
|
|
static void PlsrTransitionToNext(uint8_t allowCarry); |
|
|
static void PlsrTransitionToNext(uint8_t allowCarry); |
|
|
|
|
|
static void PlsrRequestCut(uint32_t expectedEpoch); |
|
|
static void PlsrFinishCompleted(void); |
|
|
static void PlsrFinishCompleted(void); |
|
|
static void PlsrFinishStopped(void); |
|
|
static void PlsrFinishStopped(void); |
|
|
static void PlsrEnterError(PLSR_ERROR error); |
|
|
static void PlsrEnterError(PLSR_ERROR error); |
|
|
@@ -437,7 +439,8 @@ static void PlsrProfileQueueResetBankLocked(uint8_t bank); |
|
|
static void PlsrInvalidateTimedStartLocked(void); |
|
|
static void PlsrInvalidateTimedStartLocked(void); |
|
|
static void PlsrServiceTimedStartPreparation(void); |
|
|
static void PlsrServiceTimedStartPreparation(void); |
|
|
static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment( |
|
|
static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment( |
|
|
uint8_t segmentNumber); |
|
|
|
|
|
|
|
|
uint8_t segmentNumber, |
|
|
|
|
|
int64_t resolvedDisplacement); |
|
|
static uint8_t PlsrStartPreparedTimedOutput(void); |
|
|
static uint8_t PlsrStartPreparedTimedOutput(void); |
|
|
static void PlsrProfileQueueInvalidateGeneration(void); |
|
|
static void PlsrProfileQueueInvalidateGeneration(void); |
|
|
static uint8_t PlsrProfileQueueBegin( |
|
|
static uint8_t PlsrProfileQueueBegin( |
|
|
@@ -2363,6 +2366,7 @@ static void PlsrInvalidateTimedStartLocked(void) |
|
|
PlsrTimedStart.valid = 0U; |
|
|
PlsrTimedStart.valid = 0U; |
|
|
PlsrTimedStart.pendingActivation = 0U; |
|
|
PlsrTimedStart.pendingActivation = 0U; |
|
|
PlsrTimedStart.nextActTimedCut = 0U; |
|
|
PlsrTimedStart.nextActTimedCut = 0U; |
|
|
|
|
|
PlsrTimedStart.resolvedDisplacement = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void PlsrProfileQueueResetBankLocked(uint8_t bank) |
|
|
static void PlsrProfileQueueResetBankLocked(uint8_t bank) |
|
|
@@ -2678,6 +2682,7 @@ static void PlsrServiceTimedStartPreparation(void) |
|
|
|
|
|
|
|
|
PlsrTimedStart.firstRun = entry; |
|
|
PlsrTimedStart.firstRun = entry; |
|
|
PlsrTimedStart.magnitude = magnitude; |
|
|
PlsrTimedStart.magnitude = magnitude; |
|
|
|
|
|
PlsrTimedStart.resolvedDisplacement = displacement; |
|
|
PlsrTimedStart.sourceEpoch = sourceEpoch; |
|
|
PlsrTimedStart.sourceEpoch = sourceEpoch; |
|
|
PlsrTimedStart.queueGeneration = queue->generation; |
|
|
PlsrTimedStart.queueGeneration = queue->generation; |
|
|
PlsrTimedStart.generatedItems = 0U; |
|
|
PlsrTimedStart.generatedItems = 0U; |
|
|
@@ -2910,6 +2915,9 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrPrepareDelayedCurrentOutput( |
|
|
} |
|
|
} |
|
|
PlsrTimedStart.firstRun = firstRun; |
|
|
PlsrTimedStart.firstRun = firstRun; |
|
|
PlsrTimedStart.magnitude = profile.pulseCount; |
|
|
PlsrTimedStart.magnitude = profile.pulseCount; |
|
|
|
|
|
PlsrTimedStart.resolvedDisplacement = (countPositive != 0U) |
|
|
|
|
|
? (int64_t)remainingPulses |
|
|
|
|
|
: -(int64_t)remainingPulses; |
|
|
PlsrTimedStart.sourceEpoch = PlsrSegmentEpoch - 1UL; |
|
|
PlsrTimedStart.sourceEpoch = PlsrSegmentEpoch - 1UL; |
|
|
PlsrTimedStart.queueGeneration = queueGeneration; |
|
|
PlsrTimedStart.queueGeneration = queueGeneration; |
|
|
PlsrTimedStart.generatedItems = generatedItems; |
|
|
PlsrTimedStart.generatedItems = generatedItems; |
|
|
@@ -3407,7 +3415,8 @@ static uint8_t PlsrStartPreparedTimedOutput(void) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment( |
|
|
static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment( |
|
|
uint8_t segmentNumber) |
|
|
|
|
|
|
|
|
uint8_t segmentNumber, |
|
|
|
|
|
int64_t resolvedDisplacement) |
|
|
{ |
|
|
{ |
|
|
PLSR_PROFILE_QUEUE *queue; |
|
|
PLSR_PROFILE_QUEUE *queue; |
|
|
uint32_t criticalState; |
|
|
uint32_t criticalState; |
|
|
@@ -3422,13 +3431,23 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment( |
|
|
|| (PlsrTimedStart.pendingActivation != 0U) |
|
|
|| (PlsrTimedStart.pendingActivation != 0U) |
|
|
|| (PlsrTimedStart.sourceEpoch != PlsrSegmentEpoch) |
|
|
|| (PlsrTimedStart.sourceEpoch != PlsrSegmentEpoch) |
|
|
|| (PlsrTimedStart.sourceSegment != PlsrCurrentSegment) |
|
|
|| (PlsrTimedStart.sourceSegment != PlsrCurrentSegment) |
|
|
|| (PlsrTimedStart.nextSegment != segmentNumber) |
|
|
|
|
|
|| (PlsrTimedStart.queueBank == PlsrProfileQueueBank) |
|
|
|| (PlsrTimedStart.queueBank == PlsrProfileQueueBank) |
|
|
|| (queue->generation != PlsrTimedStart.queueGeneration)) |
|
|
|| (queue->generation != PlsrTimedStart.queueGeneration)) |
|
|
{ |
|
|
{ |
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
return PLSR_PLATFORM_SERVICE_DEFERRED; |
|
|
return PLSR_PLATFORM_SERVICE_DEFERRED; |
|
|
} |
|
|
} |
|
|
|
|
|
if ((PlsrTimedStart.nextSegment != segmentNumber) |
|
|
|
|
|
|| (PlsrTimedStart.resolvedDisplacement != resolvedDisplacement)) |
|
|
|
|
|
{ |
|
|
|
|
|
/* An unpredictable boundary (notably an early EXT cut) can change the |
|
|
|
|
|
next segment's resolved relative move. Never publish a profile |
|
|
|
|
|
built for the old endpoint. */ |
|
|
|
|
|
PlsrProfileQueueResetBankLocked(PlsrTimedStart.queueBank); |
|
|
|
|
|
PlsrInvalidateTimedStartLocked(); |
|
|
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
|
|
return PLSR_PLATFORM_SERVICE_DEFERRED; |
|
|
|
|
|
} |
|
|
magnitude = PlsrTimedStart.magnitude; |
|
|
magnitude = PlsrTimedStart.magnitude; |
|
|
positive = PlsrTimedStart.positive; |
|
|
positive = PlsrTimedStart.positive; |
|
|
directionLevel = PlsrTimedStart.directionLevel; |
|
|
directionLevel = PlsrTimedStart.directionLevel; |
|
|
@@ -4016,7 +4035,8 @@ static void PlsrTransitionToNext(uint8_t allowCarry) |
|
|
if ((allowCarry == 0U) |
|
|
if ((allowCarry == 0U) |
|
|
|| (PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR)) |
|
|
|| (PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR)) |
|
|
{ |
|
|
{ |
|
|
preparedResult = PlsrTryStartPreparedTimedSegment(nextSegment); |
|
|
|
|
|
|
|
|
preparedResult = PlsrTryStartPreparedTimedSegment( |
|
|
|
|
|
nextSegment, displacement); |
|
|
if (preparedResult == PLSR_PLATFORM_SERVICE_READY) |
|
|
if (preparedResult == PLSR_PLATFORM_SERVICE_READY) |
|
|
{ |
|
|
{ |
|
|
return; |
|
|
return; |
|
|
@@ -4429,6 +4449,7 @@ uint8_t PlsrExecTakeCountedRunIrq( |
|
|
uint32_t availablePulses; |
|
|
uint32_t availablePulses; |
|
|
uint32_t holdPulses; |
|
|
uint32_t holdPulses; |
|
|
uint32_t holdFrequencyHz; |
|
|
uint32_t holdFrequencyHz; |
|
|
|
|
|
uint32_t producerRemaining; |
|
|
|
|
|
|
|
|
if (queue->generatorComplete != 0U) |
|
|
if (queue->generatorComplete != 0U) |
|
|
{ |
|
|
{ |
|
|
@@ -4440,19 +4461,23 @@ uint8_t PlsrExecTakeCountedRunIrq( |
|
|
pulses and hold the last applied timer setting. The task repays |
|
|
pulses and hold the last applied timer setting. The task repays |
|
|
this debt by advancing (without enqueueing) the same number of |
|
|
this debt by advancing (without enqueueing) the same number of |
|
|
planner pulses, so segment pulse count remains exact. */ |
|
|
planner pulses, so segment pulse count remains exact. */ |
|
|
availablePulses = |
|
|
|
|
|
|
|
|
producerRemaining = |
|
|
(queue->producerProfile.pulseCount |
|
|
(queue->producerProfile.pulseCount |
|
|
> queue->producerProfile.nextPeriod) |
|
|
> queue->producerProfile.nextPeriod) |
|
|
? queue->producerProfile.pulseCount |
|
|
? queue->producerProfile.pulseCount |
|
|
- queue->producerProfile.nextPeriod |
|
|
- queue->producerProfile.nextPeriod |
|
|
: 0UL; |
|
|
: 0UL; |
|
|
if (availablePulses > queue->underrunDebtPulses) |
|
|
|
|
|
|
|
|
if (producerRemaining > queue->underrunDebtPulses) |
|
|
{ |
|
|
{ |
|
|
availablePulses -= queue->underrunDebtPulses; |
|
|
|
|
|
|
|
|
availablePulses = |
|
|
|
|
|
producerRemaining - queue->underrunDebtPulses; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
availablePulses = 0UL; |
|
|
|
|
|
|
|
|
/* Every remaining planner pulse is already represented by a |
|
|
|
|
|
borrowed run. The current committed run is the terminal tail; |
|
|
|
|
|
stopping after it is completion, not a stream underrun. */ |
|
|
|
|
|
return PLSR_EXEC_RUN_DONE; |
|
|
} |
|
|
} |
|
|
holdFrequencyHz = queue->lastSetting.actualFrequencyHz; |
|
|
holdFrequencyHz = queue->lastSetting.actualFrequencyHz; |
|
|
holdPulses = (uint32_t)( |
|
|
holdPulses = (uint32_t)( |
|
|
@@ -4964,10 +4989,9 @@ static PLSR_PLATFORM_QUEUE_RESULT PlsrTryContinuousHandoff(void) |
|
|
return PLSR_PLATFORM_QUEUE_APPLIED; |
|
|
return PLSR_PLATFORM_QUEUE_APPLIED; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 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. */ |
|
|
|
|
|
|
|
|
/* EXTI records an input edge. WAIT remains latch-only; active EXT also arms |
|
|
|
|
|
the bounded finite-cut path so pulse output stops at the next complete |
|
|
|
|
|
falling edge. Planning and segment transitions remain in task context. */ |
|
|
void PlsrWaitInputExtiIrq(uint8_t inputSelection) |
|
|
void PlsrWaitInputExtiIrq(uint8_t inputSelection) |
|
|
{ |
|
|
{ |
|
|
uint8_t bit; |
|
|
uint8_t bit; |
|
|
@@ -5002,6 +5026,10 @@ void PlsrWaitInputExtiIrq(uint8_t inputSelection) |
|
|
PlsrExtEdgePendingSegment = captureSegment; |
|
|
PlsrExtEdgePendingSegment = captureSegment; |
|
|
PlsrExtEdgePendingEpoch = captureEpoch; |
|
|
PlsrExtEdgePendingEpoch = captureEpoch; |
|
|
PlsrExtEdgePending = 1U; |
|
|
PlsrExtEdgePending = 1U; |
|
|
|
|
|
if (PlsrPulseActive != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRequestCut(captureEpoch); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -5743,16 +5771,8 @@ static uint8_t PlsrServiceCountedExecutor(void) |
|
|
} |
|
|
} |
|
|
if (PlsrSyncCountedProgress() == 0U) |
|
|
if (PlsrSyncCountedProgress() == 0U) |
|
|
{ |
|
|
{ |
|
|
#if PLSR_COUNT_ERROR_CHECK_ENABLED |
|
|
|
|
|
PlsrEnterError(PLSR_ERROR_COUNT); |
|
|
PlsrEnterError(PLSR_ERROR_COUNT); |
|
|
return 1U; |
|
|
return 1U; |
|
|
#else |
|
|
|
|
|
/* 计数错误检查暂时关闭:observed 回退(平台计数器基准重置造成的 |
|
|
|
|
|
视图回退)时重新校准发布点,继续运行,不进错误。 */ |
|
|
|
|
|
PlsrCountedObservedPublished = PlsrPlatformObservedPulses( |
|
|
|
|
|
(uint8_t)PlsrActiveConfig.pulseOutput); |
|
|
|
|
|
return 0U; |
|
|
|
|
|
#endif |
|
|
|
|
|
} |
|
|
} |
|
|
activeFrequencyHz = PlsrPlatformActiveFrequency( |
|
|
activeFrequencyHz = PlsrPlatformActiveFrequency( |
|
|
(uint8_t)PlsrActiveConfig.pulseOutput); |
|
|
(uint8_t)PlsrActiveConfig.pulseOutput); |
|
|
@@ -5781,7 +5801,11 @@ static uint8_t PlsrServiceCountedExecutor(void) |
|
|
return 0U; |
|
|
return 0U; |
|
|
} |
|
|
} |
|
|
(void)completedPulses; |
|
|
(void)completedPulses; |
|
|
(void)PlsrSyncCountedProgress(); |
|
|
|
|
|
|
|
|
if (PlsrSyncCountedProgress() == 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrEnterError(PLSR_ERROR_COUNT); |
|
|
|
|
|
return 1U; |
|
|
|
|
|
} |
|
|
completedFrequencyHz = PlsrCurrentFrequencyHz; |
|
|
completedFrequencyHz = PlsrCurrentFrequencyHz; |
|
|
completedNormally = ((PlsrRemainingPulses == 0ULL) |
|
|
completedNormally = ((PlsrRemainingPulses == 0ULL) |
|
|
&& (PlsrCutRequested == 0U) |
|
|
&& (PlsrCutRequested == 0U) |
|
|
|