-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScheduler.hpp
More file actions
100 lines (83 loc) · 3.05 KB
/
Scheduler.hpp
File metadata and controls
100 lines (83 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* Scheduler.hpp
*
* Created on: 17 nov. 2025
* Author: Victor (coauthor Stephan)
*/
#pragma once
/* Uso del scheduler, descrito en la wiki:
* https://wiki.hyperloopupv.com/es/firmware/Timing/Scheduler */
#include "stm32h7xx_ll_tim_wrapper.h"
#include <array>
#include <cstdint>
#include <functional>
#ifndef SIM_ON
#include "stm32h7xx_hal_tim.h"
#endif
extern TIM_TypeDef* Scheduler_global_timer;
struct Scheduler {
using callback_t = void (*)();
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();
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);
static uint16_t set_timeout(uint32_t microseconds, callback_t func);
static bool cancel_timeout(uint16_t id);
// internal
static void on_timer_update();
#ifndef SIM_ON
private:
#endif
struct Task {
uint32_t next_fire_us{0};
callback_t callback{};
uint32_t period_us{0};
uint16_t id;
bool repeating{false};
};
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");
static constexpr uint32_t FREQUENCY = 1'000'000u; // 1 MHz -> 1us precision
static std::array<Task, kMaxTasks> tasks_;
static_assert(
kMaxTasks == 16,
"kMaxTasks must be 16, if more is needed, sorted_task_ids_ must change"
);
/* sorted_task_ids_ is a sorted queue with 4bits for each id in the
* scheduler's current ids */
static uint64_t sorted_task_ids_;
static uint32_t active_task_count_;
static_assert(
kMaxTasks <= 32,
"kMaxTasks must be <= 32, if more is needed, the bitmaps must change"
);
static uint32_t ready_bitmap_;
static uint32_t free_bitmap_;
static uint64_t global_tick_us_;
static uint32_t current_interval_us_;
static uint16_t timeout_idx_;
static inline uint8_t allocate_slot();
static inline void release_slot(uint8_t id);
static void insert_sorted(uint8_t id);
static void remove_sorted(uint8_t id);
static void schedule_next_interval();
static inline void configure_timer_for_interval(uint32_t microseconds);
// helpers
static inline uint8_t get_at(uint8_t idx);
static inline void set_at(uint8_t idx, uint8_t id);
static inline void pop_front();
static inline uint8_t front_id();
static inline void global_timer_disable();
static inline void global_timer_enable();
};