force a pwm cycle start (skip cycles) if late (#2097)

* skip cycles if late

* fail at lower count

* start at -1
This commit is contained in:
Matthew Kennedy 2020-12-18 05:21:18 -08:00 committed by GitHub
parent f37c318c04
commit 7277b04039
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 6 deletions

View File

@ -160,13 +160,15 @@ void PwmConfig::handleCycleStart() {
efiAssertVoid(CUSTOM_ERR_6580, periodNt != 0, "period not initialized");
efiAssertVoid(CUSTOM_ERR_6580, iterationLimit > 0, "iterationLimit invalid");
if (safe.periodNt != periodNt || safe.iteration == iterationLimit) {
if (forceCycleStart || safe.periodNt != periodNt || safe.iteration == iterationLimit) {
/**
* period length has changed - we need to reset internal state
*/
safe.startNt = getTimeNowNt();
safe.iteration = 0;
safe.periodNt = periodNt;
forceCycleStart = false;
#if DEBUG_PWM
scheduleMsg(&logger, "state reset start=%d iteration=%d", state->safe.start, state->safe.iteration);
#endif
@ -225,10 +227,18 @@ efitick_t PwmConfig::togglePwmState() {
scheduleMsg(&logger, "%s: nextSwitchTime %d", state->name, nextSwitchTime);
#endif /* DEBUG_PWM */
// If we're very far behind schedule, restart the cycle fresh to avoid scheduling a huge pile of events all at once
// This can happen during config write or debugging where CPU is halted for multiple seconds
bool isVeryBehindSchedule = nextSwitchTimeNt < getTimeNowNt() - MS2NT(10);
safe.phaseIndex++;
if (safe.phaseIndex == phaseCount || mode != PM_NORMAL) {
if (isVeryBehindSchedule || safe.phaseIndex == phaseCount || mode != PM_NORMAL) {
safe.phaseIndex = 0; // restart
safe.iteration++;
if (isVeryBehindSchedule) {
forceCycleStart = true;
}
}
#if EFI_UNIT_TEST
printf("PWM: nextSwitchTimeNt=%d phaseIndex=%d iteration=%d\r\n", nextSwitchTimeNt,

View File

@ -110,6 +110,9 @@ private:
* PWM generation is not happening while this value is NAN
*/
float periodNt;
// Set if we are very far behind schedule and need to reset back to the beginning of a cycle to find our way
bool forceCycleStart = true;
};
struct hardware_pwm;

View File

@ -123,16 +123,21 @@ void SingleTimerExecutor::executeAllPendingActions() {
* TODO: add a counter & figure out a limit of iterations?
*/
executeCounter = 0;
// starts at -1 because do..while will run a minimum of once
executeCounter = -1;
bool didExecute;
do {
efitick_t nowNt = getTimeNowNt();
didExecute = queue.executeOne(nowNt);
if (executeCounter++ == 10000) {
firmwareError(CUSTOM_ERR_LOCK_ISSUE, "Looks like firmware is really busy");
// if we're stuck in a loop executing lots of events, panic!
if (executeCounter++ == 500) {
firmwareError(CUSTOM_ERR_LOCK_ISSUE, "Maximum scheduling run length exceeded - CPU load too high");
}
} while (didExecute);
maxExecuteCounter = maxI(maxExecuteCounter, executeCounter);
if (!isLocked()) {
@ -169,7 +174,7 @@ void initSingleTimerExecutorHardware(void) {
void executorStatistics() {
if (engineConfiguration->debugMode == DBG_EXECUTOR) {
#if EFI_TUNER_STUDIO && EFI_SIGNAL_EXECUTOR_ONE_TIMER
#if EFI_TUNER_STUDIO
tsOutputChannels.debugIntField1 = ___engine.executor.timerCallbackCounter;
tsOutputChannels.debugIntField2 = ___engine.executor.executeAllPendingActionsInvocationCounter;
tsOutputChannels.debugIntField3 = ___engine.executor.scheduleCounter;