@@ -30,7 +30,7 @@ constexpr uint64_t kMaxIntervalUs =
3030
3131std::array<Scheduler::Task, Scheduler::kMaxTasks > Scheduler::tasks_{};
3232uint64_t Scheduler::sorted_task_ids_ = 0 ;
33- std:: size_t Scheduler::active_task_count_{0 };
33+ uint32_t Scheduler::active_task_count_{0 };
3434
3535uint32_t Scheduler::ready_bitmap_{0 };
3636uint32_t Scheduler::free_bitmap_{0xFFFF'FFFF };
@@ -70,10 +70,54 @@ inline void Scheduler::global_timer_enable() {
7070
7171// ----------------------------
7272void 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
182227void 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
215260void Scheduler::schedule_next_interval () {
0 commit comments