| @@ -81,7 +81,7 @@ static void AppTaskStart(void *pArg) | |||
| { | |||
| PlsrServicePersistence(); | |||
| } | |||
| OSTimeDly(1U); | |||
| // OSTimeDly(1U); | |||
| } | |||
| } | |||
| @@ -226,7 +226,7 @@ | |||
| <name>CCDefines</name> | |||
| <state>USE_HAL_DRIVER</state> | |||
| <state>STM32F407xx</state> | |||
| <state>PLSR_DEBUG_TIMING=1</state> | |||
| <state>PLSR_DEBUG_TIMING=0</state> | |||
| </option> | |||
| <option> | |||
| <name>CCPreprocFile</name> | |||
| @@ -1291,7 +1291,7 @@ | |||
| <name>CCDefines</name> | |||
| <state>USE_HAL_DRIVER</state> | |||
| <state>STM32F407xx</state> | |||
| <state>PLSR_DEBUG_TIMING=1</state> | |||
| <state>PLSR_DEBUG_TIMING=0</state> | |||
| </option> | |||
| <option> | |||
| <name>CCPreprocFile</name> | |||
| @@ -1580,7 +1580,7 @@ | |||
| <name>CCDefines</name> | |||
| <state>USE_HAL_DRIVER</state> | |||
| <state>STM32F407xx</state> | |||
| <state>PLSR_DEBUG_TIMING=1</state> | |||
| <state>PLSR_DEBUG_TIMING=0</state> | |||
| </option> | |||
| <option> | |||
| <name>CCPreprocFile</name> | |||
| @@ -1836,5 +1836,276 @@ | |||
| </settings> | |||
| </configuration> | |||
| </file> | |||
| <configuration> | |||
| <name>Modbus</name> | |||
| <settings> | |||
| <name>ICCARM</name> | |||
| <data> | |||
| <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=0</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>CCOptLevel</name> | |||
| <state>3</state> | |||
| </option> | |||
| <option> | |||
| <name>CCOptStrategy</name> | |||
| <version>0</version> | |||
| <state>2</state> | |||
| </option> | |||
| <option> | |||
| <name>CCOptLevelSlave</name> | |||
| <state>3</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>CCOptStrategySlave</name> | |||
| <version>0</version> | |||
| <state>2</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> | |||
| </data> | |||
| </settings> | |||
| </configuration> | |||
| </group> | |||
| </project> | |||
| @@ -128,8 +128,12 @@ extern volatile uint32_t PlsrProfileProducerItemCount; | |||
| extern volatile uint32_t PlsrProfileProducerTotalCycles; | |||
| extern volatile uint32_t PlsrProfileProducerMaxItemCycles; | |||
| extern volatile uint32_t PlsrFiniteBlockIrqCount[4]; | |||
| extern volatile uint32_t PlsrFiniteBlockIrqLastCycles[4]; | |||
| extern volatile uint32_t PlsrFiniteBlockIrqTotalCycles[4]; | |||
| extern volatile uint32_t PlsrFiniteBlockIrqMaxCycles[4]; | |||
| extern volatile uint32_t PlsrFiniteFinalIrqCount[4]; | |||
| extern volatile uint32_t PlsrFiniteFinalIrqLastCycles[4]; | |||
| extern volatile uint32_t PlsrFiniteFinalIrqTotalCycles[4]; | |||
| extern volatile uint32_t PlsrFiniteFinalIrqMaxCycles[4]; | |||
| #endif | |||
| @@ -59,8 +59,8 @@ | |||
| /* A profile item can represent only one pulse. At the 100 kHz limit these | |||
| thresholds provide 4 ms of startup data, refill toward 8 ms, and cap each | |||
| 1 ms producer pass at 2 ms worth of newly planned items. */ | |||
| #define PLSR_PROFILE_STARTUP_TARGET (400U) | |||
| #define PLSR_PROFILE_STARTUP_BUDGET (400U) | |||
| #define PLSR_PROFILE_STARTUP_TARGET (800U) | |||
| #define PLSR_PROFILE_STARTUP_BUDGET (800U) | |||
| #define PLSR_PROFILE_REFILL_TARGET (800U) | |||
| #define PLSR_PROFILE_REFILL_BUDGET (200U) | |||
| #define PLSR_TIMED_START_BUILD_BUDGET (32U) | |||
| @@ -5725,6 +5725,9 @@ uint8_t PlsrInit(void) | |||
| PlsrProfileProducerItemCount = 0UL; | |||
| PlsrProfileProducerTotalCycles = 0UL; | |||
| PlsrProfileProducerMaxItemCycles = 0UL; | |||
| #if !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingReset(); | |||
| #endif | |||
| #endif | |||
| PlsrError = PLSR_ERROR_NONE; | |||
| PlsrRunStatus = PLSR_STATUS_IDLE; | |||
| @@ -5,6 +5,47 @@ | |||
| #define PLSR_PLANNER_Q32_ONE (4294967296ULL) | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| #define PLSR_PLANNER_CYCCNT_ADDRESS (0xE0001004UL) | |||
| volatile PLSR_PLANNER_TIMING PlsrPlannerTiming; | |||
| static uint32_t PlsrPlannerTimingNow(void) | |||
| { | |||
| return *((volatile uint32_t *)PLSR_PLANNER_CYCCNT_ADDRESS); | |||
| } | |||
| static void PlsrPlannerTimingRecord( | |||
| volatile PLSR_PLANNER_TIMING_SAMPLE *sample, | |||
| uint32_t startedAt) | |||
| { | |||
| uint32_t elapsed = PlsrPlannerTimingNow() - startedAt; | |||
| uint32_t total = sample->totalCycles; | |||
| sample->lastCycles = elapsed; | |||
| if ((sample->callCount == 0UL) || (elapsed < sample->minCycles)) | |||
| { | |||
| sample->minCycles = elapsed; | |||
| } | |||
| if (sample->callCount != 0xFFFFFFFFUL) | |||
| { | |||
| sample->callCount++; | |||
| } | |||
| sample->totalCycles = (elapsed > (0xFFFFFFFFUL - total)) | |||
| ? 0xFFFFFFFFUL : total + elapsed; | |||
| if (elapsed > sample->maxCycles) | |||
| { | |||
| sample->maxCycles = elapsed; | |||
| } | |||
| } | |||
| void PlsrPlannerTimingReset(void) | |||
| { | |||
| (void)memset((void *)&PlsrPlannerTiming, 0, sizeof(PlsrPlannerTiming)); | |||
| } | |||
| #endif | |||
| static const uint32_t PlsrPlannerSmoothIntegralQ24[65] = | |||
| { | |||
| 0UL, 64UL, 504UL, 1688UL, 3968UL, 7688UL, 13176UL, 20752UL, | |||
| @@ -402,38 +443,86 @@ static void PlsrPlannerStartRamp(PLSR_PLANNER_CONTEXT *context, | |||
| uint32_t toHz, | |||
| uint32_t pulseCount) | |||
| { | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| uint32_t totalStartedAt = PlsrPlannerTimingNow(); | |||
| uint32_t phaseStartedAt; | |||
| #endif | |||
| context->rampKind = rampKind; | |||
| context->rampRelativePulse = 0UL; | |||
| context->rampPulseCount = pulseCount; | |||
| context->rampFromHz = fromHz; | |||
| context->rampToHz = toHz; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| context->rampDurationMs = PlsrPlannerRampTime(&context->block, fromHz, toHz); | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampTime, phaseStartedAt); | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| context->rampTotalAreaQ32 = PlsrPlannerRampAreaQ32( | |||
| context, fromHz, toHz, PLSR_PLANNER_Q32_ONE); | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampTotalArea, | |||
| phaseStartedAt); | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| context->rampAreaStepQ32 = context->rampTotalAreaQ32 / pulseCount; | |||
| context->rampAreaRemainder = | |||
| (uint32_t)(context->rampTotalAreaQ32 % pulseCount); | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampAreaSplit, | |||
| phaseStartedAt); | |||
| #endif | |||
| context->rampRemainderAccumulator = 0UL; | |||
| context->rampTargetAreaQ32 = 0ULL; | |||
| context->rampBoundaryQ32 = 0ULL; | |||
| context->rampActualTimeQ32 = 0ULL; | |||
| context->rampLastPhaseStepQ32 = 0ULL; | |||
| context->lastRampHz = 0UL; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| context->rampFirstBoundaryQ32 = PlsrPlannerExactBoundaryQ32( | |||
| context, 0ULL, context->rampAreaStepQ32); | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampFirstBoundary, | |||
| phaseStartedAt); | |||
| #endif | |||
| if (pulseCount > 1UL) | |||
| { | |||
| uint64_t secondTargetAreaQ32 = context->rampAreaStepQ32 * 2ULL | |||
| uint64_t secondTargetAreaQ32; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| secondTargetAreaQ32 = context->rampAreaStepQ32 * 2ULL | |||
| + ((uint64_t)context->rampAreaRemainder * 2ULL) / pulseCount; | |||
| context->rampSecondBoundaryQ32 = PlsrPlannerExactBoundaryQ32( | |||
| context, context->rampFirstBoundaryQ32, | |||
| secondTargetAreaQ32); | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampSecondBoundary, | |||
| phaseStartedAt); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| context->rampSecondBoundaryQ32 = PLSR_PLANNER_Q32_ONE; | |||
| } | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.startRamp, totalStartedAt); | |||
| #endif | |||
| } | |||
| static uint8_t PlsrPlannerSameSetting( | |||
| @@ -452,6 +541,12 @@ static uint8_t PlsrPlannerBuildStep(PLSR_PLANNER_CONTEXT *context, | |||
| PLSR_PLATFORM_TIMER_SETTING *setting, | |||
| uint32_t *normalizedRequestedHz) | |||
| { | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| uint32_t startedAt; | |||
| uint8_t result; | |||
| #endif | |||
| if (requestedHz == 0UL) | |||
| { | |||
| requestedHz = 1UL; | |||
| @@ -461,9 +556,19 @@ static uint8_t PlsrPlannerBuildStep(PLSR_PLANNER_CONTEXT *context, | |||
| requestedHz = PLSR_FREQUENCY_MAX_HZ; | |||
| } | |||
| *normalizedRequestedHz = requestedHz; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| startedAt = PlsrPlannerTimingNow(); | |||
| result = PlsrPlatformBuildTimerSetting(context->block.pulseOutput, | |||
| PLSR_OUTPUT_PULSE_DIR, | |||
| requestedHz, setting); | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.timerSetting, startedAt); | |||
| return result; | |||
| #else | |||
| return PlsrPlatformBuildTimerSetting(context->block.pulseOutput, | |||
| PLSR_OUTPUT_PULSE_DIR, | |||
| requestedHz, setting); | |||
| #endif | |||
| } | |||
| static uint8_t PlsrPlannerTakeRampStep( | |||
| @@ -476,6 +581,11 @@ static uint8_t PlsrPlannerTakeRampStep( | |||
| uint64_t denominator; | |||
| uint64_t requestedHz; | |||
| uint64_t actualDeltaQ32; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| uint32_t totalStartedAt = PlsrPlannerTimingNow(); | |||
| uint32_t phaseStartedAt; | |||
| #endif | |||
| context->rampTargetAreaQ32 += context->rampAreaStepQ32; | |||
| context->rampRemainderAccumulator += context->rampAreaRemainder; | |||
| @@ -499,8 +609,17 @@ static uint8_t PlsrPlannerTakeRampStep( | |||
| } | |||
| else | |||
| { | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| nextBoundaryQ32 = PlsrPlannerPredictedBoundaryQ32( | |||
| context, context->rampTargetAreaQ32); | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampPredictedBoundary, | |||
| phaseStartedAt); | |||
| #endif | |||
| } | |||
| desiredDeltaQ32 = (nextBoundaryQ32 > context->rampActualTimeQ32) | |||
| @@ -509,11 +628,20 @@ static uint8_t PlsrPlannerTakeRampStep( | |||
| /* The allocated pulse count closes the ramp area exactly. Derive the | |||
| physical duration from N/averageHz instead of rounding it to whole | |||
| milliseconds; short clipped ramps can be well below 1 ms. */ | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| denominator = (uint64_t)context->rampPulseCount * desiredDeltaQ32; | |||
| requestedHz = (denominator == 0ULL) | |||
| ? context->rampToHz | |||
| : (context->rampTotalAreaQ32 | |||
| + denominator / 2ULL) / denominator; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampRequestedDivide, | |||
| phaseStartedAt); | |||
| #endif | |||
| if (requestedHz == 0ULL) | |||
| { | |||
| requestedHz = 1ULL; | |||
| @@ -533,21 +661,39 @@ static uint8_t PlsrPlannerTakeRampStep( | |||
| if (PlsrPlannerBuildStep(context, (uint32_t)requestedHz, setting, | |||
| requestedFrequencyHz) == 0U) | |||
| { | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampStep, | |||
| totalStartedAt); | |||
| #endif | |||
| return 0U; | |||
| } | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| phaseStartedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| denominator = (uint64_t)context->rampPulseCount | |||
| * setting->actualFrequencyHz; | |||
| actualDeltaQ32 = (denominator == 0ULL) | |||
| ? desiredDeltaQ32 | |||
| : (context->rampTotalAreaQ32 | |||
| + denominator / 2ULL) / denominator; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampActualDivide, | |||
| phaseStartedAt); | |||
| #endif | |||
| context->rampActualTimeQ32 += actualDeltaQ32; | |||
| context->rampLastPhaseStepQ32 = | |||
| nextBoundaryQ32 - context->rampBoundaryQ32; | |||
| context->rampBoundaryQ32 = nextBoundaryQ32; | |||
| context->lastRampHz = setting->actualFrequencyHz; | |||
| context->rampRelativePulse++; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.rampStep, totalStartedAt); | |||
| #endif | |||
| return 1U; | |||
| } | |||
| @@ -602,6 +748,10 @@ PLSR_PLANNER_STATUS PlsrPlannerBegin(PLSR_PLANNER_CONTEXT *context, | |||
| uint64_t exitWeight; | |||
| uint64_t totalWeight; | |||
| uint64_t scaledEntry; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| uint32_t startedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| if ((context == NULL) || (block == NULL) | |||
| || (block->pulseBudget == 0UL) | |||
| @@ -614,6 +764,10 @@ PLSR_PLANNER_STATUS PlsrPlannerBegin(PLSR_PLANNER_CONTEXT *context, | |||
| || (appliedHz > PLSR_FREQUENCY_MAX_HZ) | |||
| || (block->curveMode > 2U) || (block->pulseOutput > 3U)) | |||
| { | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.begin, startedAt); | |||
| #endif | |||
| return PLSR_PLANNER_INVALID; | |||
| } | |||
| @@ -640,6 +794,10 @@ PLSR_PLANNER_STATUS PlsrPlannerBegin(PLSR_PLANNER_CONTEXT *context, | |||
| context->entryPulses = block->pulseBudget; | |||
| context->clipped = 1U; | |||
| context->active = 1U; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.begin, startedAt); | |||
| #endif | |||
| return PLSR_PLANNER_CLIPPED; | |||
| } | |||
| @@ -695,6 +853,10 @@ PLSR_PLANNER_STATUS PlsrPlannerBegin(PLSR_PLANNER_CONTEXT *context, | |||
| context->clipped = 1U; | |||
| } | |||
| context->active = 1U; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.begin, startedAt); | |||
| #endif | |||
| return (context->clipped != 0U) ? PLSR_PLANNER_CLIPPED | |||
| : PLSR_PLANNER_OK; | |||
| } | |||
| @@ -707,10 +869,18 @@ uint16_t PlsrPlannerGenerate(PLSR_PLANNER_CONTEXT *context,//规划账本:三 | |||
| uint32_t requestedFrequencyHz; | |||
| uint32_t repeatCount; | |||
| uint16_t produced = 0U; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| uint32_t startedAt = PlsrPlannerTimingNow(); | |||
| #endif | |||
| if ((context == NULL) || (output == NULL) || (capacity == 0U) | |||
| || (context->active == 0U)) | |||
| { | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.generate, startedAt); | |||
| #endif | |||
| return 0U; | |||
| } | |||
| while ((produced < capacity)&& (context->generatedPulses < context->block.pulseBudget)) | |||
| @@ -746,6 +916,10 @@ uint16_t PlsrPlannerGenerate(PLSR_PLANNER_CONTEXT *context,//规划账本:三 | |||
| { | |||
| context->active = 0U; | |||
| } | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| PlsrPlannerTimingRecord(&PlsrPlannerTiming.generate, startedAt); | |||
| #endif | |||
| return produced; | |||
| } | |||
| @@ -95,6 +95,38 @@ typedef struct | |||
| uint8_t active; // 是否还可 Generate,吐完或失败清 0 | |||
| } PLSR_PLANNER_CONTEXT; | |||
| #if defined(PLSR_DEBUG_TIMING) && (PLSR_DEBUG_TIMING != 0) \ | |||
| && !defined(PLSR_HOST_TEST) | |||
| typedef struct | |||
| { | |||
| volatile uint32_t callCount; | |||
| volatile uint32_t lastCycles; | |||
| volatile uint32_t totalCycles; | |||
| volatile uint32_t minCycles; | |||
| volatile uint32_t maxCycles; | |||
| } PLSR_PLANNER_TIMING_SAMPLE; | |||
| typedef struct | |||
| { | |||
| PLSR_PLANNER_TIMING_SAMPLE begin; | |||
| PLSR_PLANNER_TIMING_SAMPLE generate; | |||
| PLSR_PLANNER_TIMING_SAMPLE startRamp; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampTime; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampTotalArea; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampAreaSplit; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampFirstBoundary; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampSecondBoundary; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampPredictedBoundary; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampRequestedDivide; | |||
| PLSR_PLANNER_TIMING_SAMPLE timerSetting; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampActualDivide; | |||
| PLSR_PLANNER_TIMING_SAMPLE rampStep; | |||
| } PLSR_PLANNER_TIMING; | |||
| extern volatile PLSR_PLANNER_TIMING PlsrPlannerTiming; | |||
| void PlsrPlannerTimingReset(void); | |||
| #endif | |||
| PLSR_PLANNER_STATUS PlsrPlannerBegin(PLSR_PLANNER_CONTEXT *context, | |||
| const PLSR_MOTION_BLOCK *block, | |||
| uint32_t appliedHz, | |||
| @@ -1611,8 +1611,12 @@ volatile uint32_t PlsrFinalArmJobMaxCycles[4]; | |||
| volatile uint32_t PlsrFinalArmQueueToStopLastCycles[4]; | |||
| volatile uint32_t PlsrFinalArmQueueToStopMaxCycles[4]; | |||
| volatile uint32_t PlsrFiniteBlockIrqCount[4]; | |||
| volatile uint32_t PlsrFiniteBlockIrqLastCycles[4]; | |||
| volatile uint32_t PlsrFiniteBlockIrqTotalCycles[4]; | |||
| volatile uint32_t PlsrFiniteBlockIrqMaxCycles[4]; | |||
| volatile uint32_t PlsrFiniteFinalIrqCount[4]; | |||
| volatile uint32_t PlsrFiniteFinalIrqLastCycles[4]; | |||
| volatile uint32_t PlsrFiniteFinalIrqTotalCycles[4]; | |||
| volatile uint32_t PlsrFiniteFinalIrqMaxCycles[4]; | |||
| volatile uint32_t PlsrAbReloadCounterBefore[4]; | |||
| volatile uint32_t PlsrAbReloadCounterArmed[4]; | |||
| @@ -2910,6 +2914,22 @@ uint8_t PlsrPlatformInit(void) | |||
| sizeof(PlsrFinalArmQueuedAt)); | |||
| (void)memset((void *)PlsrFinalArmQueueTimingPending, 0, | |||
| sizeof(PlsrFinalArmQueueTimingPending)); | |||
| (void)memset((void *)PlsrFiniteBlockIrqCount, 0, | |||
| sizeof(PlsrFiniteBlockIrqCount)); | |||
| (void)memset((void *)PlsrFiniteBlockIrqLastCycles, 0, | |||
| sizeof(PlsrFiniteBlockIrqLastCycles)); | |||
| (void)memset((void *)PlsrFiniteBlockIrqTotalCycles, 0, | |||
| sizeof(PlsrFiniteBlockIrqTotalCycles)); | |||
| (void)memset((void *)PlsrFiniteBlockIrqMaxCycles, 0, | |||
| sizeof(PlsrFiniteBlockIrqMaxCycles)); | |||
| (void)memset((void *)PlsrFiniteFinalIrqCount, 0, | |||
| sizeof(PlsrFiniteFinalIrqCount)); | |||
| (void)memset((void *)PlsrFiniteFinalIrqLastCycles, 0, | |||
| sizeof(PlsrFiniteFinalIrqLastCycles)); | |||
| (void)memset((void *)PlsrFiniteFinalIrqTotalCycles, 0, | |||
| sizeof(PlsrFiniteFinalIrqTotalCycles)); | |||
| (void)memset((void *)PlsrFiniteFinalIrqMaxCycles, 0, | |||
| sizeof(PlsrFiniteFinalIrqMaxCycles)); | |||
| #endif | |||
| HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | |||
| @@ -5110,10 +5130,19 @@ static void PlsrHandleCounterIrq(uint8_t counterIndex) | |||
| #if PLSR_DEBUG_TIMING | |||
| { | |||
| uint32_t elapsedCycles = DWT->CYCCNT - startedAt; | |||
| uint32_t totalCycles; | |||
| if (PlsrFiniteCompletionPending[owner] != 0U) | |||
| { | |||
| totalCycles = PlsrFiniteFinalIrqTotalCycles[owner]; | |||
| if (PlsrFiniteFinalIrqCount[owner] != 0xFFFFFFFFUL) | |||
| { | |||
| PlsrFiniteFinalIrqCount[owner]++; | |||
| } | |||
| PlsrFiniteFinalIrqLastCycles[owner] = elapsedCycles; | |||
| PlsrFiniteFinalIrqTotalCycles[owner] = | |||
| (elapsedCycles > (0xFFFFFFFFUL - totalCycles)) | |||
| ? 0xFFFFFFFFUL : totalCycles + elapsedCycles; | |||
| if (elapsedCycles > PlsrFiniteFinalIrqMaxCycles[owner]) | |||
| { | |||
| PlsrFiniteFinalIrqMaxCycles[owner] = elapsedCycles; | |||
| @@ -5121,7 +5150,15 @@ static void PlsrHandleCounterIrq(uint8_t counterIndex) | |||
| } | |||
| else | |||
| { | |||
| PlsrFiniteBlockIrqCount[owner]++; | |||
| totalCycles = PlsrFiniteBlockIrqTotalCycles[owner]; | |||
| if (PlsrFiniteBlockIrqCount[owner] != 0xFFFFFFFFUL) | |||
| { | |||
| PlsrFiniteBlockIrqCount[owner]++; | |||
| } | |||
| PlsrFiniteBlockIrqLastCycles[owner] = elapsedCycles; | |||
| PlsrFiniteBlockIrqTotalCycles[owner] = | |||
| (elapsedCycles > (0xFFFFFFFFUL - totalCycles)) | |||
| ? 0xFFFFFFFFUL : totalCycles + elapsedCycles; | |||
| if (elapsedCycles > PlsrFiniteBlockIrqMaxCycles[owner]) | |||
| { | |||
| PlsrFiniteBlockIrqMaxCycles[owner] = elapsedCycles; | |||