Skip to content

Commit 1ac4c8c

Browse files
fix: Calculate correct prescaler & add to HALAL.hpp
1 parent 6cfd3f3 commit 1ac4c8c

3 files changed

Lines changed: 63 additions & 16 deletions

File tree

Inc/HALAL/HALAL.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "HALAL/Services/PWM/DualPhasedPWM/DualPhasedPWM.hpp"
1919

2020
#include "HALAL/Services/Time/Time.hpp"
21+
#include "HALAL/Services/Time/Scheduler.hpp"
2122
#include "HALAL/Services/Time/RTC.hpp"
2223

2324
#include "HALAL/Services/InputCapture/InputCapture.hpp"

Inc/HALAL/Services/Time/Scheduler.hpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@
2222
# define SCHEDULER_TIMER_IDX 2
2323
#endif
2424

25-
#define glue_(a,b) a ## b
26-
#define glue(a,b) glue_(a,b)
27-
#define SCHEDULER_TIMER_BASE glue(TIM, glue(SCHEDULER_TIMER_IDX, _BASE))
25+
#define glue_(a,b) a ## b
26+
#define glue(a,b) glue_(a,b)
27+
#define SCHEDULER_TIMER_BASE glue(TIM, glue(SCHEDULER_TIMER_IDX, _BASE))
2828

