From 7fe90899fc9288cb1e1a5411d7a87f5decd20edd Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 14 Mar 2026 12:38:54 +0100 Subject: [PATCH 01/14] initial cleanup (no fixes found for now) --- Inc/HALAL/Services/Time/Scheduler.hpp | 13 ++++++------- Src/HALAL/Services/Time/Scheduler.cpp | 11 +++++------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index dbe965891..d8f9dc9ab 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -23,7 +23,8 @@ extern TIM_TypeDef* Scheduler_global_timer; struct Scheduler { using callback_t = void (*)(); - static constexpr uint32_t INVALID_ID = 0xFFu; + // NOTE: Changed to 0xFE since set_timeout() only outputs odd ids and it could theoretically output 0xFF + static constexpr uint32_t INVALID_ID = 0xFEU; static void start(); static void update(); @@ -37,13 +38,8 @@ struct Scheduler { static uint16_t set_timeout(uint32_t microseconds, callback_t func); static bool cancel_timeout(uint16_t id); - // static void global_timer_callback(); - - // Have to be public because SCHEDULER_GLOBAL_TIMER_CALLBACK won't work - // otherwise - // static const uint32_t global_timer_base = SCHEDULER_TIMER_BASE; + // internal static void on_timer_update(); - #ifndef SIM_ON private: #endif @@ -56,6 +52,9 @@ struct Scheduler { }; static constexpr std::size_t kMaxTasks = 16; + static_assert((INVALID_ID % 2) == 0, "INVALID_ID must be an even number"); + static_assert(INVALID_ID >= kMaxTasks, "INVALID_ID must not be a possible task id"); + static_assert((kMaxTasks & (kMaxTasks - 1)) == 0, "kMaxTasks must be a power of two"); static constexpr uint32_t FREQUENCY = 1'000'000u; // 1 MHz -> 1us precision diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 59892a0fa..f119359a0 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -35,8 +35,6 @@ inline void Scheduler::set_at(uint8_t idx, uint8_t id) { uint32_t shift = idx * 4; uint64_t clearmask = ~(0xFF << shift); Scheduler::sorted_task_ids_ = (sorted_task_ids_ & clearmask) | (id << shift); - // sorted_task_ids_ |= ((id & 0x0F) << shift); // This is also an option in case id is - // incorrect, I don't think it's necessary though } inline uint8_t Scheduler::front_id() { return *((uint8_t*)&sorted_task_ids_) & 0xF; } inline void Scheduler::pop_front() { @@ -68,6 +66,7 @@ void Scheduler::start() { Scheduler_global_timer = ST_LIB::TimerDomain::cmsis_timers[ST_LIB::timer_idxmap[SCHEDULER_TIMER_DOMAIN]]; + // TODO: change this to use TimerDomain::get_timer_clock()? uint32_t prescaler = (SystemCoreClock / Scheduler::FREQUENCY); // setup prescaler { @@ -155,7 +154,7 @@ void Scheduler::start() { void Scheduler::update() { while (ready_bitmap_ != 0u) { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); - ready_bitmap_ &= ~(1u << bit_index); // Clear the bit + CLEAR_BIT(ready_bitmap_, 1u << bit_index); Task& task = tasks_[bit_index]; task.callback(); if (!task.repeating) [[unlikely]] { @@ -319,7 +318,7 @@ uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { return static_cast(Scheduler::INVALID_ID); uint8_t slot = allocate_slot(); - if (slot == Scheduler::INVALID_ID) + if (slot == Scheduler::INVALID_ID) [[unlikely]] return slot; Task& task = tasks_[slot]; @@ -343,14 +342,14 @@ uint16_t Scheduler::set_timeout(uint32_t microseconds, callback_t func) { return static_cast(Scheduler::INVALID_ID); uint8_t slot = allocate_slot(); - if (slot == Scheduler::INVALID_ID) + if (slot == Scheduler::INVALID_ID) [[unlikely]] return slot; Task& task = tasks_[slot]; task.callback = func; task.period_us = microseconds; task.repeating = false; - task.next_fire_us = static_cast(global_tick_us_ + microseconds); + task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + microseconds); task.id = slot + Scheduler::timeout_idx_ * Scheduler::kMaxTasks; // Add 2 instead of 1 so overflow doesn't make timeout_idx == 0, From 2ade7023573fbb109fd6618784ef516153121110 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 14 Mar 2026 13:27:02 +0100 Subject: [PATCH 02/14] Start marking lock - unlocks and fix INVALID_ID again --- Inc/HALAL/Services/Time/Scheduler.hpp | 9 +++++---- Src/HALAL/Services/Time/Scheduler.cpp | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index d8f9dc9ab..60364859d 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -23,8 +23,10 @@ extern TIM_TypeDef* Scheduler_global_timer; struct Scheduler { using callback_t = void (*)(); - // NOTE: Changed to 0xFE since set_timeout() only outputs odd ids and it could theoretically output 0xFF - static constexpr uint32_t INVALID_ID = 0xFEU; + static constexpr uint32_t kMaxTasks = 16; + // INVALID_ID must be an even multiple of kMaxTasks. + // if it isn't it could theoretically be used as an id in set_timeout + static constexpr uint32_t INVALID_ID = 2*kMaxTasks; static void start(); static void update(); @@ -51,8 +53,7 @@ struct Scheduler { bool repeating{false}; }; - static constexpr std::size_t kMaxTasks = 16; - static_assert((INVALID_ID % 2) == 0, "INVALID_ID must be an even number"); + static_assert(((INVALID_ID/kMaxTasks) % 2) == 0, "INVALID_ID must be an even multiple of kMaxTasks"); static_assert(INVALID_ID >= kMaxTasks, "INVALID_ID must not be a possible task id"); static_assert((kMaxTasks & (kMaxTasks - 1)) == 0, "kMaxTasks must be a power of two"); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index f119359a0..9ea40263a 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -325,11 +325,14 @@ uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { task.callback = func; task.period_us = period_us; task.repeating = true; + task.id = static_cast(slot); + + // TODO: Lock from here task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + period_us); - task.id = static_cast(slot); insert_sorted(slot); schedule_next_interval(); + // TODO: Unlock here return task.id; } @@ -349,15 +352,17 @@ uint16_t Scheduler::set_timeout(uint32_t microseconds, callback_t func) { task.callback = func; task.period_us = microseconds; task.repeating = false; - task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + microseconds); task.id = slot + Scheduler::timeout_idx_ * Scheduler::kMaxTasks; - // Add 2 instead of 1 so overflow doesn't make timeout_idx == 0, // we need it to never be 0 Scheduler::timeout_idx_ += 2; + // TODO: Lock from here + task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + microseconds); insert_sorted(slot); schedule_next_interval(); + // TODO: Unlock here + return task.id; } @@ -367,9 +372,11 @@ bool Scheduler::unregister_task(uint16_t id) { if (free_bitmap_ & (1UL << id)) return false; + // TODO: Lock from here remove_sorted(id); release_slot(id); schedule_next_interval(); + // TODO: Unlock here return true; } @@ -383,8 +390,10 @@ bool Scheduler::cancel_timeout(uint16_t id) { if (free_bitmap_ & (1UL << idx)) return false; + // TODO: Lock from here remove_sorted(idx); release_slot(idx); schedule_next_interval(); + // TODO: Unlock here return true; } From 1b4fb551f3fc7d75189c5a1e397cf36e7d7fcbd0 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 14 Mar 2026 13:31:07 +0100 Subject: [PATCH 03/14] Add last sync mark, need to implement them though --- Src/HALAL/Services/Time/Scheduler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 9ea40263a..bbc598c15 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -158,7 +158,9 @@ void Scheduler::update() { Task& task = tasks_[bit_index]; task.callback(); if (!task.repeating) [[unlikely]] { + // TODO: Lock from here release_slot(static_cast(bit_index)); + // TODO: Unlock here } } } From e482886902d7f73fef888bf7336c0b74f09c2d73 Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 14 Mar 2026 15:35:23 +0100 Subject: [PATCH 04/14] Exclusive store for ready_bitmap_ --- Src/HALAL/Services/Time/Scheduler.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index bbc598c15..d80c8a851 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -154,7 +154,11 @@ void Scheduler::start() { void Scheduler::update() { while (ready_bitmap_ != 0u) { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); - CLEAR_BIT(ready_bitmap_, 1u << bit_index); + + //CLEAR_BIT(ready_bitmap_, 1u << bit_index); + uint32_t new_ready_bitmap = ready_bitmap_ & ~(1U << bit_index); + __STREXW(new_ready_bitmap, (volatile uint32_t*)&ready_bitmap_); + Task& task = tasks_[bit_index]; task.callback(); if (!task.repeating) [[unlikely]] { @@ -300,7 +304,10 @@ void Scheduler::on_timer_update() { break; // Task is in the future, stop processing } pop_front(); - ready_bitmap_ |= (1u << candidate_id); // mark task as ready + + //ready_bitmap_ |= (1u << candidate_id); // mark task as ready + uint32_t new_ready_bmp = ready_bitmap_ | (1U << candidate_id); + __STREXW(new_ready_bmp, (volatile uint32_t*)&ready_bitmap_); if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); From 526970720a471878d9ef3c6e4041931800ab2e7a Mon Sep 17 00:00:00 2001 From: victhor Date: Sat, 14 Mar 2026 15:42:17 +0100 Subject: [PATCH 05/14] Add more lock marks for interrupt callback --- Src/HALAL/Services/Time/Scheduler.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index d80c8a851..2dc5ed977 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -303,7 +303,9 @@ void Scheduler::on_timer_update() { if (diff > 0) [[likely]] { break; // Task is in the future, stop processing } + // TODO: Lock from here pop_front(); + // TODO: Unlock here //ready_bitmap_ |= (1u << candidate_id); // mark task as ready uint32_t new_ready_bmp = ready_bitmap_ | (1U << candidate_id); @@ -311,11 +313,15 @@ void Scheduler::on_timer_update() { if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); + // TODO: Lock from here insert_sorted(candidate_id); + // TODO: Unlock here } } + // TODO: Lock from here schedule_next_interval(); + // TODO: Unlock here } uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { From 9bc043e5577cc79f45d448f80d4bae09d31eea2c Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 12:13:08 +0100 Subject: [PATCH 06/14] Add SchedLock, SchedUnlock via NVIC --- Src/HALAL/Services/Time/Scheduler.cpp | 43 +++++++++++++-------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 2dc5ed977..cb194ec60 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -10,6 +10,9 @@ #include +#define SchedLock() NVIC_DisableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) +#define SchedUnlock() NVIC_EnableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) + TIM_TypeDef* Scheduler_global_timer = nullptr; namespace { @@ -155,16 +158,14 @@ void Scheduler::update() { while (ready_bitmap_ != 0u) { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); - //CLEAR_BIT(ready_bitmap_, 1u << bit_index); - uint32_t new_ready_bitmap = ready_bitmap_ & ~(1U << bit_index); - __STREXW(new_ready_bitmap, (volatile uint32_t*)&ready_bitmap_); + CLEAR_BIT(ready_bitmap_, 1u << bit_index); Task& task = tasks_[bit_index]; task.callback(); if (!task.repeating) [[unlikely]] { - // TODO: Lock from here + SchedLock(); release_slot(static_cast(bit_index)); - // TODO: Unlock here + SchedUnlock(); } } } @@ -303,25 +304,23 @@ void Scheduler::on_timer_update() { if (diff > 0) [[likely]] { break; // Task is in the future, stop processing } - // TODO: Lock from here + SchedLock(); pop_front(); - // TODO: Unlock here + SchedUnlock(); - //ready_bitmap_ |= (1u << candidate_id); // mark task as ready - uint32_t new_ready_bmp = ready_bitmap_ | (1U << candidate_id); - __STREXW(new_ready_bmp, (volatile uint32_t*)&ready_bitmap_); + ready_bitmap_ |= (1u << candidate_id); // mark task as ready if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); - // TODO: Lock from here + SchedLock(); insert_sorted(candidate_id); - // TODO: Unlock here + SchedUnlock(); } } - // TODO: Lock from here + SchedLock(); schedule_next_interval(); - // TODO: Unlock here + SchedUnlock(); } uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { @@ -342,12 +341,12 @@ uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { task.repeating = true; task.id = static_cast(slot); - // TODO: Lock from here + SchedLock(); task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + period_us); insert_sorted(slot); schedule_next_interval(); - // TODO: Unlock here + SchedUnlock(); return task.id; } @@ -372,11 +371,11 @@ uint16_t Scheduler::set_timeout(uint32_t microseconds, callback_t func) { // we need it to never be 0 Scheduler::timeout_idx_ += 2; - // TODO: Lock from here + SchedLock(); task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + microseconds); insert_sorted(slot); schedule_next_interval(); - // TODO: Unlock here + SchedUnlock(); return task.id; } @@ -387,11 +386,11 @@ bool Scheduler::unregister_task(uint16_t id) { if (free_bitmap_ & (1UL << id)) return false; - // TODO: Lock from here + SchedLock(); remove_sorted(id); release_slot(id); schedule_next_interval(); - // TODO: Unlock here + SchedUnlock(); return true; } @@ -405,10 +404,10 @@ bool Scheduler::cancel_timeout(uint16_t id) { if (free_bitmap_ & (1UL << idx)) return false; - // TODO: Lock from here + SchedLock(); remove_sorted(idx); release_slot(idx); schedule_next_interval(); - // TODO: Unlock here + SchedUnlock(); return true; } From e5ca89ebcb2b050fb1b68da8a3e760eb7dae8c40 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 12:19:20 +0100 Subject: [PATCH 07/14] fomatting --- Inc/HALAL/Services/Time/Scheduler.hpp | 7 +++++-- Src/HALAL/Services/Time/Scheduler.cpp | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 60364859d..eb358c72d 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -26,7 +26,7 @@ struct Scheduler { static constexpr uint32_t kMaxTasks = 16; // INVALID_ID must be an even multiple of kMaxTasks. // if it isn't it could theoretically be used as an id in set_timeout - static constexpr uint32_t INVALID_ID = 2*kMaxTasks; + static constexpr uint32_t INVALID_ID = 2 * kMaxTasks; static void start(); static void update(); @@ -53,7 +53,10 @@ struct Scheduler { bool repeating{false}; }; - static_assert(((INVALID_ID/kMaxTasks) % 2) == 0, "INVALID_ID must be an even multiple of kMaxTasks"); + static_assert( + ((INVALID_ID/kMaxTasks) % 2) == 0, + "INVALID_ID must be an even multiple of kMaxTasks" + ); static_assert(INVALID_ID >= kMaxTasks, "INVALID_ID must not be a possible task id"); static_assert((kMaxTasks & (kMaxTasks - 1)) == 0, "kMaxTasks must be a power of two"); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index cb194ec60..09e76b2fc 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -10,7 +10,7 @@ #include -#define SchedLock() NVIC_DisableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) +#define SchedLock() NVIC_DisableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) #define SchedUnlock() NVIC_EnableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) TIM_TypeDef* Scheduler_global_timer = nullptr; @@ -307,7 +307,7 @@ void Scheduler::on_timer_update() { SchedLock(); pop_front(); SchedUnlock(); - + ready_bitmap_ |= (1u << candidate_id); // mark task as ready if (task.repeating) [[likely]] { From bf43942393dd781fc7e57abd2efd05b160bc6053 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 12:22:07 +0100 Subject: [PATCH 08/14] fix slight inaccuracy --- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Src/HALAL/Services/Time/Scheduler.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index eb358c72d..fd6b414d4 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -54,7 +54,7 @@ struct Scheduler { }; static_assert( - ((INVALID_ID/kMaxTasks) % 2) == 0, + ((INVALID_ID / kMaxTasks) % 2) == 0, "INVALID_ID must be an even multiple of kMaxTasks" ); static_assert(INVALID_ID >= kMaxTasks, "INVALID_ID must not be a possible task id"); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 09e76b2fc..a26af9864 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -311,8 +311,9 @@ void Scheduler::on_timer_update() { ready_bitmap_ |= (1u << candidate_id); // mark task as ready if (task.repeating) [[likely]] { - task.next_fire_us = static_cast(global_tick_us_ + task.period_us); SchedLock(); + task.next_fire_us = + static_cast(global_tick_us_ + Scheduler_global_timer->CNT + task.period_us); insert_sorted(candidate_id); SchedUnlock(); } @@ -372,7 +373,8 @@ uint16_t Scheduler::set_timeout(uint32_t microseconds, callback_t func) { Scheduler::timeout_idx_ += 2; SchedLock(); - task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + microseconds); + task.next_fire_us = + static_cast(global_tick_us_ + Scheduler_global_timer->CNT + microseconds); insert_sorted(slot); schedule_next_interval(); SchedUnlock(); From b0478d2ae319836f3f2a45c8798434a48c7d9ccf Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 12:52:11 +0100 Subject: [PATCH 09/14] Slight inaccuracy was not a slight inaccuracy lol --- Src/HALAL/Services/Time/Scheduler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index a26af9864..3a7b6ecca 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -308,12 +308,12 @@ void Scheduler::on_timer_update() { pop_front(); SchedUnlock(); - ready_bitmap_ |= (1u << candidate_id); // mark task as ready + // mark task as ready + SET_BIT(ready_bitmap_, 1u << candidate_id); if (task.repeating) [[likely]] { SchedLock(); - task.next_fire_us = - static_cast(global_tick_us_ + Scheduler_global_timer->CNT + task.period_us); + task.next_fire_us = static_cast(global_tick_us_ + task.period_us); insert_sorted(candidate_id); SchedUnlock(); } From 8c8b6251da4c954edbb47274bf0507d1a2dec2e8 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 13:09:50 +0100 Subject: [PATCH 10/14] remove lock in interrupt callback --- Src/HALAL/Services/Time/Scheduler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 3a7b6ecca..2114d10ae 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -304,9 +304,7 @@ void Scheduler::on_timer_update() { if (diff > 0) [[likely]] { break; // Task is in the future, stop processing } - SchedLock(); pop_front(); - SchedUnlock(); // mark task as ready SET_BIT(ready_bitmap_, 1u << candidate_id); From 0aedc098ddc928baaceca7a7ae9491818f338316 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 13:17:20 +0100 Subject: [PATCH 11/14] Add cmsis_timers to state_machine_test --- Tests/StateMachine/state_machine_test.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Tests/StateMachine/state_machine_test.cpp b/Tests/StateMachine/state_machine_test.cpp index 2cd1119f2..4c176d6ad 100644 --- a/Tests/StateMachine/state_machine_test.cpp +++ b/Tests/StateMachine/state_machine_test.cpp @@ -2,6 +2,25 @@ #include "ST-LIB_LOW/StateMachine/StateMachine.hpp" #include "HALAL/Services/Time/Scheduler.hpp" +TIM_TypeDef* ST_LIB::TimerDomain::cmsis_timers[16] = { + [0] = TIM2_BASE, + [1] = TIM3_BASE, + [2] = TIM4_BASE, + [3] = TIM5_BASE, + [4] = TIM23_BASE, + [5] = TIM24_BASE, + [6] = TIM12_BASE, + [7] = TIM13_BASE, + [8] = TIM14_BASE, + [9] = TIM15_BASE, + [10] = TIM16_BASE, + [11] = TIM17_BASE, + [12] = TIM6_BASE, + [13] = TIM7_BASE, + [14] = TIM1_BASE, + [15] = TIM8_BASE, +}; + enum class MasterState { A, B, C }; enum class SubState { S1, S2 }; From 02c0a3fe8731eb933491d3ca95457d6f64dd5249 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 13:22:10 +0100 Subject: [PATCH 12/14] fix state_machine_test part 2 --- Tests/StateMachine/state_machine_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/StateMachine/state_machine_test.cpp b/Tests/StateMachine/state_machine_test.cpp index 4c176d6ad..50d5bba07 100644 --- a/Tests/StateMachine/state_machine_test.cpp +++ b/Tests/StateMachine/state_machine_test.cpp @@ -1,5 +1,6 @@ #include #include "ST-LIB_LOW/StateMachine/StateMachine.hpp" +#include "HALAL/Models/TimerDomain/TimerDomain.hpp" #include "HALAL/Services/Time/Scheduler.hpp" TIM_TypeDef* ST_LIB::TimerDomain::cmsis_timers[16] = { From 0402fd55e21b54b20021dcae5de8906e257f0ad7 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 13:41:50 +0100 Subject: [PATCH 13/14] fix tests and add gdb simulator debug option --- .vscode/launch.json | 23 ++++++++++++++++++- Inc/HALAL/Models/TimerDomain/TimerDomain.hpp | 7 +++--- Src/HALAL/Services/Time/Scheduler.cpp | 2 ++ Tests/StateMachine/state_machine_test.cpp | 24 ++++---------------- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 4643e2cb5..7c7f584d5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -26,6 +26,27 @@ "stopAtEntry": false, "MIMode": "lldb", "preLaunchTask": "CMake: build" - } + }, + { + "name": "Debug ST-LIB tests (simulator) [gdb]", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/out/build/simulator/Tests/st-lib-test", + "args": [ + "--gtest_break_on_failure" + ], + "cwd": "${workspaceFolder}", + "externalConsole": false, + "stopAtEntry": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "CMake: build" + }, ] } diff --git a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp index e4187a054..a5502bd78 100644 --- a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp +++ b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp @@ -26,8 +26,7 @@ (SCHEDULER_TIMER_DOMAIN != 23) && (SCHEDULER_TIMER_DOMAIN != 24) #error Scheduler timer must be a 32 bit timer #endif - -#define SCHEDULER_GLOBAL_TIMER_IRQn glue(TIM, glue(SCHEDULER_TIMER_DOMAIN, _IRQn)) +extern TIM_TypeDef* Scheduler_global_timer; // NOTE: only works for static arrays #define ARRAY_LENGTH(a) (sizeof(a) / sizeof(*a)) @@ -676,8 +675,8 @@ TimerXList static inline std::array instances{}; static void init(std::span cfgs) { - TIM_TypeDef* sched_timer = cmsis_timers[timer_idxmap[SCHEDULER_TIMER_DOMAIN]]; - rcc_enable_timer(sched_timer); + Scheduler_global_timer = cmsis_timers[timer_idxmap[SCHEDULER_TIMER_DOMAIN]]; + rcc_enable_timer(Scheduler_global_timer); for (std::size_t i = 0; i < N; i++) { const Config& e = cfgs[i]; diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 2114d10ae..c953f553d 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -10,6 +10,8 @@ #include +#define SCHEDULER_GLOBAL_TIMER_IRQn glue(TIM, glue(SCHEDULER_TIMER_DOMAIN, _IRQn)) + #define SchedLock() NVIC_DisableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) #define SchedUnlock() NVIC_EnableIRQ(SCHEDULER_GLOBAL_TIMER_IRQn) diff --git a/Tests/StateMachine/state_machine_test.cpp b/Tests/StateMachine/state_machine_test.cpp index 50d5bba07..017c5a0d6 100644 --- a/Tests/StateMachine/state_machine_test.cpp +++ b/Tests/StateMachine/state_machine_test.cpp @@ -1,26 +1,7 @@ #include #include "ST-LIB_LOW/StateMachine/StateMachine.hpp" -#include "HALAL/Models/TimerDomain/TimerDomain.hpp" #include "HALAL/Services/Time/Scheduler.hpp" - -TIM_TypeDef* ST_LIB::TimerDomain::cmsis_timers[16] = { - [0] = TIM2_BASE, - [1] = TIM3_BASE, - [2] = TIM4_BASE, - [3] = TIM5_BASE, - [4] = TIM23_BASE, - [5] = TIM24_BASE, - [6] = TIM12_BASE, - [7] = TIM13_BASE, - [8] = TIM14_BASE, - [9] = TIM15_BASE, - [10] = TIM16_BASE, - [11] = TIM17_BASE, - [12] = TIM6_BASE, - [13] = TIM7_BASE, - [14] = TIM1_BASE, - [15] = TIM8_BASE, -}; +#include "HALAL/Models/TimerDomain/TimerDomain.hpp" enum class MasterState { A, B, C }; @@ -85,6 +66,9 @@ static void reset_test_state() { TIM2_BASE->SR = 0; TIM2_BASE->CR1 = 0; TIM2_BASE->DIER = 0; + + Scheduler_global_timer = + ST_LIB::TimerDomain::cmsis_timers[ST_LIB::timer_idxmap[SCHEDULER_TIMER_DOMAIN]]; } static void tick_scheduler(int ticks) { From 9719f7333ba49fcb4791ae6865358881eb69e842 Mon Sep 17 00:00:00 2001 From: victhor Date: Sun, 15 Mar 2026 14:44:49 +0100 Subject: [PATCH 14/14] remove _all_ locks from on_timer_update() --- Src/HALAL/Services/Time/Scheduler.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index c953f553d..9f01f4124 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -312,16 +312,12 @@ void Scheduler::on_timer_update() { SET_BIT(ready_bitmap_, 1u << candidate_id); if (task.repeating) [[likely]] { - SchedLock(); 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) {