diff --git a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp index 98af03b94..cb4d0eacf 100644 --- a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp +++ b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp @@ -19,6 +19,16 @@ #include "ErrorHandler/ErrorHandler.hpp" +#ifndef SCHEDULER_TIMER_DOMAIN +/* default is tim2 */ +#define SCHEDULER_TIMER_DOMAIN 2 +#elif (SCHEDULER_TIMER_DOMAIN != 2) && (SCHEDULER_TIMER_DOMAIN != 3) && \ + (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)) + // NOTE: only works for static arrays #define ARRAY_LENGTH(a) (sizeof(a) / sizeof(*a)) @@ -531,6 +541,10 @@ TimerXList remaining_requests[i] = i; for (int i = 0; i < (int)requests.size(); i++) { + if (static_cast(requests[i].request) == SCHEDULER_TIMER_DOMAIN) { + ST_LIB::compile_error("This timer is used by the scheduler"); + } + if (requests[i].request != TimerRequest::AnyGeneralPurpose && (requests[i].request < 1 || requests[i].request > 24 || (requests[i].request > 17 && requests[i].request < 23))) { @@ -576,7 +590,7 @@ TimerXList uint8_t count_32bit_requests = 0; for (int i = 0; i < (int)ARRAY_LENGTH(bits32_timers); i++) { - if (!used_timers[bits32_timers[i]]) + if (!used_timers[bits32_timers[i]] && (bits32_timers[i] != SCHEDULER_TIMER_DOMAIN)) remaining_32bit_timers[count_remaining_32bit_timers++] = bits32_timers[i]; } @@ -662,6 +676,8 @@ TimerXList static inline std::array instances{}; static void init(std::span cfgs) { + rcc_enable_timer(cmsis_timers[static_cast(SCHEDULER_TIMER_DOMAIN)]); + for (std::size_t i = 0; i < N; i++) { const Config& e = cfgs[i]; diff --git a/Inc/HALAL/Services/Time/Scheduler.hpp b/Inc/HALAL/Services/Time/Scheduler.hpp index ae7bcdb1c..dbe965891 100644 --- a/Inc/HALAL/Services/Time/Scheduler.hpp +++ b/Inc/HALAL/Services/Time/Scheduler.hpp @@ -15,31 +15,21 @@ #include #include -/* NOTE(vic): Esto cambiará pronto */ -#ifndef SCHEDULER_TIMER_IDX -#define SCHEDULER_TIMER_IDX 2 -#endif - -#ifndef glue -#define glue_(a, b) a##b -#define glue(a, b) glue_(a, b) -#endif -#define SCHEDULER_TIMER_BASE glue(TIM, glue(SCHEDULER_TIMER_IDX, _BASE)) - -// Used to reserve a TimerPeripheral #ifndef SIM_ON #include "stm32h7xx_hal_tim.h" -#define SCHEDULER_HAL_TIM glue(htim, SCHEDULER_TIMER_IDX) -extern TIM_HandleTypeDef SCHEDULER_HAL_TIM; #endif +extern TIM_TypeDef* Scheduler_global_timer; + struct Scheduler { using callback_t = void (*)(); static constexpr uint32_t INVALID_ID = 0xFFu; static void start(); static void update(); - static inline uint64_t get_global_tick() { return global_tick_us_; } + static inline uint64_t get_global_tick() { + return global_tick_us_ + Scheduler_global_timer->CNT; + } 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 9754d10ee..59892a0fa 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -10,11 +10,8 @@ #include -/* NOTE(vic): Pido perdón a Boris pero es la mejor manera que se me ha ocurrido hacer esto */ -#define SCHEDULER_RCC_TIMER_ENABLE glue(glue(RCC_APB1LENR_TIM, SCHEDULER_TIMER_IDX), EN) -#define SCHEDULER_GLOBAL_TIMER_IRQn glue(TIM, glue(SCHEDULER_TIMER_IDX, _IRQn)) +TIM_TypeDef* Scheduler_global_timer = nullptr; -#define Scheduler_global_timer ((TIM_TypeDef*)SCHEDULER_TIMER_BASE) namespace { constexpr uint64_t kMaxIntervalUs = static_cast(UINT32_MAX) / 2 + 1ULL; } @@ -68,6 +65,8 @@ void scheduler_global_timer_callback(void* raw) { void Scheduler::start() { static_assert((Scheduler::FREQUENCY % 1'000'000) == 0u, "frequenct must be a multiple of 1MHz"); + Scheduler_global_timer = + ST_LIB::TimerDomain::cmsis_timers[ST_LIB::timer_idxmap[SCHEDULER_TIMER_DOMAIN]]; uint32_t prescaler = (SystemCoreClock / Scheduler::FREQUENCY); // setup prescaler @@ -133,23 +132,17 @@ void Scheduler::start() { if (prescaler == 0 || prescaler > 0xFFFF) { ErrorHandler("Invalid prescaler value: %u", prescaler); + return; } - // static_assert(prescaler < 0xFFFF, "Prescaler is 16 bit, so it must be in that range"); - // static_assert(prescaler != 0, "Prescaler must be in the range [1, 65535]"); -#ifndef SIM_ON - RCC->APB1LENR |= SCHEDULER_RCC_TIMER_ENABLE; -#endif - Scheduler_global_timer->PSC = (uint16_t)prescaler; Scheduler_global_timer->ARR = 0; Scheduler_global_timer->DIER |= LL_TIM_DIER_UIE; Scheduler_global_timer->CR1 = LL_TIM_CLOCKDIVISION_DIV1 | (Scheduler_global_timer->CR1 & ~TIM_CR1_CKD); - // Temporary solution for TimerDomain - ST_LIB::TimerDomain::callbacks[ST_LIB::timer_idxmap[SCHEDULER_TIMER_IDX]] = - scheduler_global_timer_callback; + ST_LIB::TimerDomain::callbacks[ST_LIB::timer_idxmap[static_cast(SCHEDULER_TIMER_DOMAIN + )]] = scheduler_global_timer_callback; Scheduler_global_timer->CNT = 0; /* Clear counter value */ diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index 600fdba0a..7376abe5b 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -16,6 +16,7 @@ class SchedulerTests : public ::testing::Test { Scheduler::sorted_task_ids_ = 0; Scheduler::global_tick_us_ = 0; Scheduler::current_interval_us_ = 0; + Scheduler_global_timer = TIM2_BASE; // Reset global callback task count count = 0;