diff --git a/firmware/controllers/algo/event_registry.h b/firmware/controllers/algo/event_registry.h index bf8640f167..edcb4ba60c 100644 --- a/firmware/controllers/algo/event_registry.h +++ b/firmware/controllers/algo/event_registry.h @@ -91,7 +91,7 @@ public: /** * Ignition scheduler maintains a linked list of all pending ignition events. */ - IgnitionEvent *next = nullptr; + IgnitionEvent *nextIgnitionEvent = nullptr; /** * Sequential number of currently processed spark event * @see globalSparkIdCounter diff --git a/firmware/controllers/scheduling/event_queue.cpp b/firmware/controllers/scheduling/event_queue.cpp index d39cba69b5..4974a0379e 100644 --- a/firmware/controllers/scheduling/event_queue.cpp +++ b/firmware/controllers/scheduling/event_queue.cpp @@ -30,7 +30,7 @@ EventQueue::EventQueue() { } bool EventQueue::checkIfPending(scheduling_s *scheduling) { - return assertNotInList(head, scheduling); + assertNotInListMethodBody(scheduling_s, head, scheduling, nextScheduling_s); } /** @@ -63,7 +63,7 @@ bool EventQueue::insertTask(scheduling_s *scheduling, efitime_t timeX, schfunc_t if (head == NULL || timeX < head->momentX) { // here we insert into head of the linked list - LL_PREPEND(head, scheduling); + LL_PREPEND2(head, scheduling, nextScheduling_s); #if EFI_UNIT_TEST assertListIsSorted(); #endif /* EFI_UNIT_TEST */ @@ -71,12 +71,12 @@ bool EventQueue::insertTask(scheduling_s *scheduling, efitime_t timeX, schfunc_t } else { // here we know we are not in the head of the list, let's find the position - linear search scheduling_s *insertPosition = head; - while (insertPosition->next != NULL && insertPosition->next->momentX < timeX) { - insertPosition = insertPosition->next; + while (insertPosition->nextScheduling_s != NULL && insertPosition->nextScheduling_s->momentX < timeX) { + insertPosition = insertPosition->nextScheduling_s; } - scheduling->next = insertPosition->next; - insertPosition->next = scheduling; + scheduling->nextScheduling_s = insertPosition->nextScheduling_s; + insertPosition->nextScheduling_s = scheduling; #if EFI_UNIT_TEST assertListIsSorted(); #endif /* EFI_UNIT_TEST */ @@ -132,7 +132,7 @@ int EventQueue::executeAll(efitime_t now) { int listIterationCounter = 0; int executionCounter = 0; // we need safe iteration because we are removing elements inside the loop - LL_FOREACH_SAFE(head, current, tmp) + LL_FOREACH_SAFE2(head, current, tmp, nextScheduling_s) { efiAssert(CUSTOM_ERR_ASSERT, current->callback != NULL, "callback==null1", 0); if (++listIterationCounter > QUEUE_LENGTH_LIMIT) { @@ -143,14 +143,14 @@ int EventQueue::executeAll(efitime_t now) { executionCounter++; efiAssert(CUSTOM_ERR_ASSERT, head == current, "removing from head", -1); //LL_DELETE(head, current); - head = head->next; + head = head->nextScheduling_s; if (executionList == NULL) { lastInExecutionList = executionList = current; } else { - lastInExecutionList->next = current; + lastInExecutionList->nextScheduling_s = current; lastInExecutionList = current; } - current->next = nullptr; + current->nextScheduling_s = nullptr; } else { /** * The list is sorted. Once we find one action in the future, all the remaining ones @@ -167,7 +167,7 @@ int EventQueue::executeAll(efitime_t now) { * we need safe iteration here because 'callback' might change change 'current->next' * while re-inserting it into the queue from within the callback */ - LL_FOREACH_SAFE(executionList, current, tmp) + LL_FOREACH_SAFE2(executionList, current, tmp, nextScheduling_s) { efiAssert(CUSTOM_ERR_ASSERT, current->callback != NULL, "callback==null2", 0); uint32_t before = getTimeNowLowerNt(); @@ -198,16 +198,16 @@ int EventQueue::executeAll(efitime_t now) { int EventQueue::size(void) const { scheduling_s *tmp; int result; - LL_COUNT(head, tmp, result); + LL_COUNT2(head, tmp, result, nextScheduling_s); return result; } #if EFI_UNIT_TEST void EventQueue::assertListIsSorted() const { scheduling_s *current = head; - while (current != NULL && current->next != NULL) { - efiAssertVoid(CUSTOM_ERR_6623, current->momentX <= current->next->momentX, "list order"); - current = current->next; + while (current != NULL && current->nextScheduling_s != NULL) { + efiAssertVoid(CUSTOM_ERR_6623, current->momentX <= current->nextScheduling_s->momentX, "list order"); + current = current->nextScheduling_s; } } #endif @@ -223,7 +223,7 @@ scheduling_s * EventQueue::getHead() { scheduling_s *EventQueue::getForUnitText(int index) { scheduling_s * current; - LL_FOREACH(head, current) + LL_FOREACH2(head, current, nextScheduling_s) { if (index == 0) return current; diff --git a/firmware/controllers/scheduling/event_queue.h b/firmware/controllers/scheduling/event_queue.h index ba8a56cf07..1ab88e45f3 100644 --- a/firmware/controllers/scheduling/event_queue.h +++ b/firmware/controllers/scheduling/event_queue.h @@ -18,29 +18,28 @@ #define QUEUE_LENGTH_LIMIT 1000 -template -bool assertNotInList(T *head, T*element) { - // this code is just to validate state, no functional load - T * current; - int counter = 0; - LL_FOREACH(head, current) - { - if (++counter > QUEUE_LENGTH_LIMIT) { - firmwareError(CUSTOM_ERR_LOOPED_QUEUE, "Looped queue?"); - return false; - } - if (current == element) { - /** - * for example, this might happen in case of sudden RPM change if event - * was not scheduled by angle but was scheduled by time. In case of scheduling - * by time with slow RPM the whole next fast revolution might be within the wait period - */ - warning(CUSTOM_RE_ADDING_INTO_EXECUTION_QUEUE, "re-adding element into event_queue"); - return true; - } - } +// templates do not accept field names so we use a macro here +#define assertNotInListMethodBody(T, head, element, field) \ + /* this code is just to validate state, no functional load*/ \ + T * current; \ + int counter = 0; \ + LL_FOREACH2(head, current, field) { \ + if (++counter > QUEUE_LENGTH_LIMIT) { \ + firmwareError(CUSTOM_ERR_LOOPED_QUEUE, "Looped queue?"); \ + return false; \ + } \ + if (current == element) { \ + /** \ + * for example, this might happen in case of sudden RPM change if event \ + * was not scheduled by angle but was scheduled by time. In case of scheduling \ + * by time with slow RPM the whole next fast revolution might be within the wait period \ + */ \ + warning(CUSTOM_RE_ADDING_INTO_EXECUTION_QUEUE, "re-adding element into event_queue"); \ + return true; \ + } \ + } \ return false; -} + /** * Execution sorted linked list diff --git a/firmware/controllers/scheduling/scheduler.h b/firmware/controllers/scheduling/scheduler.h index 1aa0b275fc..77a0b71029 100644 --- a/firmware/controllers/scheduling/scheduler.h +++ b/firmware/controllers/scheduling/scheduler.h @@ -28,7 +28,7 @@ public: /** * Scheduler implementation uses a sorted linked list of these scheduling records. */ - scheduling_s *next = nullptr; + scheduling_s *nextScheduling_s = nullptr; schfunc_t callback = nullptr; void *param = nullptr; diff --git a/firmware/controllers/trigger/spark_logic.cpp b/firmware/controllers/trigger/spark_logic.cpp index 82cc763f46..5995af6963 100644 --- a/firmware/controllers/trigger/spark_logic.cpp +++ b/firmware/controllers/trigger/spark_logic.cpp @@ -215,6 +215,10 @@ void turnSparkPinHigh(IgnitionEvent *event) { } } +static bool assertNotInIgnitionList(IgnitionEvent *head, IgnitionEvent *element) { + assertNotInListMethodBody(IgnitionEvent, head, element, nextIgnitionEvent) +} + static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent, int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) { @@ -315,7 +319,7 @@ static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventI /** * Spark should be scheduled in relation to some future trigger event, this way we get better firing precision */ - bool isPending = assertNotInList(ENGINE(ignitionEventsHead), iEvent); + bool isPending = assertNotInIgnitionList(ENGINE(ignitionEventsHead), iEvent); if (isPending) { #if SPARK_EXTREME_LOGGING scheduleMsg(logger, "not adding to queue sparkDown ind=%d %d %s %d", trgEventIndex, getRevolutionCounter(), iEvent->getOutputForLoggins()->name, (int)getTimeNowUs()); @@ -323,7 +327,7 @@ static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventI return; } - LL_APPEND(ENGINE(ignitionEventsHead), iEvent); + LL_APPEND2(ENGINE(ignitionEventsHead), iEvent, nextIgnitionEvent); } } @@ -383,11 +387,11 @@ static ALWAYS_INLINE void prepareIgnitionSchedule(DECLARE_ENGINE_PARAMETER_SIGNA static void scheduleAllSparkEventsUntilNextTriggerTooth(uint32_t trgEventIndex DECLARE_ENGINE_PARAMETER_SUFFIX) { IgnitionEvent *current, *tmp; - LL_FOREACH_SAFE(ENGINE(ignitionEventsHead), current, tmp) + LL_FOREACH_SAFE2(ENGINE(ignitionEventsHead), current, tmp, nextIgnitionEvent) { if (current->sparkPosition.triggerEventIndex == trgEventIndex) { // time to fire a spark which was scheduled previously - LL_DELETE(ENGINE(ignitionEventsHead), current); + LL_DELETE2(ENGINE(ignitionEventsHead), current, nextIgnitionEvent); scheduling_s * sDown = ¤t->signalTimerDown; diff --git a/unit_tests/tests/test_signal_executor.cpp b/unit_tests/tests/test_signal_executor.cpp index f40e49b051..3c35b17759 100644 --- a/unit_tests/tests/test_signal_executor.cpp +++ b/unit_tests/tests/test_signal_executor.cpp @@ -108,9 +108,9 @@ TEST(misc, testSignalExecutor) { ASSERT_EQ(4, eq.size()); ASSERT_EQ(10, eq.getHead()->momentX); - ASSERT_EQ(10, eq.getHead()->next->momentX); - ASSERT_EQ(11, eq.getHead()->next->next->momentX); - ASSERT_EQ(12, eq.getHead()->next->next->next->momentX); + ASSERT_EQ(10, eq.getHead()->nextScheduling_s->momentX); + ASSERT_EQ(11, eq.getHead()->nextScheduling_s->nextScheduling_s->momentX); + ASSERT_EQ(12, eq.getHead()->nextScheduling_s->nextScheduling_s->nextScheduling_s->momentX); callbackCounter = 0; eq.executeAll(10);