Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Inc/HALAL/Services/Time/Scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
37 changes: 37 additions & 0 deletions Src/HALAL/Services/Time/Scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -76,19 +98,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<uint32_t>(__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]] {
Expand Down Expand Up @@ -247,9 +282,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<uint32_t>(global_tick_us_ + task.period_us);
Expand Down
Loading