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_set_mode(GPIOC, BIT8 | BIT9 | BIT7, MODER_OUTPUT);
gpio_set_mode(GPIOA, BIT0, MODER_INPUT);
}

@ -5,12 +5,36 @@
#include "init.h"
void blink(void) {
void blink_green(void)
{
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() */
void SystemInit(void)
@ -20,16 +44,25 @@ void SystemInit(void)
init_gpios();
init_usart();
schedule_timed_task(blink, 500);
register_periodic_task(blink_green, 500);
register_periodic_task(say_hello, 1000);
}
int main(void)
{
int btn_c = 0;
while (1) {
delay_ms(1000);
GPIOC_ODR ^= BIT8;
bool btn = GPIOA_IDR & BIT0;
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;
#define TASK_COUNT 10
#define PERIODIC_TASK_COUNT 5
#define FUTURE_TASK_COUNT 5
// --- time scheduler system ---
typedef struct {
/** User callback */
void (*callback) (void);
void (*callback)(void);
/** Callback interval */
uint32_t interval_ms;
/** Counter, when reaches interval_ms, is cleared and callback is called. */
uint32_t countup;
} timebase_cb_t;
} periodic_task_t;
static uint8_t scheduled_task_n = 0;
static timebase_cb_t scheduled_tasks[TASK_COUNT];
static uint8_t periodic_task_n = 0;
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
timebase_cb_t *task = &scheduled_tasks[scheduled_task_n++];
periodic_task_t *task = &periodic_tasks[periodic_task_n++];
task->callback = callback;
task->countup = 0;
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 */
void SysTick_Handler(void)
{
TIME_MS++;
// run scheduled tasks
for (int i = 0; i < scheduled_task_n; i++) {
timebase_cb_t *task = &scheduled_tasks[i];
for (int i = 0; i < periodic_task_n; i++) {
periodic_task_t *task = &periodic_tasks[i];
if (task->countup++ >= task->interval_ms) {
task->callback();
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_s(uint32_t s);
/** Schedule a timed task (like a cron job) */
bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms);
/** Schedule a periodic task (like a cron job). Returns success. */
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