Improve task's time management

Linking the systick and RTC could cause ticks to be lost on some occasions when
the RTC and systick become desync. We don't care about having them synced but
we care about their individual accuracy. Switching to independant timestamps,
using the tasks ones, fixes that and saves space
This commit is contained in:
Steins7 2024-11-03 22:46:06 +01:00
parent b032890a2c
commit 021180a22f
2 changed files with 23 additions and 30 deletions

View File

@ -47,8 +47,6 @@ static struct Task task_list[MAX_TASK_NB];
static uint8_t task_nb; static uint8_t task_nb;
static volatile bool stk_irq; static volatile bool stk_irq;
static volatile bool rtc_irq; static volatile bool rtc_irq;
static volatile uint32_t timestamp;
//--public functions------------------------------------------------------------ //--public functions------------------------------------------------------------
@ -58,9 +56,15 @@ void task_start_scheduler(void)
rcc_configure_lsi(true); rcc_configure_lsi(true);
pwr_configure_bkp_write(true); pwr_configure_bkp_write(true);
bkp_configure_rtc(1000, BKP_RTC_CLOCK_SRC_LSI, BKP_RTC_IRQ_NONE, nullptr); //may need to be looked into later: basically, the RTC only wakes up the
//system 1 tick too late when using pwr_stop(). To fix that, we can use a
//tick divided by 2, but I have no idea what the underlying problem is
bkp_configure_rtc(500, BKP_RTC_CLOCK_SRC_LSI, BKP_RTC_IRQ_NONE, nullptr);
pwr_configure_bkp_write(false); pwr_configure_bkp_write(false);
exti_configure(EXTI_LINE_RTC, EXTI_CONFIG_RISING_EDGE, callback_rtc); exti_configure(EXTI_LINE_RTC, EXTI_CONFIG_RISING_EDGE, callback_rtc);
pwr_configure_bkp_write(true);
bkp_set_rtc_alam(1);
pwr_configure_bkp_write(false);
while (true) { while (true) {
uint8_t triggers = stk_irq << 0 | rtc_irq << 1; uint8_t triggers = stk_irq << 0 | rtc_irq << 1;
@ -76,20 +80,13 @@ void task_start_scheduler(void)
stk_start(); stk_start();
pwr_sleep(); pwr_sleep();
} else { } else {
pwr_configure_bkp_write(true);
bkp_set_rtc_alam(1);
pwr_configure_bkp_write(false);
stk_stop(); stk_stop();
pwr_sleep(); //pwr_sleep();
pwr_stop(PWR_WAKEUP_SPEED_SLOW);
} }
} }
} }
uint32_t task_current_time(void)
{
return timestamp;
}
void task_start(TaskFunction function) void task_start(TaskFunction function)
{ {
for (uint8_t i = 0; i < MAX_TASK_NB; ++i) { for (uint8_t i = 0; i < MAX_TASK_NB; ++i) {
@ -112,7 +109,7 @@ void task_stop(TaskFunction function)
for (uint8_t i = 0; i < task_nb; ++i) { for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function == function) { if (task_list[i].function == function) {
task_list[i].state.count = _TASK_COUNT_CLEANUP & 0x1F; task_list[i].state.count = _TASK_COUNT_CLEANUP & 0x1F;
task_list[i].function(&task_list[i].state, timestamp); task_list[i].function(&task_list[i].state);
task_list[i].function = nullptr; task_list[i].function = nullptr;
return; return;
@ -139,18 +136,14 @@ static bool execute_task(struct Task* restrict task, uint8_t triggers)
{ {
if (task->function != nullptr) { if (task->function != nullptr) {
if (task->state.trigger == TASK_TRIGGER_ANY) { if (task->state.trigger == TASK_TRIGGER_ANY) {
task->function(&task->state, timestamp); task->function(&task->state);
} else { } else {
if ((task->state.trigger & triggers) != 0) { if ((task->state.trigger & triggers) != 0) {
if (task->state.timestamp <= timestamp) { --task->state.timestamp;
task->state.timestamp = 0;
}
if ((task->state.timestamp == 0) || if ((task->state.timestamp == 0) ||
task->state.timeout_mode) { task->state.timeout_mode) {
task->function(&task->state, task->function(&task->state);
timestamp);
} }
} }
} }
@ -164,11 +157,12 @@ static bool execute_task(struct Task* restrict task, uint8_t triggers)
static void callback_stk(void) static void callback_stk(void)
{ {
stk_irq = true; stk_irq = true;
++timestamp;
} }
static void callback_rtc(void) static void callback_rtc(void)
{ {
rtc_irq = true; rtc_irq = true;
timestamp = bkp_read_rtc() * 1000; pwr_configure_bkp_write(true);
bkp_set_rtc_alam(1);
pwr_configure_bkp_write(false);
} }

View File

@ -56,7 +56,7 @@ struct TaskState {
/** /**
* Function prototype of tasks * Function prototype of tasks
*/ */
typedef void(*TaskFunction)(struct TaskState*, uint32_t); typedef void(*TaskFunction)(struct TaskState*);
/** /**
* Full definition of a task. Contains the function supporting the task as well * Full definition of a task. Contains the function supporting the task as well
@ -74,8 +74,7 @@ struct Task {
* Task declaration macro, to be used to declare and define a task instead of a * Task declaration macro, to be used to declare and define a task instead of a
* regular function declaration/defintion * regular function declaration/defintion
*/ */
#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state, \ #define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state)
uint32_t __task_time)
/** /**
* Task entry macro, must be present at the begin of every task. Setup code to * Task entry macro, must be present at the begin of every task. Setup code to
@ -84,7 +83,6 @@ struct Task {
*/ */
#define TASK_ENTRY \ #define TASK_ENTRY \
_TASK_COUNT_INIT; \ _TASK_COUNT_INIT; \
(void) __task_time; \
switch (__task_state->count) { switch (__task_state->count) {
/** /**
@ -217,7 +215,7 @@ bool task_is_running(TaskFunction task);
#define _TASK_PAUSE(delay_ms, count_val) do { \ #define _TASK_PAUSE(delay_ms, count_val) do { \
__task_state->count = count_val; \ __task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_ms; \ __task_state->timestamp += delay_ms; \
__task_state->trigger = TASK_TRIGGER_STK; \ __task_state->trigger = TASK_TRIGGER_STK; \
return; \ return; \
case (count_val): \ case (count_val): \
@ -226,7 +224,7 @@ bool task_is_running(TaskFunction task);
#define _TASK_SLEEP(delay_s, count_val) do { \ #define _TASK_SLEEP(delay_s, count_val) do { \
__task_state->count = count_val; \ __task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_s * 1000; \ __task_state->timestamp += delay_s; \
__task_state->trigger = TASK_TRIGGER_RTC; \ __task_state->trigger = TASK_TRIGGER_RTC; \
return; \ return; \
case (count_val): \ case (count_val): \
@ -245,7 +243,7 @@ bool task_is_running(TaskFunction task);
#define _TASK_PAUSE_UNTIL(cond, delay_ms, count_val) do { \ #define _TASK_PAUSE_UNTIL(cond, delay_ms, count_val) do { \
__task_state->count = count_val; \ __task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_ms; \ __task_state->timestamp += delay_ms; \
__task_state->trigger = TASK_TRIGGER_STK; \ __task_state->trigger = TASK_TRIGGER_STK; \
__task_state->timeout_mode = true; \ __task_state->timeout_mode = true; \
case (count_val): \ case (count_val): \
@ -253,13 +251,14 @@ bool task_is_running(TaskFunction task);
return; \ return; \
} else { \ } else { \
__task_state->timeout_mode = false; \ __task_state->timeout_mode = false; \
__task_state->timestamp = 0; \
} \ } \
/* fall through */ \ /* fall through */ \
} while (0) } while (0)
#define _TASK_SLEEP_UNTIL(cond, delay_s, count_val) do { \ #define _TASK_SLEEP_UNTIL(cond, delay_s, count_val) do { \
__task_state->count = count_val; \ __task_state->count = count_val; \
__task_state->timestamp = __taks_time + delay_s * 1000; \ __task_state->timestamp += delay_s; \
__task_state->trigger = TASK_TRIGGER_RTC; \ __task_state->trigger = TASK_TRIGGER_RTC; \
__task_state->timeout_mode = true; \ __task_state->timeout_mode = true; \
case (count_val): \ case (count_val): \