2929
// Used to reserve a TimerPeripheral
3030
#ifndef TESTING_ENV
31-
#include "stm32h7xx_hal_tim.h"
32-
#define SCHEDULER_HAL_TIM glue(htim, SCHEDULER_TIMER_IDX)
33-
extern TIM_HandleTypeDef SCHEDULER_HAL_TIM;
31+
#include "stm32h7xx_hal_tim.h"
32+
#define SCHEDULER_HAL_TIM glue(htim, SCHEDULER_TIMER_IDX)
33+
extern TIM_HandleTypeDef SCHEDULER_HAL_TIM;
3434
#endif
35+
3536
struct Scheduler {
3637
using callback_t = void (*)();
3738
static constexpr uint32_t INVALID_ID = 0xFFu;
@@ -79,14 +80,14 @@ struct Scheduler {
7980

8081
static constexpr std::size_t kMaxTasks = 16;
8182
static_assert((kMaxTasks & (kMaxTasks - 1)) == 0, "kMaxTasks must be a power of two");
82-
static constexpr uint32_t kBaseClockHz = 1'000'000u;
83+
static constexpr uint32_t FREQUENCY = 1'000'000u; // 1 MHz -> 1us precision
8384

8485
static std::array<Task, kMaxTasks> tasks_;
8586
static_assert(kMaxTasks == 16, "kMaxTasks must be 16, if more is needed, sorted_task_ids_ must change");
8687
/* sorted_task_ids_ is a sorted queue with 4bits for each id in the scheduler's current ids */
8788
static uint64_t sorted_task_ids_;
8889

89-
static std::size_t active_task_count_;
90+
static uint32_t active_task_count_;
9091
static_assert(kMaxTasks <= 32, "kMaxTasks must be <= 32, if more is needed, the bitmaps must change");
9192
static uint32_t ready_bitmap_;
9293
static uint32_t free_bitmap_;

Src/HALAL/Services/Time/Scheduler.cpp

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ constexpr uint64_t kMaxIntervalUs =
3030

3131
std::array<Scheduler::Task, Scheduler::kMaxTasks> Scheduler::tasks_{};
3232
uint64_t Scheduler::sorted_task_ids_ = 0;
33-
std::size_t Scheduler::active_task_count_{0};
33+
uint32_t Scheduler::active_task_count_{0};
3434

3535
uint32_t Scheduler::ready_bitmap_{0};
3636
uint32_t Scheduler::free_bitmap_{0xFFFF'FFFF};
@@ -70,10 +70,54 @@ inline void Scheduler::global_timer_enable() {
7070

7171
// ----------------------------
7272
void Scheduler::start() {
73-
static_assert(kBaseClockHz % 1'000'000u == 0u, "Base clock must be a multiple of 1MHz");
73+
static_assert((Scheduler::FREQUENCY % 1'000'000) == 0u, "frequenct must be a multiple of 1MHz");
74+
75+
76+
uint32_t prescaler = (SystemCoreClock / Scheduler::FREQUENCY);
77+
// setup prescaler
78+
{
79+
// ref manual: section 8.7.7 RCC domain 1 clock configuration register
80+
uint32_t ahb_prescaler = RCC->D1CFGR & RCC_D1CFGR_HPRE_Msk;
81+
if((ahb_prescaler & 0b1000) != 0) {
82+
switch(ahb_prescaler) {
83+
case 0b1000: prescaler /= 2; break;
84+
case 0b1001: prescaler /= 4; break;
85+
case 0b1010: prescaler /= 8; break;
86+
case 0b1011: prescaler /= 16; break;
87+
case 0b1100: prescaler /= 64; break;
88+
case 0b1101: prescaler /= 128; break;
89+
case 0b1110: prescaler /= 256; break;
90+
case 0b1111: prescaler /= 512; break;
91+
}
92+
}
93+
94+
// ref manual: section 8.7.8: RCC domain 2 clock configuration register
95+
uint32_t apb1_prescaler = (RCC->D2CFGR & RCC_D2CFGR_D2PPRE1_Msk) >> RCC_D2CFGR_D2PPRE1_Pos;
96+
if((apb1_prescaler & 0b100) != 0) {
97+
switch(apb1_prescaler) {
98+
case 0b100: prescaler /= 2; break;
99+
case 0b101: prescaler /= 4; break;
100+
case 0b110: prescaler /= 8; break;
101+
case 0b111: prescaler /= 16; break;
102+
}
103+
}
104+
// tim2clk = 2 x pclk1 when apb1_prescaler != 1
105+
if(apb1_prescaler != 1) {
106+
prescaler *= 2;
107+
}
108+
109+
if(prescaler > 1) {
110+
prescaler--;
111+
}
112+
}
74113

75-
const uint32_t prescaler = (kBaseClockHz / 1'000'000u) - 1u;
76-
static_assert(prescaler < 0xFFFF'FFFF, "Prescaler is 16 bit, so it must be in that range");
114+
// TODO: Fault when any of the next 2 static asserts happen (needs to be runtime bcos of SystemCoreClock)
115+
if(prescaler == 0 || prescaler > 0xFFFF) {
116+
// error here
117+
}
118+
119+
//static_assert(prescaler < 0xFFFF, "Prescaler is 16 bit, so it must be in that range");
120+
//static_assert(prescaler != 0, "Prescaler must be in the range [1, 65535]");
77121
#ifndef TESTING_ENV
78122

79123
// Register a TimerPeripheral so it's not used anywhere else
@@ -140,7 +184,7 @@ void Scheduler::insert_sorted(uint8_t id) {
140184

141185
// binary search on logical range [0, active_task_count_)
142186
std::size_t left = 0;
143-
std::size_t right = active_task_count_;
187+
std::size_t right = Scheduler::active_task_count_;
144188
while (left < right) {
145189
std::size_t mid = left + ((right - left) / 2);
146190
const Task& mid_task = tasks_[Scheduler::get_at(mid)];
@@ -155,6 +199,7 @@ void Scheduler::insert_sorted(uint8_t id) {
155199
uint32_t lo = (uint32_t)sorted_task_ids_;
156200
uint32_t hi = (uint32_t)(sorted_task_ids_ >> 32);
157201

202+
// take the shift for only high or low 32 bits
158203
uint32_t shift = (pos & 7) << 2;
159204
uint32_t id_shifted = id << shift;
160205

@@ -167,7 +212,7 @@ void Scheduler::insert_sorted(uint8_t id) {
167212

168213
uint32_t hi_spilled = (hi << 4) | (lo >> 28);
169214

170-
if (pos >= 8) { //this can be done without branching
215+
if (pos >= 8) {
171216
hi = hi_modified;
172217
// lo remains unchanged
173218
} else {
@@ -176,7 +221,7 @@ void Scheduler::insert_sorted(uint8_t id) {
176221
}
177222

178223
sorted_task_ids_ = ((uint64_t)hi << 32) | lo;
179-
active_task_count_++;
224+
Scheduler::active_task_count_++;
180225
}
181226

182227
void Scheduler::remove_sorted(uint8_t id) {
@@ -209,7 +254,7 @@ void Scheduler::remove_sorted(uint8_t id) {
209254

210255
// Remove element (lower part | higher pushing nibble out of mask)
211256
Scheduler::sorted_task_ids_ = (Scheduler::sorted_task_ids_ & mask) | ((Scheduler::sorted_task_ids_ >> 4) & ~mask);
212-
active_task_count_--;
257+
Scheduler::active_task_count_--;
213258
}
214259

215260
void Scheduler::schedule_next_interval() {

0 commit comments

Comments
 (0)