From 36b0dc7707312ce8a43c63a43e253325747ff81a Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Fri, 7 Jun 2013 18:15:11 +0200 Subject: [PATCH] Timer handling moved to the main thread In order to mitigate the problem with watchdog reset, possibly caused by timer IRQ handling taking too long, we only increment the jiffies value in the WDT IRQ handler, and then read this value in the main loop, compare with the previous one, and if those two are different, we run the timer-induced operations. We can (probably) detect the timer overrun (the difference in jiffies being greater than 1), and log it. The individual timer-induced operations are run in their own atomic blocks for now, in order to be safe. The finer-grained locking is in the TODO list :-). --- firmware/main.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ firmware/tmr.c | 11 +---------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index e6f03b0..b3fcc65 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,6 +8,8 @@ #include "lights.h" +static unsigned char prev_jiffies_8; + static void hw_setup() { init_battery(); @@ -83,11 +86,40 @@ static void inline first_boot() hw_setup(); power_down(mcusr_save & _BV(WDRF)); + prev_jiffies_8 = jiffies; + sei(); } +static void inline do_timer() +{ + // For now, we run them all in their own atomic blocks + ATOMIC_BLOCK(ATOMIC_FORCEON) { + timer_check_buttons(); + } + ATOMIC_BLOCK(ATOMIC_FORCEON) { + patterns_next_tick(); + } + ATOMIC_BLOCK(ATOMIC_FORCEON) { + pwm_disable_if_not_needed(); + } + ATOMIC_BLOCK(ATOMIC_FORCEON) { + timer_start_slow_adcs(); + } + ATOMIC_BLOCK(ATOMIC_FORCEON) { + if ((jiffies & 0x7FF) == 0) + ambient_log_min_max(); + } +} + static void inline main_loop_iteration() { + unsigned char jiffies_8; /* + * we use only lower 8-bits in order to + * avoid the need for locking of 16-bit + * accesses. + */ + cli(); if (TIMER1_IS_ON()) { set_sleep_mode(SLEEP_MODE_IDLE); @@ -102,6 +134,20 @@ static void inline main_loop_iteration() sei(); sleep_cpu(); sleep_disable(); + + jiffies_8 = jiffies; + + if (jiffies_8 != prev_jiffies_8) { // was timer IRQ + if (jiffies_8 - prev_jiffies_8 > 1) { // overrun + log_byte(0xee); + log_byte(jiffies_8 - prev_jiffies_8); + log_flush(); + } + + prev_jiffies_8 = jiffies_8; + + do_timer(); + } } int main(void) diff --git a/firmware/tmr.c b/firmware/tmr.c index 7a31f19..77e1153 100644 --- a/firmware/tmr.c +++ b/firmware/tmr.c @@ -18,16 +18,7 @@ void susp_tmr() } ISR(WDT_vect) { - ++jiffies; - - timer_check_buttons(); - patterns_next_tick(); - pwm_disable_if_not_needed(); - timer_start_slow_adcs(); - - if ((jiffies & 0x7FF) == 0) - ambient_log_min_max(); - WDTCR |= _BV(WDIE); // avoid WDT reset next time + ++jiffies; } -- 2.39.3