Compare commits

..

7 Commits

Author SHA1 Message Date
b893a0283f Reduce task's context size
Since RTC ans STK timestamps are now different, they don't need to be as big and
be can safely reduce their size to 24 bits to save space
2024-11-03 22:53:19 +01:00
8540e2e21f Cleanup forgotten debug line 2024-11-03 22:50:13 +01:00
021180a22f 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
2024-11-03 22:49:51 +01:00
b032890a2c Update debug baurate to work with default clock 2024-11-03 22:36:20 +01:00
c4358a7c28 Cosmetic fix in RCC 2024-11-03 22:28:53 +01:00
99f3bb79c3 Fix rcc_configure failing silently
The function being so important, any failure should be fatal
2024-11-03 22:28:00 +01:00
4df0ba5c6a Fix RCC's speed preset not working in release
Since rcc_configure should always be called before anything else, short timing
depends on hard coded loops. These are too fast in release...
2024-11-03 22:23:26 +01:00
4 changed files with 38 additions and 43 deletions

View File

@ -161,26 +161,27 @@ static void apply_speed_preset(void)
//restore sane values
apply_default_preset();
//try enabling HSE, fallback to HSI if HSE fails
//enable HSE
regs->CR.HSEON = 1;
for (uint32_t i=0; i<1000; ++i) {
__asm__("nop");
for (uint32_t i=0; i<10000; ++i) {
__asm("nop");
}
if (regs->CR.HSERDY == 0x1) {
regs->CFGR.PLLSCR = 1;
} else {
regs->CR.HSEON = 0;
apply_default_preset();
while (true);
}
//configure PLL, fallback to HSI if PLL fails
//configure PLL
regs->CFGR.PLLMUL = 0x7; //PLL x9
regs->CR.PLLON = 1;
for (uint32_t i=0; i<1000; ++i) {
__asm__("nop");
for (uint32_t i=0; i<10000; ++i) {
__asm("nop");
}
if (regs->CR.PLLRDY != 0x1) {
regs->CR.PLLON = 0;
return; //clock low enough, no need for prescalers
apply_default_preset();
while (true);
}
//configure prescalers

View File

@ -18,6 +18,7 @@
static uint32_t write_debug(uint8_t c, void* arg);
#define DEBUG_BAUDRATE 115200
#define BUFFER_SIZE 162 //(80 char line + \n) * 2
@ -34,7 +35,7 @@ void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port,
{
gpio_configure(tx_port, tx_pin, GPIO_MODE_OUTPUT_FAST,
GPIO_CONFIG_OUT_ALT_PUSH_PULL);
usart_configure(usart, USART_CONFIG_8N1, 1000000);
usart_configure(usart, USART_CONFIG_8N1, DEBUG_BAUDRATE);
dma_mbuf_configure(&mbuf,usart_configure_tx_dma(usart),
DMA_CONFIG_PRIO_LOW, tx_buffer, BUFFER_SIZE);

View File

@ -47,8 +47,6 @@ static struct Task task_list[MAX_TASK_NB];
static uint8_t task_nb;
static volatile bool stk_irq;
static volatile bool rtc_irq;
static volatile uint32_t timestamp;
//--public functions------------------------------------------------------------
@ -58,9 +56,15 @@ void task_start_scheduler(void)
rcc_configure_lsi(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);
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) {
uint8_t triggers = stk_irq << 0 | rtc_irq << 1;
@ -76,20 +80,12 @@ void task_start_scheduler(void)
stk_start();
pwr_sleep();
} else {
pwr_configure_bkp_write(true);
bkp_set_rtc_alam(1);
pwr_configure_bkp_write(false);
stk_stop();
pwr_sleep();
pwr_stop(PWR_WAKEUP_SPEED_SLOW);
}
}
}
uint32_t task_current_time(void)
{
return timestamp;
}
void task_start(TaskFunction function)
{
for (uint8_t i = 0; i < MAX_TASK_NB; ++i) {
@ -112,7 +108,7 @@ void task_stop(TaskFunction function)
for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function == function) {
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;
return;
@ -139,18 +135,14 @@ static bool execute_task(struct Task* restrict task, uint8_t triggers)
{
if (task->function != nullptr) {
if (task->state.trigger == TASK_TRIGGER_ANY) {
task->function(&task->state, timestamp);
task->function(&task->state);
} else {
if ((task->state.trigger & triggers) != 0) {
if (task->state.timestamp <= timestamp) {
task->state.timestamp = 0;
}
--task->state.timestamp;
if ((task->state.timestamp == 0) ||
task->state.timeout_mode) {
task->function(&task->state,
timestamp);
task->function(&task->state);
}
}
}
@ -164,11 +156,13 @@ static bool execute_task(struct Task* restrict task, uint8_t triggers)
static void callback_stk(void)
{
stk_irq = true;
++timestamp;
}
static void callback_rtc(void)
{
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

@ -47,16 +47,16 @@ enum TaskTrigger {
* struct
*/
struct TaskState {
uint32_t timestamp; //timestamp at wich to wakeup the task, if any
uint8_t count:5; //task counter: active step of task
uint32_t timestamp:24; //timestamp at wich to wakeup the task, if any
uint32_t count:5; //task counter: active step of task
enum TaskTrigger trigger:2; //triggers on wich to execute the task
uint8_t timeout_mode:1; //whether the timestamp is a timeout or a delay
uint32_t timeout_mode:1; //whether the timestamp is a timeout or a delay
};
/**
* 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
@ -74,8 +74,7 @@ struct Task {
* Task declaration macro, to be used to declare and define a task instead of a
* regular function declaration/defintion
*/
#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state, \
uint32_t __task_time)
#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state)
/**
* Task entry macro, must be present at the begin of every task. Setup code to
@ -84,7 +83,6 @@ struct Task {
*/
#define TASK_ENTRY \
_TASK_COUNT_INIT; \
(void) __task_time; \
switch (__task_state->count) {
/**
@ -217,7 +215,7 @@ bool task_is_running(TaskFunction task);
#define _TASK_PAUSE(delay_ms, count_val) do { \
__task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_ms; \
__task_state->timestamp += delay_ms; \
__task_state->trigger = TASK_TRIGGER_STK; \
return; \
case (count_val): \
@ -226,7 +224,7 @@ bool task_is_running(TaskFunction task);
#define _TASK_SLEEP(delay_s, count_val) do { \
__task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_s * 1000; \
__task_state->timestamp += delay_s; \
__task_state->trigger = TASK_TRIGGER_RTC; \
return; \
case (count_val): \
@ -245,7 +243,7 @@ bool task_is_running(TaskFunction task);
#define _TASK_PAUSE_UNTIL(cond, delay_ms, count_val) do { \
__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->timeout_mode = true; \
case (count_val): \
@ -253,13 +251,14 @@ bool task_is_running(TaskFunction task);
return; \
} else { \
__task_state->timeout_mode = false; \
__task_state->timestamp = 0; \
} \
/* fall through */ \
} while (0)
#define _TASK_SLEEP_UNTIL(cond, delay_s, count_val) do { \
__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->timeout_mode = true; \
case (count_val): \