Async tasks + async task demo in main

master
Ondřej Hruška 9 years ago
parent 39d47509ec
commit 6dd9ceb94e
  1. 1
      init.c
  2. 45
      main.c
  3. 63
      utils/timebase.c
  4. 7
      utils/timebase.h

@ -11,6 +11,7 @@ void init_gpios(void)
gpio_enable(GPIOC); gpio_enable(GPIOC);
gpio_set_mode(GPIOC, BIT8 | BIT9 | BIT7, MODER_OUTPUT); gpio_set_mode(GPIOC, BIT8 | BIT9 | BIT7, MODER_OUTPUT);
gpio_set_mode(GPIOA, BIT0, MODER_INPUT);
} }

@ -5,12 +5,36 @@
#include "init.h" #include "init.h"
void blink_green(void)
void blink(void) { {
GPIOC_ODR ^= BIT9; GPIOC_ODR ^= BIT9;
} }
// --- async delayed blue blink ---
bool blue_blink_pending = false;
void blue_off(void)
{
GPIOC_ODR &= ~BIT8;
blue_blink_pending = false;
}
void blink_blue(void)
{
GPIOC_ODR |= BIT8;
register_future_task(blue_off, 200);
}
// called every 1s
void say_hello(void)
{
usart_tx_string(USART3, "HELLO\r\n");
}
/** Called before main() */ /** Called before main() */
void SystemInit(void) void SystemInit(void)
@ -20,16 +44,25 @@ void SystemInit(void)
init_gpios(); init_gpios();
init_usart(); init_usart();
schedule_timed_task(blink, 500); register_periodic_task(blink_green, 500);
register_periodic_task(say_hello, 1000);
} }
int main(void) int main(void)
{ {
int btn_c = 0;
while (1) { while (1) {
delay_ms(1000); bool btn = GPIOA_IDR & BIT0;
GPIOC_ODR ^= BIT8; if (btn) {
if (btn_c++ > 20 && !blue_blink_pending) {
blue_blink_pending = true;
register_future_task(blink_blue, 1000);
}
} else {
btn_c = 0;
}
usart_tx_string(USART3, "HELLO\r\n"); delay_ms(1);
} }
} }

@ -2,28 +2,43 @@
volatile uint32_t TIME_MS; volatile uint32_t TIME_MS;
#define TASK_COUNT 10 #define PERIODIC_TASK_COUNT 5
#define FUTURE_TASK_COUNT 5
// --- time scheduler system --- // --- time scheduler system ---
typedef struct { typedef struct {
/** User callback */ /** User callback */
void (*callback) (void); void (*callback)(void);
/** Callback interval */ /** Callback interval */
uint32_t interval_ms; uint32_t interval_ms;
/** Counter, when reaches interval_ms, is cleared and callback is called. */ /** Counter, when reaches interval_ms, is cleared and callback is called. */
uint32_t countup; uint32_t countup;
} timebase_cb_t; } periodic_task_t;
static uint8_t scheduled_task_n = 0; static uint8_t periodic_task_n = 0;
static timebase_cb_t scheduled_tasks[TASK_COUNT]; static periodic_task_t periodic_tasks[PERIODIC_TASK_COUNT];
bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms) // --- future call system ---
typedef struct {
/** 1 for active tasks */
bool active;
/** User callback */
void (*callback)(void);
/** Counter, when reaches 0ms, callback is called and the task is removed */
uint32_t countdown_ms;
} future_task_t;
static future_task_t future_tasks[FUTURE_TASK_COUNT];
bool register_periodic_task(void (*callback)(void), uint32_t interval_ms)
{ {
if (scheduled_task_n >= TASK_COUNT) return false; if (periodic_task_n >= PERIODIC_TASK_COUNT) return false;
// add the task // add the task
timebase_cb_t *task = &scheduled_tasks[scheduled_task_n++]; periodic_task_t *task = &periodic_tasks[periodic_task_n++];
task->callback = callback; task->callback = callback;
task->countup = 0; task->countup = 0;
task->interval_ms = interval_ms; task->interval_ms = interval_ms;
@ -32,19 +47,47 @@ bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms)
} }
bool register_future_task(void (*callback)(void), uint32_t delay_ms)
{
for (int i = 0; i < FUTURE_TASK_COUNT; i++) {
future_task_t *task = &future_tasks[i];
if (task->active) continue;
task->callback = callback;
task->countdown_ms = delay_ms;
task->active = true;
}
return false;
}
/** IRQ */ /** IRQ */
void SysTick_Handler(void) void SysTick_Handler(void)
{ {
TIME_MS++; TIME_MS++;
// run scheduled tasks // run scheduled tasks
for (int i = 0; i < scheduled_task_n; i++) { for (int i = 0; i < periodic_task_n; i++) {
timebase_cb_t *task = &scheduled_tasks[i]; periodic_task_t *task = &periodic_tasks[i];
if (task->countup++ >= task->interval_ms) { if (task->countup++ >= task->interval_ms) {
task->callback(); task->callback();
task->countup = 0; task->countup = 0;
} }
} }
// run future tasks
for (int i = 0; i < FUTURE_TASK_COUNT; i++) {
future_task_t *task = &future_tasks[i];
if (!task->active) continue;
if (task->countdown_ms-- == 0) {
task->callback();
task->active = 0;
}
}
} }

@ -6,5 +6,8 @@ extern volatile uint32_t TIME_MS;
void delay_ms(uint32_t ms); void delay_ms(uint32_t ms);
void delay_s(uint32_t s); void delay_s(uint32_t s);
/** Schedule a timed task (like a cron job) */ /** Schedule a periodic task (like a cron job). Returns success. */
bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms); bool register_periodic_task(void (*callback) (void), uint32_t interval_ms);
/** Schedule a future one-off task. Returns success. */
bool register_future_task(void (*callback)(void), uint32_t delay_ms);

Loading…
Cancel
Save