From e9cbbdbfb629c398db2cef324cbeed5388c9c820 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:21:04 +0100 Subject: [PATCH 01/35] fix (tested on PCU, LV-BMS and LCU) --- Inc/HALAL/Services/Time/Scheduler.hpp | 4 +-- Src/HALAL/Services/Time/Scheduler.cpp | 49 ++++++++++++++++----------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index dfabc0bdb..e964ae8c0 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -33,9 +33,7 @@ struct Scheduler { // temporary, will be removed [[deprecated]] static inline void start() {} static void update(); - static inline uint64_t get_global_tick() { - return global_tick_us_ + Scheduler_global_timer->CNT; - } + static inline uint64_t get_global_tick(); static uint16_t register_task(uint32_t period_us, callback_t func); static bool unregister_task(uint16_t id); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 62a2333ad..15b7594cb 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -1,5 +1,5 @@ /* - * Scheduler.hpp + * Scheduler.cpp * * Created on: 17 nov. 2025 * Author: Victor (coauthor Stephan) @@ -32,13 +32,11 @@ uint32_t Scheduler::current_interval_us_{0}; uint16_t Scheduler::timeout_idx_{1}; inline uint8_t Scheduler::get_at(uint8_t idx) { - int word_idx = idx > 7; - uint32_t shift = (idx & 7) << 2; - return (((uint32_t*)&sorted_task_ids_)[word_idx] & (0x0F << shift)) >> shift; + return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); } inline void Scheduler::set_at(uint8_t idx, uint8_t id) { uint32_t shift = idx * 4; - uint64_t clearmask = ~(0xFF << shift); + uint64_t clearmask = ~(0xFFULL << shift); Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); } inline uint8_t Scheduler::front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } @@ -159,18 +157,25 @@ void Scheduler::update() { while (ready_bitmap_ != 0u) { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); - CLEAR_BIT(ready_bitmap_, 1u << bit_index); - Task& task = tasks_[bit_index]; task.callback(); + + SchedLock(); + CLEAR_BIT(ready_bitmap_, 1u << bit_index); if (!task.repeating) [[unlikely]] { - SchedLock(); release_slot(static_cast(bit_index)); - SchedUnlock(); } + SchedUnlock(); } } +inline uint64_t Scheduler::get_global_tick() { + SchedLock(); + uint64_t val = global_tick_us_ + Scheduler_global_timer->CNT; + SchedUnlock(); + return val; +} + inline uint8_t Scheduler::allocate_slot() { uint32_t idx = __builtin_ffs(Scheduler::free_bitmap_) - 1; if (idx > static_cast(Scheduler::kMaxTasks)) [[unlikely]] @@ -272,24 +277,27 @@ void Scheduler::schedule_next_interval() { return; } + SchedLock(); uint8_t next_id = Scheduler::front_id(); // sorted_task_ids_[0] Task& next_task = tasks_[next_id]; int32_t diff = (int32_t)(next_task.next_fire_us - static_cast(global_tick_us_)); + SchedUnlock(); + if (diff >= -1 && diff <= 1) [[unlikely]] { current_interval_us_ = 1; SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt } else { if (diff < -1) [[unlikely]] { - current_interval_us_ = static_cast(0 - diff); + current_interval_us_ = static_cast(0 - diff) - 1u; } else { - current_interval_us_ = static_cast(diff); + current_interval_us_ = static_cast(diff) - 1u; } - Scheduler_global_timer->ARR = static_cast(current_interval_us_ - 1u); - while (Scheduler_global_timer->CNT > Scheduler_global_timer->ARR) [[unlikely]] { - uint32_t offset = Scheduler_global_timer->CNT - Scheduler_global_timer->ARR; - current_interval_us_ = offset; - SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt - Scheduler_global_timer->CNT = Scheduler_global_timer->CNT + offset; + + Scheduler_global_timer->ARR = current_interval_us_; + if (Scheduler_global_timer->CNT > current_interval_us_) [[unlikely]] { + uint32_t offset = Scheduler_global_timer->CNT - current_interval_us_; + Scheduler_global_timer->CNT = 0; + global_tick_us_ += offset; } } Scheduler::global_timer_enable(); @@ -305,18 +313,21 @@ void Scheduler::on_timer_update() { if (diff > 0) [[likely]] { break; // Task is in the future, stop processing } - pop_front(); + SchedLock(); + pop_front(); // mark task as ready SET_BIT(ready_bitmap_, 1u << candidate_id); - if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); insert_sorted(candidate_id); } + SchedUnlock(); } + //SchedLock(); schedule_next_interval(); + //SchedUnlock(); } uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { From 773c44602566054c184feb2795f1412920c01b5d Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:25:42 +0100 Subject: [PATCH 02/35] get cleanup to compile --- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Src/HALAL/Services/Time/Scheduler.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index e964ae8c0..69fb68ba9 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -33,7 +33,7 @@ struct Scheduler { // temporary, will be removed [[deprecated]] static inline void start() {} static void update(); - static inline uint64_t get_global_tick(); + static uint64_t get_global_tick(); static uint16_t register_task(uint32_t period_us, callback_t func); static bool unregister_task(uint16_t id); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 15b7594cb..bdb4cd319 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -169,7 +169,7 @@ void Scheduler::update() { } } -inline uint64_t Scheduler::get_global_tick() { +uint64_t Scheduler::get_global_tick() { SchedLock(); uint64_t val = global_tick_us_ + Scheduler_global_timer->CNT; SchedUnlock(); From 5418b89c1f097d1fee1420f60e7f6fa123f26a0a Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:28:21 +0100 Subject: [PATCH 03/35] format checks --- Src/HALAL/Services/Time/Scheduler.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index bdb4cd319..a9bc91640 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -282,7 +282,7 @@ void Scheduler::schedule_next_interval() { Task& next_task = tasks_[next_id]; int32_t diff = (int32_t)(next_task.next_fire_us - static_cast(global_tick_us_)); SchedUnlock(); - + if (diff >= -1 && diff <= 1) [[unlikely]] { current_interval_us_ = 1; SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt @@ -325,9 +325,7 @@ void Scheduler::on_timer_update() { SchedUnlock(); } - //SchedLock(); schedule_next_interval(); - //SchedUnlock(); } uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { From 7231bfd71b9d8bcdedeeb0521c7fb49826157f12 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:49:13 +0100 Subject: [PATCH 04/35] fix tests and scheduler (off by one error) --- Src/HALAL/Services/Time/Scheduler.cpp | 6 +++--- Tests/Time/scheduler_test.cpp | 9 --------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index a9bc91640..04bbe9da2 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -288,12 +288,12 @@ void Scheduler::schedule_next_interval() { SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt } else { if (diff < -1) [[unlikely]] { - current_interval_us_ = static_cast(0 - diff) - 1u; + current_interval_us_ = static_cast(0 - diff); } else { - current_interval_us_ = static_cast(diff) - 1u; + current_interval_us_ = static_cast(diff); } - Scheduler_global_timer->ARR = current_interval_us_; + Scheduler_global_timer->ARR = current_interval_us_ - 1u; if (Scheduler_global_timer->CNT > current_interval_us_) [[unlikely]] { uint32_t offset = Scheduler_global_timer->CNT - current_interval_us_; Scheduler_global_timer->CNT = 0; diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 7f468b870..75c0a45af 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -44,7 +44,6 @@ TEST_F(SchedulerTests, TaskRegistration) { TEST_F(SchedulerTests, TaskExecutionShort) { Scheduler::register_task(10, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 1'000; @@ -59,7 +58,6 @@ TEST_F(SchedulerTests, TaskExecutionShort) { TEST_F(SchedulerTests, TaskExecutionLong) { Scheduler::register_task(10, &fake_workload); - Scheduler::start(); // TIM2_BASE->ARR = 500; TIM2_BASE->generate_update(); TIM2_BASE->PSC = 2; // quicker test @@ -75,7 +73,6 @@ TEST_F(SchedulerTests, TaskExecutionLong) { TEST_F(SchedulerTests, SetTimeout) { Scheduler::set_timeout(10, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -90,7 +87,6 @@ TEST_F(SchedulerTests, SetTimeout) { TEST_F(SchedulerTests, GlobalTickOverflow) { Scheduler::global_tick_us_ = 0xFFFFFFF0ULL; // Near 32-bit max Scheduler::register_task(20, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -133,7 +129,6 @@ TEST_F(SchedulerTests, GlobalTickOverflowManyTasks) { Scheduler::register_task(10, &multiple_task_1); Scheduler::register_task(20, &multiple_task_2); Scheduler::register_task(30, &multiple_task_3); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -151,7 +146,6 @@ TEST_F(SchedulerTests, GlobalTickOverflowManyTasks) { TEST_F(SchedulerTests, TimeoutClearAddTask) { uint8_t timeout_id = Scheduler::set_timeout(10, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -190,7 +184,6 @@ TEST_F(SchedulerTests, TaskDe_ReRegistration) { uint8_t connecting_task = Scheduler::register_task(10, &connecting_cyclic); uint8_t operational_task = 0; uint8_t fault_task = 0; - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -231,7 +224,6 @@ TEST_F(SchedulerTests, MultipleTasks) { Scheduler::register_task(5, &multiple_task_5); Scheduler::register_task(6, &multiple_task_6); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 300; for (int i = 0; i < NUM_TICKS; i++) { @@ -258,7 +250,6 @@ TEST_F(SchedulerTests, SameTaskMultipleTimes) { Scheduler::register_task(6, &multiple_task_1); multiple_task1count = 0; - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 300; for (int i = 0; i < NUM_TICKS; i++) { From f60c1596313b9d36429abbae4583c11ae0fcdfea Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:22:40 +0100 Subject: [PATCH 05/35] Add a test for get_at --- Inc/HALAL/Services/Time/Scheduler.hpp | 26 +++++++++++++++++++++----- Src/HALAL/Services/Time/Scheduler.cpp | 17 +---------------- Tests/Time/scheduler_test.cpp | 8 ++++++++ 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 69fb68ba9..b85dda0b6 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -9,6 +9,13 @@ /* Uso del scheduler, descrito en la wiki: * https://wiki.hyperloopupv.com/es/firmware/Timing/Scheduler */ +/* To allow debugging of inline functions only when testing */ +#ifdef SIM_ON +# define HYPER_INLINE inline +#else +# define HYPER_INLINE +#endif + #include "stm32h7xx_ll_tim_wrapper.h" #include @@ -42,7 +49,7 @@ struct Scheduler { static bool cancel_timeout(uint16_t id); // internal - static void on_timer_update(); + static inline void on_timer_update(); static void schedule_next_interval(); static constexpr uint32_t FREQUENCY = 1'000'000u; // 1 MHz -> 1us precision #ifndef SIM_ON @@ -90,10 +97,19 @@ struct Scheduler { static void remove_sorted(uint8_t id); // helpers - static inline uint8_t get_at(uint8_t idx); - static inline void set_at(uint8_t idx, uint8_t id); - static inline void pop_front(); - static inline uint8_t front_id(); + static HYPER_INLINE uint8_t get_at(uint8_t idx) { + return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); + } + static HYPER_INLINE void set_at(uint8_t idx, uint8_t id) { + uint32_t shift = idx * 4; + uint64_t clearmask = ~(0xFFULL << shift); + Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); + } + static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } + static HYPER_INLINE void pop_front() { + Scheduler::active_task_count_--; + Scheduler::sorted_task_ids_ >>= 4; + } static inline void global_timer_disable(); static inline void global_timer_enable(); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 04bbe9da2..5ae9dc694 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -31,21 +31,6 @@ uint64_t Scheduler::global_tick_us_{0}; uint32_t Scheduler::current_interval_us_{0}; uint16_t Scheduler::timeout_idx_{1}; -inline uint8_t Scheduler::get_at(uint8_t idx) { - return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); -} -inline void Scheduler::set_at(uint8_t idx, uint8_t id) { - uint32_t shift = idx * 4; - uint64_t clearmask = ~(0xFFULL << shift); - Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); -} -inline uint8_t Scheduler::front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } -inline void Scheduler::pop_front() { - // O(1) remove of logical index 0 - Scheduler::active_task_count_--; - Scheduler::sorted_task_ids_ >>= 4; -} - // ---------------------------- inline void Scheduler::global_timer_disable() { @@ -303,7 +288,7 @@ void Scheduler::schedule_next_interval() { Scheduler::global_timer_enable(); } -void Scheduler::on_timer_update() { +inline void Scheduler::on_timer_update() { global_tick_us_ += current_interval_us_; while (active_task_count_ > 0) { // Pop all due tasks, several might be due in the same tick diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 75c0a45af..19a39622f 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -32,6 +32,14 @@ class SchedulerTests : public ::testing::Test { } }; +TEST_F(SchedulerTests, GetAt) { + Scheduler::sorted_task_ids_ = 0xFEDCBA9876543210ULL; + for(uint64_t i = 0; i < 16; i++) { + uint64_t val = Scheduler::get_at(i); + EXPECT_EQ(val, i); + } +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From 643d2c8eacba2c8ef7adcb5dfd2b35abac7620b8 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:29:30 +0100 Subject: [PATCH 06/35] formatting --- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Tests/Time/scheduler_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index b85dda0b6..aa564becd 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -105,7 +105,7 @@ struct Scheduler { uint64_t clearmask = ~(0xFFULL << shift); Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); } - static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } + static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } static HYPER_INLINE void pop_front() { Scheduler::active_task_count_--; Scheduler::sorted_task_ids_ >>= 4; diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 19a39622f..235c041b7 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -34,7 +34,7 @@ class SchedulerTests : public ::testing::Test { TEST_F(SchedulerTests, GetAt) { Scheduler::sorted_task_ids_ = 0xFEDCBA9876543210ULL; - for(uint64_t i = 0; i < 16; i++) { + for (uint64_t i = 0; i < 16; i++) { uint64_t val = Scheduler::get_at(i); EXPECT_EQ(val, i); } From 8629f5edc040038fcf49df9f179df72269b93c2d Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:40:50 +0100 Subject: [PATCH 07/35] Add a test for set_at and fix it --- Inc/HALAL/Services/Time/Scheduler.hpp | 6 +++--- Tests/Time/scheduler_test.cpp | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index aa564becd..7ce4d1457 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -101,9 +101,9 @@ struct Scheduler { return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); } static HYPER_INLINE void set_at(uint8_t idx, uint8_t id) { - uint32_t shift = idx * 4; - uint64_t clearmask = ~(0xFFULL << shift); - Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); + uint64_t shift = idx * 4; + uint64_t clearmask = ~(0x0FULL << shift); + Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | ((uint64_t)id << shift); } static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } static HYPER_INLINE void pop_front() { diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 235c041b7..6646661ff 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -40,6 +40,15 @@ TEST_F(SchedulerTests, GetAt) { } } +TEST_F(SchedulerTests, SetAt) { + uint64_t original = 0x1EDCBA9876543210ULL; + for (uint64_t i = 0; i < 16; i++) { + Scheduler::sorted_task_ids_ = original; + Scheduler::set_at(i, 0xF); + EXPECT_EQ(Scheduler::sorted_task_ids_, original | (0xFULL << (i*4))); + } +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From 175dc804c492f61f188b385cb0a6cc3e2f38e911 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:43:47 +0100 Subject: [PATCH 08/35] formatting --- Tests/Time/scheduler_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 6646661ff..ad9225fa1 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -45,7 +45,7 @@ TEST_F(SchedulerTests, SetAt) { for (uint64_t i = 0; i < 16; i++) { Scheduler::sorted_task_ids_ = original; Scheduler::set_at(i, 0xF); - EXPECT_EQ(Scheduler::sorted_task_ids_, original | (0xFULL << (i*4))); + EXPECT_EQ(Scheduler::sorted_task_ids_, original | (0xFULL << (i * 4))); } } From 9862b386c0e7852706e937df47688732466ab0ad Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:45:51 +0100 Subject: [PATCH 09/35] formatting --- Inc/HALAL/Services/Time/Scheduler.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 7ce4d1457..32e0aa84a 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -11,9 +11,9 @@ /* To allow debugging of inline functions only when testing */ #ifdef SIM_ON -# define HYPER_INLINE inline +#define HYPER_INLINE inline #else -# define HYPER_INLINE +#define HYPER_INLINE #endif #include "stm32h7xx_ll_tim_wrapper.h" From cb381bfb9abbb3a76a757fb1f81b06d9f6c7fc00 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 17:01:23 +0100 Subject: [PATCH 10/35] try to fix issue in LCU --- Src/HALAL/Services/Time/Scheduler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 5ae9dc694..075ad8952 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -279,8 +279,8 @@ void Scheduler::schedule_next_interval() { } Scheduler_global_timer->ARR = current_interval_us_ - 1u; - if (Scheduler_global_timer->CNT > current_interval_us_) [[unlikely]] { - uint32_t offset = Scheduler_global_timer->CNT - current_interval_us_; + if (Scheduler_global_timer->CNT > Scheduler_global_timer->ARR) [[unlikely]] { + uint32_t offset = Scheduler_global_timer->CNT - Scheduler_global_timer->ARR; Scheduler_global_timer->CNT = 0; global_tick_us_ += offset; } From 1c489af68073c8c0cbe8e5712cf5b8169c3a3fe2 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 17:12:05 +0100 Subject: [PATCH 11/35] add a test for front_id and pop_front --- Tests/Time/scheduler_test.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index ad9225fa1..2f6b8b70b 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -49,6 +49,15 @@ TEST_F(SchedulerTests, SetAt) { } } +TEST_F(SchedulerTests, FrontId_PopFront) { + Scheduler::sorted_task_ids_ = 0xFEDCBA9876543210ULL; + for (uint8_t i = 0; i < 16; i++) { + uint8_t id = Scheduler::front_id(); + Scheduler::pop_front(); + EXPECT_EQ(id, i); + } +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From 3c16640750868091e98834acd3b0b98b57fddaba Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 21 Mar 2026 00:29:11 +0100 Subject: [PATCH 12/35] add changeset for this pr --- .changesets/fix-scheduler-race-condition.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changesets/fix-scheduler-race-condition.md diff --git a/.changesets/fix-scheduler-race-condition.md b/.changesets/fix-scheduler-race-condition.md new file mode 100644 index 000000000..97577ff77 --- /dev/null +++ b/.changesets/fix-scheduler-race-condition.md @@ -0,0 +1,4 @@ +release: patch +summary: fix remaining scheduler race conditions + +Currently only tested on LCU despite title saying otherwise (too many changes to say it was tested) \ No newline at end of file From e49afea44fbd8852fa5f6c714480e6cb579ef0c6 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 21 Mar 2026 00:31:16 +0100 Subject: [PATCH 13/35] formatting for changeset :/ --- .changesets/fix-scheduler-race-condition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changesets/fix-scheduler-race-condition.md b/.changesets/fix-scheduler-race-condition.md index 97577ff77..a811cd55c 100644 --- a/.changesets/fix-scheduler-race-condition.md +++ b/.changesets/fix-scheduler-race-condition.md @@ -1,4 +1,4 @@ release: patch summary: fix remaining scheduler race conditions -Currently only tested on LCU despite title saying otherwise (too many changes to say it was tested) \ No newline at end of file +Currently only tested on LCU despite title saying otherwise (too many changes to say it was tested) From fb9fa43ca7b73caafc5472be6afcfadb16a6f7d5 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:21:04 +0100 Subject: [PATCH 14/35] fix (tested on PCU, LV-BMS and LCU) --- Inc/HALAL/Services/Time/Scheduler.hpp | 4 +-- Src/HALAL/Services/Time/Scheduler.cpp | 49 ++++++++++++++++----------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index dfabc0bdb..e964ae8c0 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -33,9 +33,7 @@ struct Scheduler { // temporary, will be removed [[deprecated]] static inline void start() {} static void update(); - static inline uint64_t get_global_tick() { - return global_tick_us_ + Scheduler_global_timer->CNT; - } + static inline uint64_t get_global_tick(); static uint16_t register_task(uint32_t period_us, callback_t func); static bool unregister_task(uint16_t id); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 62a2333ad..15b7594cb 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -1,5 +1,5 @@ /* - * Scheduler.hpp + * Scheduler.cpp * * Created on: 17 nov. 2025 * Author: Victor (coauthor Stephan) @@ -32,13 +32,11 @@ uint32_t Scheduler::current_interval_us_{0}; uint16_t Scheduler::timeout_idx_{1}; inline uint8_t Scheduler::get_at(uint8_t idx) { - int word_idx = idx > 7; - uint32_t shift = (idx & 7) << 2; - return (((uint32_t*)&sorted_task_ids_)[word_idx] & (0x0F << shift)) >> shift; + return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); } inline void Scheduler::set_at(uint8_t idx, uint8_t id) { uint32_t shift = idx * 4; - uint64_t clearmask = ~(0xFF << shift); + uint64_t clearmask = ~(0xFFULL << shift); Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); } inline uint8_t Scheduler::front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } @@ -159,18 +157,25 @@ void Scheduler::update() { while (ready_bitmap_ != 0u) { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); - CLEAR_BIT(ready_bitmap_, 1u << bit_index); - Task& task = tasks_[bit_index]; task.callback(); + + SchedLock(); + CLEAR_BIT(ready_bitmap_, 1u << bit_index); if (!task.repeating) [[unlikely]] { - SchedLock(); release_slot(static_cast(bit_index)); - SchedUnlock(); } + SchedUnlock(); } } +inline uint64_t Scheduler::get_global_tick() { + SchedLock(); + uint64_t val = global_tick_us_ + Scheduler_global_timer->CNT; + SchedUnlock(); + return val; +} + inline uint8_t Scheduler::allocate_slot() { uint32_t idx = __builtin_ffs(Scheduler::free_bitmap_) - 1; if (idx > static_cast(Scheduler::kMaxTasks)) [[unlikely]] @@ -272,24 +277,27 @@ void Scheduler::schedule_next_interval() { return; } + SchedLock(); uint8_t next_id = Scheduler::front_id(); // sorted_task_ids_[0] Task& next_task = tasks_[next_id]; int32_t diff = (int32_t)(next_task.next_fire_us - static_cast(global_tick_us_)); + SchedUnlock(); + if (diff >= -1 && diff <= 1) [[unlikely]] { current_interval_us_ = 1; SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt } else { if (diff < -1) [[unlikely]] { - current_interval_us_ = static_cast(0 - diff); + current_interval_us_ = static_cast(0 - diff) - 1u; } else { - current_interval_us_ = static_cast(diff); + current_interval_us_ = static_cast(diff) - 1u; } - Scheduler_global_timer->ARR = static_cast(current_interval_us_ - 1u); - while (Scheduler_global_timer->CNT > Scheduler_global_timer->ARR) [[unlikely]] { - uint32_t offset = Scheduler_global_timer->CNT - Scheduler_global_timer->ARR; - current_interval_us_ = offset; - SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt - Scheduler_global_timer->CNT = Scheduler_global_timer->CNT + offset; + + Scheduler_global_timer->ARR = current_interval_us_; + if (Scheduler_global_timer->CNT > current_interval_us_) [[unlikely]] { + uint32_t offset = Scheduler_global_timer->CNT - current_interval_us_; + Scheduler_global_timer->CNT = 0; + global_tick_us_ += offset; } } Scheduler::global_timer_enable(); @@ -305,18 +313,21 @@ void Scheduler::on_timer_update() { if (diff > 0) [[likely]] { break; // Task is in the future, stop processing } - pop_front(); + SchedLock(); + pop_front(); // mark task as ready SET_BIT(ready_bitmap_, 1u << candidate_id); - if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); insert_sorted(candidate_id); } + SchedUnlock(); } + //SchedLock(); schedule_next_interval(); + //SchedUnlock(); } uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { From 3eb88abdd48188901a4b597b68afc563fac56f45 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:25:42 +0100 Subject: [PATCH 15/35] get cleanup to compile --- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Src/HALAL/Services/Time/Scheduler.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index e964ae8c0..69fb68ba9 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -33,7 +33,7 @@ struct Scheduler { // temporary, will be removed [[deprecated]] static inline void start() {} static void update(); - static inline uint64_t get_global_tick(); + static uint64_t get_global_tick(); static uint16_t register_task(uint32_t period_us, callback_t func); static bool unregister_task(uint16_t id); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 15b7594cb..bdb4cd319 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -169,7 +169,7 @@ void Scheduler::update() { } } -inline uint64_t Scheduler::get_global_tick() { +uint64_t Scheduler::get_global_tick() { SchedLock(); uint64_t val = global_tick_us_ + Scheduler_global_timer->CNT; SchedUnlock(); From 6f2eaf8694d3e1602b6fd7ea913e126667f4c8b1 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:28:21 +0100 Subject: [PATCH 16/35] format checks --- Src/HALAL/Services/Time/Scheduler.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index bdb4cd319..a9bc91640 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -282,7 +282,7 @@ void Scheduler::schedule_next_interval() { Task& next_task = tasks_[next_id]; int32_t diff = (int32_t)(next_task.next_fire_us - static_cast(global_tick_us_)); SchedUnlock(); - + if (diff >= -1 && diff <= 1) [[unlikely]] { current_interval_us_ = 1; SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt @@ -325,9 +325,7 @@ void Scheduler::on_timer_update() { SchedUnlock(); } - //SchedLock(); schedule_next_interval(); - //SchedUnlock(); } uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { From d07b4bb8064c670a192a2e5327e96c8be66fb0a7 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 15:49:13 +0100 Subject: [PATCH 17/35] fix tests and scheduler (off by one error) --- Src/HALAL/Services/Time/Scheduler.cpp | 6 +++--- Tests/Time/scheduler_test.cpp | 9 --------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index a9bc91640..04bbe9da2 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -288,12 +288,12 @@ void Scheduler::schedule_next_interval() { SET_BIT(Scheduler_global_timer->EGR, TIM_EGR_UG); // This should cause an interrupt } else { if (diff < -1) [[unlikely]] { - current_interval_us_ = static_cast(0 - diff) - 1u; + current_interval_us_ = static_cast(0 - diff); } else { - current_interval_us_ = static_cast(diff) - 1u; + current_interval_us_ = static_cast(diff); } - Scheduler_global_timer->ARR = current_interval_us_; + Scheduler_global_timer->ARR = current_interval_us_ - 1u; if (Scheduler_global_timer->CNT > current_interval_us_) [[unlikely]] { uint32_t offset = Scheduler_global_timer->CNT - current_interval_us_; Scheduler_global_timer->CNT = 0; diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 7f468b870..75c0a45af 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -44,7 +44,6 @@ TEST_F(SchedulerTests, TaskRegistration) { TEST_F(SchedulerTests, TaskExecutionShort) { Scheduler::register_task(10, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 1'000; @@ -59,7 +58,6 @@ TEST_F(SchedulerTests, TaskExecutionShort) { TEST_F(SchedulerTests, TaskExecutionLong) { Scheduler::register_task(10, &fake_workload); - Scheduler::start(); // TIM2_BASE->ARR = 500; TIM2_BASE->generate_update(); TIM2_BASE->PSC = 2; // quicker test @@ -75,7 +73,6 @@ TEST_F(SchedulerTests, TaskExecutionLong) { TEST_F(SchedulerTests, SetTimeout) { Scheduler::set_timeout(10, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -90,7 +87,6 @@ TEST_F(SchedulerTests, SetTimeout) { TEST_F(SchedulerTests, GlobalTickOverflow) { Scheduler::global_tick_us_ = 0xFFFFFFF0ULL; // Near 32-bit max Scheduler::register_task(20, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -133,7 +129,6 @@ TEST_F(SchedulerTests, GlobalTickOverflowManyTasks) { Scheduler::register_task(10, &multiple_task_1); Scheduler::register_task(20, &multiple_task_2); Scheduler::register_task(30, &multiple_task_3); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -151,7 +146,6 @@ TEST_F(SchedulerTests, GlobalTickOverflowManyTasks) { TEST_F(SchedulerTests, TimeoutClearAddTask) { uint8_t timeout_id = Scheduler::set_timeout(10, &fake_workload); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -190,7 +184,6 @@ TEST_F(SchedulerTests, TaskDe_ReRegistration) { uint8_t connecting_task = Scheduler::register_task(10, &connecting_cyclic); uint8_t operational_task = 0; uint8_t fault_task = 0; - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; @@ -231,7 +224,6 @@ TEST_F(SchedulerTests, MultipleTasks) { Scheduler::register_task(5, &multiple_task_5); Scheduler::register_task(6, &multiple_task_6); - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 300; for (int i = 0; i < NUM_TICKS; i++) { @@ -258,7 +250,6 @@ TEST_F(SchedulerTests, SameTaskMultipleTimes) { Scheduler::register_task(6, &multiple_task_1); multiple_task1count = 0; - Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 300; for (int i = 0; i < NUM_TICKS; i++) { From c199f4232a679dd16bf5cd68f3ee55641eed2904 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:22:40 +0100 Subject: [PATCH 18/35] Add a test for get_at --- Inc/HALAL/Services/Time/Scheduler.hpp | 26 +++++++++++++++++++++----- Src/HALAL/Services/Time/Scheduler.cpp | 17 +---------------- Tests/Time/scheduler_test.cpp | 8 ++++++++ 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 69fb68ba9..b85dda0b6 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -9,6 +9,13 @@ /* Uso del scheduler, descrito en la wiki: * https://wiki.hyperloopupv.com/es/firmware/Timing/Scheduler */ +/* To allow debugging of inline functions only when testing */ +#ifdef SIM_ON +# define HYPER_INLINE inline +#else +# define HYPER_INLINE +#endif + #include "stm32h7xx_ll_tim_wrapper.h" #include @@ -42,7 +49,7 @@ struct Scheduler { static bool cancel_timeout(uint16_t id); // internal - static void on_timer_update(); + static inline void on_timer_update(); static void schedule_next_interval(); static constexpr uint32_t FREQUENCY = 1'000'000u; // 1 MHz -> 1us precision #ifndef SIM_ON @@ -90,10 +97,19 @@ struct Scheduler { static void remove_sorted(uint8_t id); // helpers - static inline uint8_t get_at(uint8_t idx); - static inline void set_at(uint8_t idx, uint8_t id); - static inline void pop_front(); - static inline uint8_t front_id(); + static HYPER_INLINE uint8_t get_at(uint8_t idx) { + return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); + } + static HYPER_INLINE void set_at(uint8_t idx, uint8_t id) { + uint32_t shift = idx * 4; + uint64_t clearmask = ~(0xFFULL << shift); + Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); + } + static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } + static HYPER_INLINE void pop_front() { + Scheduler::active_task_count_--; + Scheduler::sorted_task_ids_ >>= 4; + } static inline void global_timer_disable(); static inline void global_timer_enable(); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 04bbe9da2..5ae9dc694 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -31,21 +31,6 @@ uint64_t Scheduler::global_tick_us_{0}; uint32_t Scheduler::current_interval_us_{0}; uint16_t Scheduler::timeout_idx_{1}; -inline uint8_t Scheduler::get_at(uint8_t idx) { - return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); -} -inline void Scheduler::set_at(uint8_t idx, uint8_t id) { - uint32_t shift = idx * 4; - uint64_t clearmask = ~(0xFFULL << shift); - Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); -} -inline uint8_t Scheduler::front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } -inline void Scheduler::pop_front() { - // O(1) remove of logical index 0 - Scheduler::active_task_count_--; - Scheduler::sorted_task_ids_ >>= 4; -} - // ---------------------------- inline void Scheduler::global_timer_disable() { @@ -303,7 +288,7 @@ void Scheduler::schedule_next_interval() { Scheduler::global_timer_enable(); } -void Scheduler::on_timer_update() { +inline void Scheduler::on_timer_update() { global_tick_us_ += current_interval_us_; while (active_task_count_ > 0) { // Pop all due tasks, several might be due in the same tick diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 75c0a45af..19a39622f 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -32,6 +32,14 @@ class SchedulerTests : public ::testing::Test { } }; +TEST_F(SchedulerTests, GetAt) { + Scheduler::sorted_task_ids_ = 0xFEDCBA9876543210ULL; + for(uint64_t i = 0; i < 16; i++) { + uint64_t val = Scheduler::get_at(i); + EXPECT_EQ(val, i); + } +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From d40395e19cf9994fcc3000555cf6b61e4e446470 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:29:30 +0100 Subject: [PATCH 19/35] formatting --- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Tests/Time/scheduler_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index b85dda0b6..aa564becd 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -105,7 +105,7 @@ struct Scheduler { uint64_t clearmask = ~(0xFFULL << shift); Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); } - static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } + static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } static HYPER_INLINE void pop_front() { Scheduler::active_task_count_--; Scheduler::sorted_task_ids_ >>= 4; diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 19a39622f..235c041b7 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -34,7 +34,7 @@ class SchedulerTests : public ::testing::Test { TEST_F(SchedulerTests, GetAt) { Scheduler::sorted_task_ids_ = 0xFEDCBA9876543210ULL; - for(uint64_t i = 0; i < 16; i++) { + for (uint64_t i = 0; i < 16; i++) { uint64_t val = Scheduler::get_at(i); EXPECT_EQ(val, i); } From df98f27f7a1e834ff08a8289e61bcb8465f0b19d Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:40:50 +0100 Subject: [PATCH 20/35] Add a test for set_at and fix it --- Inc/HALAL/Services/Time/Scheduler.hpp | 6 +++--- Tests/Time/scheduler_test.cpp | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index aa564becd..7ce4d1457 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -101,9 +101,9 @@ struct Scheduler { return (uint8_t)((sorted_task_ids_ >> (idx * 4)) & 0xF); } static HYPER_INLINE void set_at(uint8_t idx, uint8_t id) { - uint32_t shift = idx * 4; - uint64_t clearmask = ~(0xFFULL << shift); - Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); + uint64_t shift = idx * 4; + uint64_t clearmask = ~(0x0FULL << shift); + Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | ((uint64_t)id << shift); } static HYPER_INLINE uint8_t front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } static HYPER_INLINE void pop_front() { diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 235c041b7..6646661ff 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -40,6 +40,15 @@ TEST_F(SchedulerTests, GetAt) { } } +TEST_F(SchedulerTests, SetAt) { + uint64_t original = 0x1EDCBA9876543210ULL; + for (uint64_t i = 0; i < 16; i++) { + Scheduler::sorted_task_ids_ = original; + Scheduler::set_at(i, 0xF); + EXPECT_EQ(Scheduler::sorted_task_ids_, original | (0xFULL << (i*4))); + } +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From b0a91cd916d2f233590d7401519ed04ff69cbee8 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:43:47 +0100 Subject: [PATCH 21/35] formatting --- Tests/Time/scheduler_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 6646661ff..ad9225fa1 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -45,7 +45,7 @@ TEST_F(SchedulerTests, SetAt) { for (uint64_t i = 0; i < 16; i++) { Scheduler::sorted_task_ids_ = original; Scheduler::set_at(i, 0xF); - EXPECT_EQ(Scheduler::sorted_task_ids_, original | (0xFULL << (i*4))); + EXPECT_EQ(Scheduler::sorted_task_ids_, original | (0xFULL << (i * 4))); } } From 6dd5494100b1fc68c63d5a22dd73e4acd0efb584 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 16:45:51 +0100 Subject: [PATCH 22/35] formatting --- Inc/HALAL/Services/Time/Scheduler.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 7ce4d1457..32e0aa84a 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -11,9 +11,9 @@ /* To allow debugging of inline functions only when testing */ #ifdef SIM_ON -# define HYPER_INLINE inline +#define HYPER_INLINE inline #else -# define HYPER_INLINE +#define HYPER_INLINE #endif #include "stm32h7xx_ll_tim_wrapper.h" From 1d96793f587e1b3e60d6a22bffa08ceda78ae698 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 17:01:23 +0100 Subject: [PATCH 23/35] try to fix issue in LCU --- Src/HALAL/Services/Time/Scheduler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 5ae9dc694..075ad8952 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -279,8 +279,8 @@ void Scheduler::schedule_next_interval() { } Scheduler_global_timer->ARR = current_interval_us_ - 1u; - if (Scheduler_global_timer->CNT > current_interval_us_) [[unlikely]] { - uint32_t offset = Scheduler_global_timer->CNT - current_interval_us_; + if (Scheduler_global_timer->CNT > Scheduler_global_timer->ARR) [[unlikely]] { + uint32_t offset = Scheduler_global_timer->CNT - Scheduler_global_timer->ARR; Scheduler_global_timer->CNT = 0; global_tick_us_ += offset; } From 6e500e4bb537249356cbb92aaa871db2b368d102 Mon Sep 17 00:00:00 2001 From: victhor Date: Fri, 20 Mar 2026 17:12:05 +0100 Subject: [PATCH 24/35] add a test for front_id and pop_front --- Tests/Time/scheduler_test.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index ad9225fa1..2f6b8b70b 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -49,6 +49,15 @@ TEST_F(SchedulerTests, SetAt) { } } +TEST_F(SchedulerTests, FrontId_PopFront) { + Scheduler::sorted_task_ids_ = 0xFEDCBA9876543210ULL; + for (uint8_t i = 0; i < 16; i++) { + uint8_t id = Scheduler::front_id(); + Scheduler::pop_front(); + EXPECT_EQ(id, i); + } +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From 7a5832069aefea8b36ea655d55eda143e6264d18 Mon Sep 17 00:00:00 2001 From: victhor Date: Mon, 23 Mar 2026 20:30:42 +0100 Subject: [PATCH 25/35] revert merge from development --- Inc/HALAL/Services/Time/Scheduler.hpp | 4 +++- Src/HALAL/Services/Time/Scheduler.cpp | 13 +++++++++---- Tests/Time/scheduler_test.cpp | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 32e0aa84a..08749aedb 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -17,6 +17,8 @@ #endif #include "stm32h7xx_ll_tim_wrapper.h" +#include "HALAL/Models/Packets/Packet.hpp" +#include "HALAL/Services/Communication/Ethernet/LWIP/UDP/DatagramSocket.hpp" #include #include @@ -113,4 +115,4 @@ struct Scheduler { static inline void global_timer_disable(); static inline void global_timer_enable(); -}; +}; \ No newline at end of file diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 075ad8952..fe2aabe17 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -143,6 +143,7 @@ void Scheduler::update() { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); Task& task = tasks_[bit_index]; + task.callback(); SchedLock(); @@ -280,9 +281,9 @@ void Scheduler::schedule_next_interval() { Scheduler_global_timer->ARR = current_interval_us_ - 1u; if (Scheduler_global_timer->CNT > Scheduler_global_timer->ARR) [[unlikely]] { - uint32_t offset = Scheduler_global_timer->CNT - Scheduler_global_timer->ARR; + uint32_t cnt_temp = Scheduler_global_timer->CNT; Scheduler_global_timer->CNT = 0; - global_tick_us_ += offset; + global_tick_us_ += cnt_temp; } } Scheduler::global_timer_enable(); @@ -298,11 +299,15 @@ inline void Scheduler::on_timer_update() { if (diff > 0) [[likely]] { break; // Task is in the future, stop processing } + uint32_t task_bit = 1u << candidate_id; SchedLock(); pop_front(); // mark task as ready - SET_BIT(ready_bitmap_, 1u << candidate_id); + if ((ready_bitmap_ & task_bit) != 0) [[unlikely]] { + ErrorHandler("Too slow, could not execute task %u in time", candidate_id); + } + SET_BIT(ready_bitmap_, task_bit); if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); insert_sorted(candidate_id); @@ -401,4 +406,4 @@ bool Scheduler::cancel_timeout(uint16_t id) { schedule_next_interval(); SchedUnlock(); return true; -} +} \ No newline at end of file diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 2f6b8b70b..324623df4 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -289,4 +289,4 @@ TEST_F(SchedulerTests, SameTaskMultipleTimes) { NUM_TICKS / 1 - 1 + NUM_TICKS / 2 - 1 + NUM_TICKS / 3 - 1 + NUM_TICKS / 4 - 1 + NUM_TICKS / 5 - 1 + NUM_TICKS / 6 - 1 ); -} +} \ No newline at end of file From 8cad77fa05785fdbe7b595da8d79050e1aadc4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Fri, 27 Mar 2026 00:22:15 +0100 Subject: [PATCH 26/35] searching for case-insensitive STM32 CLT path --- toolchains/stm32.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/toolchains/stm32.cmake b/toolchains/stm32.cmake index 082d3101d..95cc954a4 100644 --- a/toolchains/stm32.cmake +++ b/toolchains/stm32.cmake @@ -34,7 +34,8 @@ endfunction() function(_stm32_extract_version _path _out_var) _stm32_resolve_path("${_path}" _resolved) - string(REGEX MATCH "STM32CubeCLT[_-]([0-9]+\\.[0-9]+\\.[0-9]+)" _match "${_resolved}") + string(TOUPPER "${_resolved}" _resolved_upper) + string(REGEX MATCH "STM32CUBECLT[_-]([0-9]+\\.[0-9]+\\.[0-9]+)" _match "${_resolved_upper}") set(${_out_var} "${CMAKE_MATCH_1}" PARENT_SCOPE) endfunction() From 379319e88c69b7f5af235977687008f6f53438f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Fri, 27 Mar 2026 00:24:11 +0100 Subject: [PATCH 27/35] applied formatter --- Inc/HALAL/Services/ADC/ADC.hpp | 10 +--------- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Src/HALAL/Services/Time/Scheduler.cpp | 2 +- Tests/Time/scheduler_test.cpp | 2 +- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Inc/HALAL/Services/ADC/ADC.hpp b/Inc/HALAL/Services/ADC/ADC.hpp index 105a932b7..7356a89b1 100644 --- a/Inc/HALAL/Services/ADC/ADC.hpp +++ b/Inc/HALAL/Services/ADC/ADC.hpp @@ -189,15 +189,7 @@ struct ADCDomain { ClockPrescaler prescaler = ClockPrescaler::DIV1, uint32_t sample_rate_hz = 0 ) - : ADC( - pin, - resolution, - sample_time, - prescaler, - sample_rate_hz, - peripheral, - channel - ) {} + : ADC(pin, resolution, sample_time, prescaler, sample_rate_hz, peripheral, channel) {} template consteval std::size_t inscribe(Ctx& ctx) const { const auto gpio_idx = gpio.inscribe(ctx); diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 08749aedb..138c79651 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -115,4 +115,4 @@ struct Scheduler { static inline void global_timer_disable(); static inline void global_timer_enable(); -}; \ No newline at end of file +}; diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index fe2aabe17..dde12a334 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -406,4 +406,4 @@ bool Scheduler::cancel_timeout(uint16_t id) { schedule_next_interval(); SchedUnlock(); return true; -} \ No newline at end of file +} diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 324623df4..2f6b8b70b 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -289,4 +289,4 @@ TEST_F(SchedulerTests, SameTaskMultipleTimes) { NUM_TICKS / 1 - 1 + NUM_TICKS / 2 - 1 + NUM_TICKS / 3 - 1 + NUM_TICKS / 4 - 1 + NUM_TICKS / 5 - 1 + NUM_TICKS / 6 - 1 ); -} \ No newline at end of file +} From 8212c6ce503ba54ea61230dcf7d3728e6ab38cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Fri, 27 Mar 2026 00:32:02 +0100 Subject: [PATCH 28/35] removed unused include --- Inc/HALAL/Services/Time/Scheduler.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 138c79651..ceb16e198 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -18,7 +18,6 @@ #include "stm32h7xx_ll_tim_wrapper.h" #include "HALAL/Models/Packets/Packet.hpp" -#include "HALAL/Services/Communication/Ethernet/LWIP/UDP/DatagramSocket.hpp" #include #include From d14ece9b39aeb2bc7461a671cc25fe58fbf2bffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Fri, 27 Mar 2026 00:32:29 +0100 Subject: [PATCH 29/35] making PacketValue destructor virtual so that CLang doesn't cry --- Inc/HALAL/Models/Packets/PacketValue.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/HALAL/Models/Packets/PacketValue.hpp b/Inc/HALAL/Models/Packets/PacketValue.hpp index 1e9d373c4..f1dd6158e 100644 --- a/Inc/HALAL/Models/Packets/PacketValue.hpp +++ b/Inc/HALAL/Models/Packets/PacketValue.hpp @@ -11,7 +11,7 @@ template <> class PacketValue<> { public: using value_type = empty_type; PacketValue() = default; - ~PacketValue() = default; + virtual ~PacketValue() = default; virtual void* get_pointer() = 0; virtual void set_pointer(void* pointer) = 0; virtual size_t get_size() = 0; From 581bb19621c41e31a86abe5d4378e12f9ed3e54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Fri, 27 Mar 2026 00:32:42 +0100 Subject: [PATCH 30/35] minor fix --- Inc/HALAL/Services/Encoder/Encoder.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/HALAL/Services/Encoder/Encoder.hpp b/Inc/HALAL/Services/Encoder/Encoder.hpp index e0529ead5..8e1ddd1b9 100644 --- a/Inc/HALAL/Services/Encoder/Encoder.hpp +++ b/Inc/HALAL/Services/Encoder/Encoder.hpp @@ -63,7 +63,7 @@ template class Encoder { } tim->instance->tim->PSC = 5; - if constexpr (tim->is_32bit_instance) { + if constexpr (TimerWrapper::is_32bit_instance) { tim->instance->tim->ARR = UINT32_MAX; } else { tim->instance->tim->ARR = UINT16_MAX; From 29467e26daf7b98d042b5233e14b7cf35e436ce5 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 28 Mar 2026 17:14:40 +0100 Subject: [PATCH 31/35] commit old changes --- Src/HALAL/Services/Time/Scheduler.cpp | 4 ++-- Tests/Time/scheduler_test.cpp | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 075ad8952..0aae1035c 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -280,9 +280,9 @@ void Scheduler::schedule_next_interval() { Scheduler_global_timer->ARR = current_interval_us_ - 1u; if (Scheduler_global_timer->CNT > Scheduler_global_timer->ARR) [[unlikely]] { - uint32_t offset = Scheduler_global_timer->CNT - Scheduler_global_timer->ARR; + uint32_t cnt_temp = Scheduler_global_timer->CNT; Scheduler_global_timer->CNT = 0; - global_tick_us_ += offset; + global_tick_us_ += cnt_temp; } } Scheduler::global_timer_enable(); diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 2f6b8b70b..726ca54ee 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -74,8 +74,12 @@ TEST_F(SchedulerTests, TaskExecutionShort) { constexpr int NUM_TICKS = 1'000; for (int i = 0; i < NUM_TICKS; i++) { + uint64_t tick = Scheduler::get_global_tick(); + EXPECT_EQ(tick, i); + for (int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); + Scheduler::update(); } // 1000 ticks / 10 ticks/task = 100 executions. From b6ead591fd4e7a34220b30e015bd5e2328a19e60 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 28 Mar 2026 17:22:13 +0100 Subject: [PATCH 32/35] fix off by one error in allocating a slot --- Src/HALAL/Services/Time/Scheduler.cpp | 2 +- Tests/Time/scheduler_test.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index dde12a334..f8cbf1069 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -164,7 +164,7 @@ uint64_t Scheduler::get_global_tick() { inline uint8_t Scheduler::allocate_slot() { uint32_t idx = __builtin_ffs(Scheduler::free_bitmap_) - 1; - if (idx > static_cast(Scheduler::kMaxTasks)) [[unlikely]] + if (idx >= Scheduler::kMaxTasks) [[unlikely]] return static_cast(Scheduler::INVALID_ID); Scheduler::free_bitmap_ &= ~(1UL << idx); return static_cast(idx); diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 726ca54ee..a1a31c9f8 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -58,6 +58,17 @@ TEST_F(SchedulerTests, FrontId_PopFront) { } } +TEST_F(SchedulerTests, Max16Tasks) { + uint16_t task_id; + for(int i = 0; i < 16; i++) { + task_id = Scheduler::register_task(1, &fake_workload); + EXPECT_EQ(task_id == Scheduler::INVALID_ID, false); + } + // 17th task should not give a valid id + task_id = Scheduler::register_task(1, &fake_workload); + EXPECT_EQ(task_id == Scheduler::INVALID_ID, true); +} + TEST_F(SchedulerTests, FreeBitmap) { Scheduler::register_task(10, &fake_workload); EXPECT_EQ(Scheduler::free_bitmap_, 0xFFFF'FFFE); From 97473f0e293eb1b871bf1ccf9a6aac2bdadec344 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 28 Mar 2026 17:24:51 +0100 Subject: [PATCH 33/35] formatting --- Tests/Time/scheduler_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index a1a31c9f8..ed20ab2da 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -60,11 +60,11 @@ TEST_F(SchedulerTests, FrontId_PopFront) { TEST_F(SchedulerTests, Max16Tasks) { uint16_t task_id; - for(int i = 0; i < 16; i++) { + for (int i = 0; i < 16; i++) { task_id = Scheduler::register_task(1, &fake_workload); EXPECT_EQ(task_id == Scheduler::INVALID_ID, false); } - // 17th task should not give a valid id + // 17th task should not give a valid i task_id = Scheduler::register_task(1, &fake_workload); EXPECT_EQ(task_id == Scheduler::INVALID_ID, true); } @@ -90,7 +90,7 @@ TEST_F(SchedulerTests, TaskExecutionShort) { for (int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); - + Scheduler::update(); } // 1000 ticks / 10 ticks/task = 100 executions. From 6c2681300b0ede68f5c3237f0aad99af6c2a939c Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 1 Apr 2026 12:53:42 +0200 Subject: [PATCH 34/35] fix old compile error which shouldn't be one --- Inc/HALAL/Models/TimerDomain/TimerDomain.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp index 45d9f3d0a..d8889c954 100644 --- a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp +++ b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp @@ -546,7 +546,8 @@ TimerXList ST_LIB::compile_error("This timer is used by the scheduler"); } - if (requests[i].request != TimerRequest::AnyGeneralPurpose && + if ((requests[i].request != TimerRequest::AnyGeneralPurpose) && + (requests[i].request != TimerRequest::Any32bit) && (requests[i].request < 1 || requests[i].request > 24 || (requests[i].request > 17 && requests[i].request < 23))) { ST_LIB::compile_error("Invalid TimerRequest value for timer"); From 84f0293835f0e5e9806268f7947372479e96b48e Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 1 Apr 2026 13:05:20 +0200 Subject: [PATCH 35/35] Add set_limit_value to set arr in TimerWrapper --- Inc/HALAL/Services/Time/TimerWrapper.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Inc/HALAL/Services/Time/TimerWrapper.hpp b/Inc/HALAL/Services/Time/TimerWrapper.hpp index 0a81056a9..caece7b71 100644 --- a/Inc/HALAL/Services/Time/TimerWrapper.hpp +++ b/Inc/HALAL/Services/Time/TimerWrapper.hpp @@ -324,6 +324,8 @@ template struct TimerWrapper { inline TIM_TypeDef* get_cmsis_handle() { return instance->tim; } inline void set_prescaler(uint16_t psc) { instance->tim->PSC = psc; } + // TODO: 16 bit and 32 bit version (?) + inline void set_limit_value(uint32_t arr) { instance->tim->ARR = arr; } inline void configure32bit(void (*callback)(void*), void* callback_data, uint32_t period) { static_assert(