diff --git a/firmware/controllers/algo/event_registry.h b/firmware/controllers/algo/event_registry.h index 2d7c932b17..bf417ebbb2 100644 --- a/firmware/controllers/algo/event_registry.h +++ b/firmware/controllers/algo/event_registry.h @@ -58,6 +58,9 @@ class FuelSchedule { public: FuelSchedule(); + // Call this function if something happens that requires a rebuild, like a change to the trigger pattern + void invalidate(); + // Call this every trigger tooth. It will schedule all required injector events. void onTriggerTooth(size_t toothIndex, int rpm, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); @@ -73,10 +76,7 @@ public: * injection events, per cylinder */ InjectionEvent elements[MAX_INJECTION_OUTPUT_COUNT]; - bool isReady; - -private: - void clear(); + bool isReady = false; }; class AngleBasedEvent { diff --git a/firmware/controllers/engine_cycle/fuel_schedule.cpp b/firmware/controllers/engine_cycle/fuel_schedule.cpp index 335f356d91..79a7e62084 100644 --- a/firmware/controllers/engine_cycle/fuel_schedule.cpp +++ b/firmware/controllers/engine_cycle/fuel_schedule.cpp @@ -14,14 +14,13 @@ EXTERN_ENGINE; #if EFI_ENGINE_CONTROL FuelSchedule::FuelSchedule() { - clear(); for (int cylinderIndex = 0; cylinderIndex < MAX_INJECTION_OUTPUT_COUNT; cylinderIndex++) { InjectionEvent *ev = &elements[cylinderIndex]; ev->ownIndex = cylinderIndex; } } -void FuelSchedule::clear() { +void FuelSchedule::invalidate() { isReady = false; } @@ -142,19 +141,26 @@ bool FuelSchedule::addFuelEventsForCylinder(int i DECLARE_ENGINE_PARAMETER_SUFF } void FuelSchedule::addFuelEvents(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - clear(); - for (int cylinderIndex = 0; cylinderIndex < CONFIG(specs.cylindersCount); cylinderIndex++) { InjectionEvent *ev = &elements[cylinderIndex]; ev->ownIndex = cylinderIndex; // todo: is this assignment needed here? we now initialize in constructor bool result = addFuelEventsForCylinder(cylinderIndex PASS_ENGINE_PARAMETER_SUFFIX); - if (!result) + if (!result) { + invalidate(); return; + } } + + // We made it through all cylinders, mark the schedule as ready so it can be used isReady = true; } void FuelSchedule::onTriggerTooth(size_t toothIndex, int rpm, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { + // Wait for schedule to be built - this happens the first time we get RPM + if (!isReady) { + return; + } + for (int i = 0; i < CONFIG(specs.cylindersCount); i++) { elements[i].onTriggerTooth(toothIndex, rpm, nowNt); } diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp index 7be0ef4740..18b14da37e 100644 --- a/firmware/controllers/math/engine_math.cpp +++ b/firmware/controllers/math/engine_math.cpp @@ -412,6 +412,9 @@ void prepareOutputSignals(DECLARE_ENGINE_PARAMETER_SIGNATURE) { prepareIgnitionPinIndices(CONFIG(ignitionMode) PASS_ENGINE_PARAMETER_SUFFIX); TRIGGER_WAVEFORM(prepareShape(&ENGINE(triggerCentral.triggerFormDetails) PASS_ENGINE_PARAMETER_SUFFIX)); + + // Fuel schedule may now be completely wrong, force a reset + ENGINE(injectionEvents).invalidate(); } void setTimingRpmBin(float from, float to DECLARE_CONFIG_PARAMETER_SUFFIX) { diff --git a/firmware/controllers/trigger/decoders/trigger_structure.cpp b/firmware/controllers/trigger/decoders/trigger_structure.cpp index 35f7feefe3..1e78814811 100644 --- a/firmware/controllers/trigger/decoders/trigger_structure.cpp +++ b/firmware/controllers/trigger/decoders/trigger_structure.cpp @@ -418,8 +418,13 @@ void findTriggerPosition(TriggerWaveform *triggerShape, return; } - position->triggerEventIndex = triggerEventIndex; - position->angleOffsetFromTriggerEvent = angle - triggerEventAngle; + { + // This must happen under lock so that the tooth and offset don't get partially read and mismatched + chibios_rt::CriticalSectionLocker csl; + + position->triggerEventIndex = triggerEventIndex; + position->angleOffsetFromTriggerEvent = angle - triggerEventAngle; + } } void TriggerWaveform::prepareShape(TriggerFormDetails *details DECLARE_ENGINE_PARAMETER_SUFFIX) {