From ecc148bde636b804f22bd008db873572d021a5eb Mon Sep 17 00:00:00 2001 From: victhor Date: Thu, 16 Apr 2026 18:59:04 +0200 Subject: [PATCH 1/9] implement an array of the last 2^n task times --- Inc/HALAL/Services/Time/Scheduler.hpp | 10 ++++++++ Src/HALAL/Services/Time/Scheduler.cpp | 37 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index ceb16e198..40741238f 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -27,6 +27,16 @@ #include "stm32h7xx_hal_tim.h" #endif +//#define SLOW_CHECK_USE_READY_BITMAP +#define SLOW_CHECK_USE_LAST_N_TASKS + +#define SLOW_CHECK_USE_LAST_N_TASKS_COUNT 512 + +#if defined(SLOW_CHECK_USE_LAST_N_TASKS) +// Must be a 32 bit timer and not be the same as the scheduler timer +extern TIM_TypeDef* perf_timer; +#endif + extern TIM_TypeDef* Scheduler_global_timer; void Scheduler_global_timer_callback(void* raw); void Scheduler_start(void); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index ac215b4b4..32f1b8bf5 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -31,8 +31,30 @@ uint64_t Scheduler::global_tick_us_{0}; uint32_t Scheduler::current_interval_us_{0}; uint16_t Scheduler::timeout_idx_{1}; +#if (SLOW_CHECK_USE_LAST_N_TASKS_COUNT & (SLOW_CHECK_USE_LAST_N_TASKS_COUNT - 1)) != 0 +// NOTE: Performance: this is to use an and instead of a mod when storing the data +#error SLOW_CHECK_USE_LAST_N_TASKS_COUNT must be a power of 2 +#endif + +#if defined(SLOW_CHECK_USE_READY_BITMAP) uint16_t failing_id = Scheduler::INVALID_ID; +#elif defined(SLOW_CHECK_USE_LAST_N_TASKS) +struct TaskTimeInfo { + uint16_t id; + uint32_t start_time; + uint32_t end_time; +}; +TaskTimeInfo time_info[SLOW_CHECK_USE_LAST_N_TASKS_COUNT]{}; +#if SLOW_CHECK_USE_LAST_N_TASKS_COUNT > 65536 +#error Use a uint32_t instead and remove these lines +#endif +uint16_t current_time_info{0}; + +// Must be a 32 bit timer and not be the same as the scheduler timer +TIM_TypeDef *perf_timer; +#endif + // ---------------------------- inline void Scheduler::global_timer_disable() { @@ -75,19 +97,32 @@ void Scheduler_start(void) { } void Scheduler::update() { +#ifdef SLOW_CHECK_USE_READY_BITMAP // NOTE: Only _one_ id will be shown per call to update() if (failing_id != Scheduler::INVALID_ID) [[unlikely]] { WARNING("Too slow, could not execute task %u in time", failing_id); failing_id = Scheduler::INVALID_ID; } +#endif while (ready_bitmap_ != 0u) { uint32_t bit_index = static_cast(__builtin_ctz(ready_bitmap_)); Task& task = tasks_[bit_index]; +#if defined(SLOW_CHECK_USE_LAST_N_TASKS) + TaskTimeInfo *info = time_info + current_time_info; + info->id = bit_index; + info->start_time = perf_timer->CNT; +#endif + task.callback(); +#if defined(SLOW_CHECK_USE_LAST_N_TASKS) + info->end_time = perf_timer->CNT; + current_time_info = (current_time_info + 1) & SLOW_CHECK_USE_LAST_N_TASKS_COUNT; +#endif + SchedLock(); CLEAR_BIT(ready_bitmap_, 1u << bit_index); if (!task.repeating) [[unlikely]] { @@ -246,9 +281,11 @@ inline void Scheduler::on_timer_update() { SchedLock(); pop_front(); // mark task as ready +#ifdef SLOW_CHECK_USE_READY_BITMAP if ((ready_bitmap_ & task_bit) != 0) [[unlikely]] { failing_id = candidate_id; } +#endif SET_BIT(ready_bitmap_, task_bit); if (task.repeating) [[likely]] { task.next_fire_us = static_cast(global_tick_us_ + task.period_us); From 19cf710aa9d698275002db0f4bece3c93e929aa3 Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 13 May 2026 18:37:01 +0200 Subject: [PATCH 2/9] Add changeset and uart helper --- .changesets/scheduler-get-perf.md | 2 ++ .../Services/Communication/UART/UART.hpp | 10 ++++++ Inc/HALAL/Services/Time/Scheduler.hpp | 22 +++++++----- .../Services/Communication/UART/UART.cpp | 6 +++- Src/HALAL/Services/Time/Scheduler.cpp | 34 ++++++++++++++----- 5 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 .changesets/scheduler-get-perf.md diff --git a/.changesets/scheduler-get-perf.md b/.changesets/scheduler-get-perf.md new file mode 100644 index 000000000..25590042d --- /dev/null +++ b/.changesets/scheduler-get-perf.md @@ -0,0 +1,2 @@ +release: minor +summary: Implement simple performance gathering with the scheduler diff --git a/Inc/HALAL/Services/Communication/UART/UART.hpp b/Inc/HALAL/Services/Communication/UART/UART.hpp index d3ac241b5..cecce6603 100644 --- a/Inc/HALAL/Services/Communication/UART/UART.hpp +++ b/Inc/HALAL/Services/Communication/UART/UART.hpp @@ -160,6 +160,16 @@ class UART { */ static bool transmit_polling(uint8_t id, span data); + /**@brief Transmits size bytes by polling. + * + * @param id Id of the UART + * @param data Pointer to data to be sent. + * @param length Length of data to be sent. + * @return bool Returns true if the packet has been send successfully. + * Returns false if the UART is busy or a problem has occurred. + */ + static bool transmit_polling(uint8_t id, uint8_t *data, size_t length); + /** * @brief This method request the receive of size bytes * by DMA and interrupts. Thus the data should not be used until diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 40741238f..36bb55b1c 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -27,16 +27,16 @@ #include "stm32h7xx_hal_tim.h" #endif -//#define SLOW_CHECK_USE_READY_BITMAP -#define SLOW_CHECK_USE_LAST_N_TASKS - -#define SLOW_CHECK_USE_LAST_N_TASKS_COUNT 512 +#ifndef SIM_ON +#define SCHEDULER_GET_LAST_N_TASKS +#endif -#if defined(SLOW_CHECK_USE_LAST_N_TASKS) -// Must be a 32 bit timer and not be the same as the scheduler timer -extern TIM_TypeDef* perf_timer; +#if !defined(SCHEDULER_GET_LAST_N_TASKS) && !defined(SLOW_CHECK_USE_READY_BITMAP) +#define SLOW_CHECK_USE_READY_BITMAP #endif +#define SCHEDULER_GET_LAST_N_TASKS_COUNT 512 + extern TIM_TypeDef* Scheduler_global_timer; void Scheduler_global_timer_callback(void* raw); void Scheduler_start(void); @@ -48,8 +48,12 @@ struct Scheduler { // if it isn't it could theoretically be used as an id in set_timeout static constexpr uint32_t INVALID_ID = 2 * kMaxTasks; - // temporary, will be removed - [[deprecated]] static inline void start() {} + /* gets and checks the performance gathering requirements + * @param tim32bit: A timer or null if not gathering perf info (preferrably 32 bit) + * @return If the given arguments are correct + */ + static bool init_perf(TIM_TypeDef* tim32bit); + static void update(); static uint64_t get_global_tick(); diff --git a/Src/HALAL/Services/Communication/UART/UART.cpp b/Src/HALAL/Services/Communication/UART/UART.cpp index 7772626f1..44cf49e8e 100644 --- a/Src/HALAL/Services/Communication/UART/UART.cpp +++ b/Src/HALAL/Services/Communication/UART/UART.cpp @@ -64,6 +64,10 @@ bool UART::transmit_polling(uint8_t id, uint8_t data) { } bool UART::transmit_polling(uint8_t id, span data) { + return UART::transmit_polling(id, data.data(), data.size()); +} + +bool UART::transmit_polling(uint8_t id, uint8_t *data, size_t length) { if (not UART::registered_uart.contains(id)) return false; // TODO: Error handler @@ -72,7 +76,7 @@ bool UART::transmit_polling(uint8_t id, span data) { if ((handle->ErrorCode & TXBUSYMASK) == 1) return false; - if (HAL_UART_Transmit(handle, data.data(), data.size(), 10) != HAL_OK) { + if (HAL_UART_Transmit(handle, data, length, 10) != HAL_OK) { return false; // TODO: Warning, Error during transmision } diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 6ade7f092..9132a6aa4 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -31,22 +31,22 @@ uint64_t Scheduler::global_tick_us_{0}; uint32_t Scheduler::current_interval_us_{0}; uint16_t Scheduler::timeout_idx_{1}; -#if (SLOW_CHECK_USE_LAST_N_TASKS_COUNT & (SLOW_CHECK_USE_LAST_N_TASKS_COUNT - 1)) != 0 +#if (SCHEDULER_GET_LAST_N_TASKS_COUNT & (SCHEDULER_GET_LAST_N_TASKS_COUNT - 1)) != 0 // NOTE: Performance: this is to use an and instead of a mod when storing the data -#error SLOW_CHECK_USE_LAST_N_TASKS_COUNT must be a power of 2 +#error SCHEDULER_GET_LAST_N_TASKS_COUNT must be a power of 2 #endif #if defined(SLOW_CHECK_USE_READY_BITMAP) uint16_t failing_id = Scheduler::INVALID_ID; -#elif defined(SLOW_CHECK_USE_LAST_N_TASKS) +#elif defined(SCHEDULER_GET_LAST_N_TASKS) struct TaskTimeInfo { uint16_t id; uint32_t start_time; uint32_t end_time; }; -TaskTimeInfo time_info[SLOW_CHECK_USE_LAST_N_TASKS_COUNT]{}; -#if SLOW_CHECK_USE_LAST_N_TASKS_COUNT > 65536 +TaskTimeInfo time_info[SCHEDULER_GET_LAST_N_TASKS_COUNT]{}; +#if SCHEDULER_GET_LAST_N_TASKS_COUNT > 65536 #error Use a uint32_t instead and remove these lines #endif uint16_t current_time_info{0}; @@ -99,6 +99,22 @@ void Scheduler_start(void) { Scheduler::schedule_next_interval(); } +bool Scheduler::init_perf(TIM_TypeDef* tim32bit) +{ +#ifdef SCHEDULER_GET_LAST_N_TASKS + if (!tim32bit) { + return false; + } + + perf_timer = tim32bit; + + return true; +#else + (void)tim32bit; + return true; +#endif +} + void Scheduler::update() { #ifdef SLOW_CHECK_USE_READY_BITMAP // NOTE: Only _one_ id will be shown per call to update() @@ -113,17 +129,17 @@ void Scheduler::update() { Task& task = tasks_[bit_index]; -#if defined(SLOW_CHECK_USE_LAST_N_TASKS) - TaskTimeInfo *info = time_info + current_time_info; +#if defined(SCHEDULER_GET_LAST_N_TASKS) + TaskTimeInfo* info = time_info + current_time_info; info->id = bit_index; info->start_time = perf_timer->CNT; #endif task.callback(); -#if defined(SLOW_CHECK_USE_LAST_N_TASKS) +#if defined(SCHEDULER_GET_LAST_N_TASKS) info->end_time = perf_timer->CNT; - current_time_info = (current_time_info + 1) & SLOW_CHECK_USE_LAST_N_TASKS_COUNT; + current_time_info = (current_time_info + 1) & SCHEDULER_GET_LAST_N_TASKS_COUNT; #endif SchedLock(); From 513aa56ea16ca47439568e06a961d2c3105ea8ac Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 13 May 2026 19:39:11 +0200 Subject: [PATCH 3/9] setup uart usage --- Inc/HALAL/Services/Time/Scheduler.hpp | 8 +++++--- Src/HALAL/Services/Time/Scheduler.cpp | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 36bb55b1c..c75d323c3 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -17,7 +17,7 @@ #endif #include "stm32h7xx_ll_tim_wrapper.h" -#include "HALAL/Models/Packets/Packet.hpp" +#include "HALAL/Services/Communication/UART/UART.hpp" #include #include @@ -35,7 +35,9 @@ #define SLOW_CHECK_USE_READY_BITMAP #endif -#define SCHEDULER_GET_LAST_N_TASKS_COUNT 512 +#if !defined(SCHEDULER_GET_LAST_N_TASKS_COUNT) +#define SCHEDULER_GET_LAST_N_TASKS_COUNT 16 +#endif extern TIM_TypeDef* Scheduler_global_timer; void Scheduler_global_timer_callback(void* raw); @@ -52,7 +54,7 @@ struct Scheduler { * @param tim32bit: A timer or null if not gathering perf info (preferrably 32 bit) * @return If the given arguments are correct */ - static bool init_perf(TIM_TypeDef* tim32bit); + static bool init_perf(TIM_TypeDef* tim32bit, UART::Peripheral* uart); static void update(); static uint64_t get_global_tick(); diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 9132a6aa4..6933a7083 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -52,7 +52,8 @@ TaskTimeInfo time_info[SCHEDULER_GET_LAST_N_TASKS_COUNT]{}; uint16_t current_time_info{0}; // Must be a 32 bit timer and not be the same as the scheduler timer -TIM_TypeDef *perf_timer; +TIM_TypeDef *perf_timer{nullptr}; +uint8_t uart_id{0}; #endif // ---------------------------- @@ -99,7 +100,7 @@ void Scheduler_start(void) { Scheduler::schedule_next_interval(); } -bool Scheduler::init_perf(TIM_TypeDef* tim32bit) +bool Scheduler::init_perf(TIM_TypeDef* tim32bit, UART::Peripheral* uart) { #ifdef SCHEDULER_GET_LAST_N_TASKS if (!tim32bit) { @@ -108,9 +109,12 @@ bool Scheduler::init_perf(TIM_TypeDef* tim32bit) perf_timer = tim32bit; + uart_id = UART::inscribe(*uart); + return true; #else (void)tim32bit; + (void)uart; return true; #endif } @@ -122,6 +126,8 @@ void Scheduler::update() { WARNING("Too slow, could not execute task %u in time", failing_id); failing_id = Scheduler::INVALID_ID; } +#elif defined(SCHEDULER_GET_LAST_N_TASKS) + current_time_info = 0; #endif while (ready_bitmap_ != 0u) { @@ -139,7 +145,7 @@ void Scheduler::update() { #if defined(SCHEDULER_GET_LAST_N_TASKS) info->end_time = perf_timer->CNT; - current_time_info = (current_time_info + 1) & SCHEDULER_GET_LAST_N_TASKS_COUNT; + current_time_info = current_time_info + 1; #endif SchedLock(); @@ -149,6 +155,12 @@ void Scheduler::update() { } SchedUnlock(); } + +#if defined(SCHEDULER_GET_LAST_N_TASKS) + if (UART::transmit_polling(uart_id, (uint8_t*)&time_info, sizeof(TaskTimeInfo)*current_time_info)) { + WARNING("UART Error while trying to transmit timing info"); + } +#endif } uint64_t Scheduler::get_global_tick() { From aa5c0cc2e8d18aa8bf4759b3901877f65c1abb54 Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 13 May 2026 19:40:05 +0200 Subject: [PATCH 4/9] 16 default tasks ---> 64 --- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index c75d323c3..0ce07924d 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -36,7 +36,7 @@ #endif #if !defined(SCHEDULER_GET_LAST_N_TASKS_COUNT) -#define SCHEDULER_GET_LAST_N_TASKS_COUNT 16 +#define SCHEDULER_GET_LAST_N_TASKS_COUNT 64 #endif extern TIM_TypeDef* Scheduler_global_timer; From b9b09c3085aaab7fa6d6b9097d0a7602bdae0f24 Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 13 May 2026 20:14:21 +0200 Subject: [PATCH 5/9] formatting --- Inc/HALAL/Services/Communication/UART/UART.hpp | 2 +- Src/HALAL/Services/Communication/UART/UART.cpp | 2 +- Src/HALAL/Services/Time/Scheduler.cpp | 11 +++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Inc/HALAL/Services/Communication/UART/UART.hpp b/Inc/HALAL/Services/Communication/UART/UART.hpp index cecce6603..164f48c86 100644 --- a/Inc/HALAL/Services/Communication/UART/UART.hpp +++ b/Inc/HALAL/Services/Communication/UART/UART.hpp @@ -168,7 +168,7 @@ class UART { * @return bool Returns true if the packet has been send successfully. * Returns false if the UART is busy or a problem has occurred. */ - static bool transmit_polling(uint8_t id, uint8_t *data, size_t length); + static bool transmit_polling(uint8_t id, uint8_t* data, size_t length); /** * @brief This method request the receive of size bytes diff --git a/Src/HALAL/Services/Communication/UART/UART.cpp b/Src/HALAL/Services/Communication/UART/UART.cpp index 44cf49e8e..a070a4a0d 100644 --- a/Src/HALAL/Services/Communication/UART/UART.cpp +++ b/Src/HALAL/Services/Communication/UART/UART.cpp @@ -67,7 +67,7 @@ bool UART::transmit_polling(uint8_t id, span data) { return UART::transmit_polling(id, data.data(), data.size()); } -bool UART::transmit_polling(uint8_t id, uint8_t *data, size_t length) { +bool UART::transmit_polling(uint8_t id, uint8_t* data, size_t length) { if (not UART::registered_uart.contains(id)) return false; // TODO: Error handler diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 6933a7083..67f9b6db7 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -52,7 +52,7 @@ TaskTimeInfo time_info[SCHEDULER_GET_LAST_N_TASKS_COUNT]{}; uint16_t current_time_info{0}; // Must be a 32 bit timer and not be the same as the scheduler timer -TIM_TypeDef *perf_timer{nullptr}; +TIM_TypeDef* perf_timer{nullptr}; uint8_t uart_id{0}; #endif @@ -100,8 +100,7 @@ void Scheduler_start(void) { Scheduler::schedule_next_interval(); } -bool Scheduler::init_perf(TIM_TypeDef* tim32bit, UART::Peripheral* uart) -{ +bool Scheduler::init_perf(TIM_TypeDef* tim32bit, UART::Peripheral* uart) { #ifdef SCHEDULER_GET_LAST_N_TASKS if (!tim32bit) { return false; @@ -157,7 +156,11 @@ void Scheduler::update() { } #if defined(SCHEDULER_GET_LAST_N_TASKS) - if (UART::transmit_polling(uart_id, (uint8_t*)&time_info, sizeof(TaskTimeInfo)*current_time_info)) { + if (UART::transmit_polling( + uart_id, + (uint8_t*)&time_info, + sizeof(TaskTimeInfo) * current_time_info + )) { WARNING("UART Error while trying to transmit timing info"); } #endif From d666e01934b7806962df000d33ca1640544045e3 Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 13 May 2026 20:16:01 +0200 Subject: [PATCH 6/9] dummy for compiling tests --- Inc/HALAL/Services/Time/Scheduler.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 0ce07924d..4a453c13c 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -29,6 +29,13 @@ #ifndef SIM_ON #define SCHEDULER_GET_LAST_N_TASKS +#else +struct UART { + struct Peripheral { + uint8_t ignore0; + }; + uint8_t ignore1; +}; #endif #if !defined(SCHEDULER_GET_LAST_N_TASKS) && !defined(SLOW_CHECK_USE_READY_BITMAP) From 005868dcc659bec4169d8eed79f651b8c95a2aa4 Mon Sep 17 00:00:00 2001 From: victhor Date: Wed, 13 May 2026 20:26:38 +0200 Subject: [PATCH 7/9] formatting --- Inc/HALAL/Services/Time/Scheduler.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index 4a453c13c..b4c97afea 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -31,10 +31,10 @@ #define SCHEDULER_GET_LAST_N_TASKS #else struct UART { - struct Peripheral { - uint8_t ignore0; - }; - uint8_t ignore1; + struct Peripheral { + uint8_t ignore0; + }; + uint8_t ignore1; }; #endif From 9ac6c190407ee72a7dc2750696f4a187615769c3 Mon Sep 17 00:00:00 2001 From: victhor Date: Mon, 1 Jun 2026 13:11:48 +0200 Subject: [PATCH 8/9] Fix issue with initializing pwms before this fix: /* bug!! */ pwm.configure(x,y); pwm.turn_on(); // deletes config on first call /* no bug. */ // pwm.initalize(); // deletes config on first call (called by pwm.turn_on() internally) pwm.turn_on(); pwm.configure(x,y); --- Inc/HALAL/Models/TimerDomain/TimerDomain.hpp | 20 ++++++ Inc/HALAL/Services/PWM/DualPWM.hpp | 65 +++++++++++++++++++- Inc/HALAL/Services/PWM/PWM.hpp | 36 ++++++++++- Inc/HALAL/Services/Time/Scheduler.hpp | 2 +- Inc/HALAL/Services/Time/TimerWrapper.hpp | 15 +---- Src/HALAL/Services/Time/Scheduler.cpp | 2 +- 6 files changed, 119 insertions(+), 21 deletions(-) diff --git a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp index 680bf82bf..c22a05a4d 100644 --- a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp +++ b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp @@ -209,6 +209,26 @@ struct TimerPin { ST_LIB::TimerChannel channel; }; +struct TimerOutputChannelConfig { + uint32_t OCMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint32_t OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for timer instances supporting break feature. */ + + uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for timer instances supporting break feature. */ + + uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for timer instances supporting break feature. */ +}; + #ifndef DEFAULT_PWM_FREQUENCY_MODE #define DEFAULT_PWM_FREQUENCY_MODE ST_LIB::PWM_Frequency_Mode::PRECISION #endif diff --git a/Inc/HALAL/Services/PWM/DualPWM.hpp b/Inc/HALAL/Services/PWM/DualPWM.hpp index 09de02378..a375f8875 100644 --- a/Inc/HALAL/Services/PWM/DualPWM.hpp +++ b/Inc/HALAL/Services/PWM/DualPWM.hpp @@ -49,14 +49,12 @@ class DualPWM { PANIC("Timer instance is not set for DualPWM"); return; } - TIM_OC_InitTypeDef sConfigOC = { + ST_LIB::TimerOutputChannelConfig sConfigOC = { .OCMode = TIM_OCMODE_PWM1, - .Pulse = 0, .OCPolarity = polarity, .OCNPolarity = negated_polarity, - .OCFastMode = TIM_OCFAST_DISABLE, .OCIdleState = TIM_OCIDLESTATE_RESET, .OCNIdleState = TIM_OCNIDLESTATE_RESET, }; @@ -274,6 +272,67 @@ class DualPWM { SET_BIT(timer->instance->tim->BDTR, TIM_BDTR_MOE); } } + + /* NOTE: fast mode is only supported in pwms */ + inline void enable_fast_mode() { + if constexpr (pin.channel == TimerChannel::CHANNEL_1 || pin.channel == TimerChannel::CHANNEL_1_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC1FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_2 || pin.channel == TimerChannel::CHANNEL_2_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC2FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_3 || pin.channel == TimerChannel::CHANNEL_3_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC3FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_4 || pin.channel == TimerChannel::CHANNEL_4_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC4FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_5) { + SET_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC5FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_6) { + SET_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC6FE); + } + + if constexpr (negated_pin.channel == TimerChannel::CHANNEL_1 || negated_pin.channel == TimerChannel::CHANNEL_1_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC1FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_2 || negated_pin.channel == TimerChannel::CHANNEL_2_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC2FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_3 || negated_pin.channel == TimerChannel::CHANNEL_3_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC3FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_4 || negated_pin.channel == TimerChannel::CHANNEL_4_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC4FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_5) { + SET_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC5FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_6) { + SET_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC6FE); + } + } + + inline void disable_fast_mode() { + if constexpr (pin.channel == TimerChannel::CHANNEL_1 || pin.channel == TimerChannel::CHANNEL_1_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC1FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_2 || pin.channel == TimerChannel::CHANNEL_2_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC2FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_3 || pin.channel == TimerChannel::CHANNEL_3_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC3FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_4 || pin.channel == TimerChannel::CHANNEL_4_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC4FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_5) { + CLEAR_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC5FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_6) { + CLEAR_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC6FE); + } + + if constexpr (negated_pin.channel == TimerChannel::CHANNEL_1 || negated_pin.channel == TimerChannel::CHANNEL_1_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC1FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_2 || negated_pin.channel == TimerChannel::CHANNEL_2_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC2FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_3 || negated_pin.channel == TimerChannel::CHANNEL_3_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC3FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_4 || negated_pin.channel == TimerChannel::CHANNEL_4_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC4FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_5) { + CLEAR_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC5FE); + } else if constexpr (negated_pin.channel == TimerChannel::CHANNEL_6) { + CLEAR_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC6FE); + } + } }; } // namespace ST_LIB diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp index 79e6b7fd7..13cd6af26 100644 --- a/Inc/HALAL/Services/PWM/PWM.hpp +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -40,9 +40,8 @@ template class PWM { PANIC("Timer instance is not set for PWM"); return; } - TIM_OC_InitTypeDef sConfigOC = { + ST_LIB::TimerOutputChannelConfig sConfigOC = { .OCMode = TIM_OCMODE_PWM1, - .Pulse = 0, .OCPolarity = polarity, .OCNPolarity = negated_polarity, @@ -153,6 +152,39 @@ template class PWM { inline uint32_t get_frequency() const { return *(this->frequency); } inline float get_duty_cycle() const { return *(this->duty_cycle); } + + /* NOTE: fast mode is only supported in pwms */ + inline void enable_fast_mode() { + if constexpr (pin.channel == TimerChannel::CHANNEL_1 || pin.channel == TimerChannel::CHANNEL_1_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC1FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_2 || pin.channel == TimerChannel::CHANNEL_2_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC2FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_3 || pin.channel == TimerChannel::CHANNEL_3_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC3FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_4 || pin.channel == TimerChannel::CHANNEL_4_NEGATED) { + SET_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC4FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_5) { + SET_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC5FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_6) { + SET_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC6FE); + } + } + + inline void disable_fast_mode() { + if constexpr (pin.channel == TimerChannel::CHANNEL_1 || pin.channel == TimerChannel::CHANNEL_1_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC1FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_2 || pin.channel == TimerChannel::CHANNEL_2_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR1, TIM_CCMR1_OC2FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_3 || pin.channel == TimerChannel::CHANNEL_3_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC3FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_4 || pin.channel == TimerChannel::CHANNEL_4_NEGATED) { + CLEAR_BIT(this->timer->instance->tim->CCMR2, TIM_CCMR2_OC4FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_5) { + CLEAR_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC5FE); + } else if constexpr (pin.channel == TimerChannel::CHANNEL_6) { + CLEAR_BIT(this->timer->instance->tim->CCMR3, TIM_CCMR3_OC6FE); + } + } }; } // namespace ST_LIB diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index b4c97afea..af5fd6016 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -28,7 +28,7 @@ #endif #ifndef SIM_ON -#define SCHEDULER_GET_LAST_N_TASKS +//#define SCHEDULER_GET_LAST_N_TASKS #else struct UART { struct Peripheral { diff --git a/Inc/HALAL/Services/Time/TimerWrapper.hpp b/Inc/HALAL/Services/Time/TimerWrapper.hpp index 051849bb4..e3879718d 100644 --- a/Inc/HALAL/Services/Time/TimerWrapper.hpp +++ b/Inc/HALAL/Services/Time/TimerWrapper.hpp @@ -564,7 +564,7 @@ template struct TimerWrapper { /* NOTE(vic): Both config_output_compare_channel and config_input_compare_channel * Could probably be done better if not using TIM_[OC/IC]_InitTypeDef structures */ template - inline void config_output_compare_channel(const TIM_OC_InitTypeDef* OC_Config) { + inline void config_output_compare_channel(const ST_LIB::TimerOutputChannelConfig* OC_Config) { if constexpr (!((ch == TimerChannel::CHANNEL_1) || (ch == TimerChannel::CHANNEL_2) || (ch == TimerChannel::CHANNEL_3) || (ch == TimerChannel::CHANNEL_4) || (ch == TimerChannel::CHANNEL_5) || (ch == TimerChannel::CHANNEL_6))) { @@ -700,19 +700,6 @@ template struct TimerWrapper { instance->tim->CCMR3 = tmpccmrx; } - if constexpr (ch == TimerChannel::CHANNEL_1) - instance->tim->CCR1 = OC_Config->Pulse; - else if constexpr (ch == TimerChannel::CHANNEL_2) - instance->tim->CCR2 = OC_Config->Pulse; - else if constexpr (ch == TimerChannel::CHANNEL_3) - instance->tim->CCR3 = OC_Config->Pulse; - else if constexpr (ch == TimerChannel::CHANNEL_4) - instance->tim->CCR4 = OC_Config->Pulse; - else if constexpr (ch == TimerChannel::CHANNEL_5) - instance->tim->CCR5 = OC_Config->Pulse; - else if constexpr (ch == TimerChannel::CHANNEL_6) - instance->tim->CCR6 = OC_Config->Pulse; - instance->tim->CCER = tmpccer; } diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 67f9b6db7..62700dc11 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -156,7 +156,7 @@ void Scheduler::update() { } #if defined(SCHEDULER_GET_LAST_N_TASKS) - if (UART::transmit_polling( + if (!UART::transmit_polling( uart_id, (uint8_t*)&time_info, sizeof(TaskTimeInfo) * current_time_info From cd2ebbddeb982472f6878f6e7cb1f527a93c2e51 Mon Sep 17 00:00:00 2001 From: victhor Date: Mon, 1 Jun 2026 16:07:33 +0200 Subject: [PATCH 9/9] remove ocfastmode from init in pwm.hpp --- Inc/HALAL/Services/PWM/PWM.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp index 13cd6af26..037012251 100644 --- a/Inc/HALAL/Services/PWM/PWM.hpp +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -46,7 +46,6 @@ template class PWM { .OCPolarity = polarity, .OCNPolarity = negated_polarity, - .OCFastMode = TIM_OCFAST_DISABLE, .OCIdleState = TIM_OCIDLESTATE_RESET, .OCNIdleState = TIM_OCNIDLESTATE_RESET, };