avr-task-scheduler

AVR mcu bare metal task scheduler
Index Commits Files Refs README LICENSE
commit 26fb95fa5e441e0decf1ac581f3f9130a2ba0f12
parent 7aa4c486b9bf8daa88969e34c6911080b043d538
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Sun, 28 Sep 2025 15:31:28 -0300

tasks ids; add one more task as example

Diffstat:
Msrc/main.c | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/millis.c | 2+-
Msrc/scheduler.c | 23+++++++++++++++++++----
Msrc/scheduler.h | 9++-------
4 files changed, 76 insertions(+), 35 deletions(-)
diff --git a/src/main.c b/src/main.c
@@ -3,40 +3,45 @@
 #include "millis.h"
 #include "scheduler.h"
 
-#define BTN_PIN   2
-#define LED_1_PIN 3
-#define LED_2_PIN 4
-#define LED_3_PIN 5
+#define BTN_A_PIN 2
+#define BTN_B_PIN 3
+#define LED_1_PIN 4
+#define LED_2_PIN 5
+#define LED_3_PIN 6
+#define LED_4_PIN 7
 
-void toggle_led_1(void) {
-    PIND = (1 << LED_1_PIN);
-}
-
-void toggle_led_2(void) {
-    PIND = (1 << LED_2_PIN);
-}
+void toggle_led_1(void);
+void toggle_led_2(void);
+void read_button_a(void);
+void read_button_b(void);
 
-void read_button(void) {
-    if (PIND & (1<<BTN_PIN)) {
-        PORTD &= ~(1<<LED_3_PIN);
-    } else {
-        PORTD |= (1<<LED_3_PIN);
-    }
-}
+typedef enum {
+    TOGGLE_LED_1_ID,
+    TOGGLE_LED_2_ID,
+    READ_BTN_A_ID,
+    READ_BTN_B_ID,
+    TASKS_COUNT
+} task_id_e;
 
 task_t tasks[] = {
-    { toggle_led_1, 1000 },
-    { toggle_led_2, 500 },
-    { read_button,  0 }
+    { toggle_led_1,  1000,  TOGGLE_LED_1_ID },
+    { toggle_led_2,   500,  TOGGLE_LED_2_ID },
+    { read_button_a,    0,    READ_BTN_A_ID },
+    { read_button_b,    0,    READ_BTN_B_ID }
 };
 
 void io_setup(void) {
-    DDRD = (DDRD | (1<<LED_1_PIN) | (1<<LED_2_PIN) | (1<<LED_3_PIN)) & ~(1<<BTN_PIN);
-    PORTD |= (1<<BTN_PIN);
+    // outputs
+    DDRD |= (1<<LED_1_PIN) | (1<<LED_2_PIN) | (1<<LED_3_PIN) | (1<<LED_4_PIN);
+
+    // inputs with internall pullup
+    DDRD &= ~((1<<BTN_A_PIN) | (1<<BTN_B_PIN));
+    PORTD |= (1<<BTN_A_PIN) | (1<<BTN_B_PIN);
 }
 
 int main(void) {
     io_setup();
+
     millis_init();
     scheduler_init(tasks, sizeof(tasks)/sizeof(tasks[0]));
 
@@ -46,3 +51,29 @@ int main(void) {
 
     return 0;
 }
+
+void toggle_led_1(void) {
+    PIND = (1 << LED_1_PIN);
+}
+
+void toggle_led_2(void) {
+    PIND = (1 << LED_2_PIN);
+}
+
+void read_button_a(void) {
+    if (PIND & (1<<BTN_A_PIN)) {
+        PORTD &= ~(1<<LED_4_PIN);
+        scheduler_set_task_period(READ_BTN_A_ID, 0);
+    } else {
+        PORTD |= (1<<LED_4_PIN);
+        scheduler_set_task_period(READ_BTN_A_ID, 150);
+    }
+}
+
+void read_button_b(void) {
+    if (PIND & (1<<BTN_B_PIN)) {
+        PORTD &= ~(1<<LED_3_PIN);
+    } else {
+        PORTD |= (1<<LED_3_PIN);
+    }
+}
diff --git a/src/millis.c b/src/millis.c
@@ -12,7 +12,7 @@ ISR(TIMER0_COMPA_vect) {
 // normal mode, prescaler 64, max value 249: exactly 1 interrupt per ms
 void millis_init(void) {
     cli();
-    TCCR0A = (1 << WGM01) | (1 << COM0A0);
+    TCCR0A = (1 << WGM01);
     TCCR0B = (1 << CS01) | (1 << CS00);
     TIMSK0 = (1 << OCIE0A);
     OCR0A = 249;
diff --git a/src/scheduler.c b/src/scheduler.c
@@ -4,8 +4,19 @@
 extern "C" {
 #endif
 
+typedef struct {
+    uint32_t t_ms_dt;
+    uint8_t task_cnt;
+    task_t *tasks;
+} scheduler_t;
+
 static scheduler_t scheduler = {0};
 
+void scheduler_init(task_t *tasks, uint8_t task_count) {
+    scheduler.tasks = tasks;
+    scheduler.task_cnt = task_count;
+}
+
 // update every 1 ms
 void scheduler_update(uint32_t t_ms) {
     if ((t_ms - scheduler.t_ms_dt) < 1) {
@@ -20,14 +31,18 @@ void scheduler_update(uint32_t t_ms) {
             continue;
         }
 
-        scheduler.tasks[i].ticks = scheduler.tasks[i].update_interval;
+        scheduler.tasks[i].ticks = scheduler.tasks[i].period;
         scheduler.tasks[i].task_update();
     }
 }
 
-void scheduler_init(task_t *tasks, uint8_t task_count) {
-    scheduler.tasks = tasks;
-    scheduler.task_cnt = task_count;
+void scheduler_set_task_period(uint8_t task_id, uint16_t new_period) {
+    for (uint8_t i = 0; i < scheduler.task_cnt; ++i) {
+        if (scheduler.tasks[i].task_id == task_id) {
+            scheduler.tasks[i].period = new_period;
+            scheduler.tasks[i].ticks = new_period;
+        }
+    }
 }
 
 #ifdef __cplusplus
diff --git a/src/scheduler.h b/src/scheduler.h
@@ -9,19 +9,14 @@ extern "C" {
 
 typedef struct {
     void (*task_update)(void);
-    uint16_t update_interval;
+    uint16_t period;
     uint8_t task_id;
     uint16_t ticks;
 } task_t;
 
-typedef struct {
-    uint32_t t_ms_dt;
-    uint8_t task_cnt;
-    task_t *tasks;
-} scheduler_t;
-
 void scheduler_init(task_t *tasks, uint8_t task_count);
 void scheduler_update(uint32_t t_ms);
+void scheduler_set_task_period(uint8_t task_id, uint16_t new_period);
 
 #ifdef __cplusplus
 }