avr-task-scheduler

AVR mcu bare metal task scheduler
Index Commits Files Refs README LICENSE
commit 6577d577eacaba4024c2d7bd22ffe6ba93c4e5c9
parent e0a61704166c37442f280fec061d436f9889da40
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Sun, 28 Sep 2025 00:37:53 -0300

do not execute functions on `ISR`

Diffstat:
Ainclude/millis.h | 17+++++++++++++++++
Minclude/scheduler.h | 2+-
Dinclude/timer.h | 17-----------------
Msrc/main.c | 16+++++++---------
Asrc/millis.c | 31+++++++++++++++++++++++++++++++
Msrc/scheduler.c | 12++++++++++--
Dsrc/timer.c | 40----------------------------------------
7 files changed, 66 insertions(+), 69 deletions(-)
diff --git a/include/millis.h b/include/millis.h
@@ -0,0 +1,17 @@
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+void millis_init(void);
+uint32_t millis(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _TIMER_H_
diff --git a/include/scheduler.h b/include/scheduler.h
@@ -10,7 +10,7 @@ extern "C" {
 #include <stdint.h>
 
 void scheduler_init(void);
-void scheduler_update(void);
+void scheduler_update(uint32_t t_ms);
 void scheduler_append_task(void (*update_func)(void), uint16_t update_interval);
 
 #ifdef __cplusplus
diff --git a/include/timer.h b/include/timer.h
@@ -1,17 +0,0 @@
-#ifndef _TIMER_H_
-#define _TIMER_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-void timer_init(void);
-void timer_add_callback(void (*func_ptr)(void));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _TIMER_H_
diff --git a/src/main.c b/src/main.c
@@ -1,10 +1,10 @@
 #include <avr/io.h>
 
-#include "timer.h"
+#include "millis.h"
 #include "scheduler.h"
 
-#define LED_1_PIN  3
-#define LED_2_PIN  4
+#define LED_1_PIN 3
+#define LED_2_PIN 4
 
 void toggle_led_1(void) {
     PIND = (1 << LED_1_PIN);
@@ -15,22 +15,20 @@ void toggle_led_2(void) {
 }
 
 void setup(void) {
-    DDRD |= (1 << LED_1_PIN) | (1 << LED_2_PIN);
+    DDRD |= (1<<LED_1_PIN) | (1<<LED_2_PIN);
 
-    scheduler_init();
+    millis_init();
 
+    scheduler_init();
     scheduler_append_task(&toggle_led_1, 1000);
     scheduler_append_task(&toggle_led_2, 500);
-
-    timer_init();
-    timer_add_callback(&scheduler_update);
 }
 
 int main(void) {
     setup();
 
     while(1) {
-        ;;
+        scheduler_update(millis());
     }
 
     return 0;
diff --git a/src/millis.c b/src/millis.c
@@ -0,0 +1,31 @@
+#include "millis.h"
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+static volatile uint32_t ms = 0;
+
+ISR(TIMER0_COMPA_vect) {
+    ms++;
+}
+
+// normal mode, prescaler 64, max value 249: exactly 1 interrupt per ms
+void millis_init(void) {
+    cli();
+    TCCR0A = (1 << WGM01) | (1 << COM0A0);
+    TCCR0B = (1 << CS01) | (1 << CS00);
+    TIMSK0 = (1 << OCIE0A);
+    OCR0A = 250;
+    sei();
+}
+
+uint32_t millis(void) {
+    uint32_t ms_now;
+    uint8_t sreg = SREG;
+
+    cli();
+    ms_now = ms;
+    SREG = sreg;
+
+    return ms_now;
+}
diff --git a/src/scheduler.c b/src/scheduler.c
@@ -11,6 +11,7 @@ typedef struct {
 } task_t;
 
 typedef struct {
+    uint32_t t_ms_dt;
     uint8_t task_cnt;
     task_t tasks[SCHEDULER_MAX_TASKS_CNT];
 } scheduler_t;
@@ -19,10 +20,17 @@ static scheduler_t scheduler = {0};
 
 void scheduler_init(void) {
     scheduler.task_cnt = 0;
+    scheduler.t_ms_dt = 0;
 }
 
-// should be called exactly every ms
-void scheduler_update(void) {
+// update every 1 ms
+void scheduler_update(uint32_t t_ms) {
+    if ((t_ms - scheduler.t_ms_dt) < 1) {
+        return;
+    }
+
+    scheduler.t_ms_dt = t_ms;
+
     for (uint8_t i = 0; i < scheduler.task_cnt; ++i) {
         if (scheduler.tasks[i].ticks > 0) {
             scheduler.tasks[i].ticks--;
diff --git a/src/timer.c b/src/timer.c
@@ -1,40 +0,0 @@
-#include "timer.h"
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-
-#define TIMER_CALLBACKS_MAX_CNT 1
-
-typedef struct {
-    uint8_t callbacks_cnt;
-    void (*callbacks[TIMER_CALLBACKS_MAX_CNT])(void);
-} timer_t;
-
-static timer_t timer = {0};
-
-ISR(TIMER0_COMPA_vect) {
-    for(uint8_t i = 0; i < timer.callbacks_cnt; ++i) {
-        timer.callbacks[i]();
-    }
-}
-
-// normal mode, prescaler 64, max value 250 == exact 1 interrupt per ms
-void timer_init(void) {
-    cli();
-    TCCR0A = (1 << WGM01) | (1 << COM0A0);
-    TCCR0B = (1 << CS01) | (1 << CS00);
-    TIMSK0 = (1 << OCIE0A);
-    OCR0A = 250;
-    sei();
-
-    // timer_add_callback(&timer_increment_millis);
-}
-
-void timer_add_callback(void (*callback)(void)) {
-    if (timer.callbacks_cnt == TIMER_CALLBACKS_MAX_CNT) {
-        return;
-    }
-
-    timer.callbacks[timer.callbacks_cnt] = callback;
-    timer.callbacks_cnt++;
-}