Save status register on each interrupt.

Costs 28 bytes binary size and two CPU cycles per interrupt,
at the advantage of getting rid of possible well hidden bugs.
This commit is contained in:
Markus Hitter 2011-12-04 18:22:11 +01:00
parent c126629ec8
commit 7528037d4e
5 changed files with 67 additions and 7 deletions

View File

@ -7,6 +7,7 @@
#include "temp.h" #include "temp.h"
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "memory_barrier.h"
/* OR-combined mask of all channels */ /* OR-combined mask of all channels */
#undef DEFINE_TEMP_SENSOR #undef DEFINE_TEMP_SENSOR
@ -79,6 +80,9 @@ void analog_init() {
This is where we read our analog value and store it in an array for later retrieval This is where we read our analog value and store it in an array for later retrieval
*/ */
ISR(ADC_vect, ISR_NOBLOCK) { ISR(ADC_vect, ISR_NOBLOCK) {
// save status register
uint8_t sreg_save = SREG;
// emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts // emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts
if (analog_mask > 0) { if (analog_mask > 0) {
// store next result // store next result
@ -102,6 +106,10 @@ ISR(ADC_vect, ISR_NOBLOCK) {
// After the mux has been set, start a new conversion // After the mux has been set, start a new conversion
ADCSRA |= MASK(ADSC); ADCSRA |= MASK(ADSC);
} }
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
/*! Read analog value from saved result array /*! Read analog value from saved result array

View File

@ -139,6 +139,9 @@ ISR(USART1_RX_vect)
ISR(USART_RX_vect) ISR(USART_RX_vect)
#endif #endif
{ {
// save status register
uint8_t sreg_save = SREG;
// pull character // pull character
static uint8_t c; static uint8_t c;
@ -196,6 +199,10 @@ ISR(USART_RX_vect)
#endif #endif
} }
} }
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
// finished transmitting interrupt- only enabled at end of packet // finished transmitting interrupt- only enabled at end of packet
@ -205,6 +212,9 @@ ISR(USART1_TX_vect)
ISR(USART_TX_vect) ISR(USART_TX_vect)
#endif #endif
{ {
// save status register
uint8_t sreg_save = SREG;
if (packet_pointer >= sizeof(intercom_packet_t)) { if (packet_pointer >= sizeof(intercom_packet_t)) {
disable_transmit(); disable_transmit();
packet_pointer = 0; packet_pointer = 0;
@ -215,6 +225,10 @@ ISR(USART_TX_vect)
UCSR0B &= ~MASK(TXCIE0); UCSR0B &= ~MASK(TXCIE0);
#endif #endif
} }
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
// tx queue empty interrupt- send next byte // tx queue empty interrupt- send next byte
@ -224,6 +238,9 @@ ISR(USART1_UDRE_vect)
ISR(USART_UDRE_vect) ISR(USART_UDRE_vect)
#endif #endif
{ {
// save status register
uint8_t sreg_save = SREG;
#ifdef HOST #ifdef HOST
UDR1 = _tx.data[packet_pointer++]; UDR1 = _tx.data[packet_pointer++];
#else #else
@ -239,6 +256,10 @@ ISR(USART_UDRE_vect)
UCSR0B |= MASK(TXCIE0); UCSR0B |= MASK(TXCIE0);
#endif #endif
} }
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
#endif /* TEMP_INTERCOM */ #endif /* TEMP_INTERCOM */

View File

@ -11,6 +11,7 @@
*/ */
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "memory_barrier.h"
#include "config.h" #include "config.h"
#include "arduino.h" #include "arduino.h"
@ -110,6 +111,9 @@ ISR(USART_RX_vect)
ISR(USART0_RX_vect) ISR(USART0_RX_vect)
#endif #endif
{ {
// save status register
uint8_t sreg_save = SREG;
if (buf_canwrite(rx)) if (buf_canwrite(rx))
buf_push(rx, UDR0); buf_push(rx, UDR0);
else { else {
@ -128,6 +132,10 @@ ISR(USART0_RX_vect)
UCSR0B |= MASK(UDRIE0); UCSR0B |= MASK(UDRIE0);
} }
#endif #endif
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
/// transmit buffer ready interrupt /// transmit buffer ready interrupt
@ -139,6 +147,9 @@ ISR(USART_UDRE_vect)
ISR(USART0_UDRE_vect) ISR(USART0_UDRE_vect)
#endif #endif
{ {
// save status register
uint8_t sreg_save = SREG;
#ifdef XONXOFF #ifdef XONXOFF
if (flowflags & FLOWFLAG_SEND_XON) { if (flowflags & FLOWFLAG_SEND_XON) {
UDR0 = ASCII_XON; UDR0 = ASCII_XON;
@ -154,6 +165,10 @@ ISR(USART0_UDRE_vect)
buf_pop(tx, UDR0); buf_pop(tx, UDR0);
else else
UCSR0B &= ~MASK(UDRIE0); UCSR0B &= ~MASK(UDRIE0);
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
/* /*

22
timer.c
View File

@ -11,6 +11,7 @@
*/ */
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "memory_barrier.h"
#include "arduino.h" #include "arduino.h"
#include "config.h" #include "config.h"
@ -19,7 +20,6 @@
#include "dda_queue.h" #include "dda_queue.h"
#endif #endif
#include "memory_barrier.h"
/// how often we overflow and update our clock; with F_CPU=16MHz, max is < 4.096ms (TICK_TIME = 65535) /// how often we overflow and update our clock; with F_CPU=16MHz, max is < 4.096ms (TICK_TIME = 65535)
#define TICK_TIME 2 MS #define TICK_TIME 2 MS
@ -48,6 +48,9 @@ volatile uint8_t clock_flag_1s = 0;
/// comparator B is the system clock, happens every TICK_TIME /// comparator B is the system clock, happens every TICK_TIME
ISR(TIMER1_COMPB_vect) { ISR(TIMER1_COMPB_vect) {
// save status register
uint8_t sreg_save = SREG;
// set output compare register to the next clock tick // set output compare register to the next clock tick
OCR1B = (OCR1B + TICK_TIME) & 0xFFFF; OCR1B = (OCR1B + TICK_TIME) & 0xFFFF;
@ -71,12 +74,19 @@ ISR(TIMER1_COMPB_vect) {
} }
} }
} }
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
#ifdef HOST #ifdef HOST
/// comparator A is the step timer. It has higher priority then B. /// comparator A is the step timer. It has higher priority then B.
ISR(TIMER1_COMPA_vect) { ISR(TIMER1_COMPA_vect) {
// save status register
uint8_t sreg_save = SREG;
// Check if this is a real step, or just a next_step_time "overflow" // Check if this is a real step, or just a next_step_time "overflow"
if (next_step_time < 65536) { if (next_step_time < 65536) {
// step! // step!
@ -108,6 +118,10 @@ ISR(TIMER1_COMPA_vect) {
next_step_time += 10000; next_step_time += 10000;
} }
// leave OCR1A as it was // leave OCR1A as it was
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
#endif /* ifdef HOST */ #endif /* ifdef HOST */
@ -136,8 +150,6 @@ void timer_init()
*/ */
void setTimer(uint32_t delay) void setTimer(uint32_t delay)
{ {
// save interrupt flag
uint8_t sreg = SREG;
uint16_t step_start = 0; uint16_t step_start = 0;
#ifdef ACCELERATION_TEMPORAL #ifdef ACCELERATION_TEMPORAL
uint16_t current_time; uint16_t current_time;
@ -211,10 +223,6 @@ void setTimer(uint32_t delay)
// timer1a interrupt to the far side of the return, protecting the // timer1a interrupt to the far side of the return, protecting the
// stack from recursively clobbering memory. // stack from recursively clobbering memory.
TIMSK1 |= MASK(OCIE1A); TIMSK1 |= MASK(OCIE1A);
// restore interrupt flag
MEMORY_BARRIER();
SREG = sreg;
} }
/// stop timers - emergency stop /// stop timers - emergency stop

View File

@ -14,6 +14,7 @@
#include <avr/wdt.h> #include <avr/wdt.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "memory_barrier.h"
#include "arduino.h" #include "arduino.h"
#ifndef EXTRUDER #ifndef EXTRUDER
@ -31,10 +32,17 @@ volatile uint8_t wd_flag = 0;
// } // }
ISR(WDT_vect) { ISR(WDT_vect) {
// save status register
uint8_t sreg_save = SREG;
// watchdog has tripped- no main loop activity for 0.5s, probably a bad thing // watchdog has tripped- no main loop activity for 0.5s, probably a bad thing
// if watchdog fires again, we will reset // if watchdog fires again, we will reset
// perhaps we should do something more intelligent in this interrupt? // perhaps we should do something more intelligent in this interrupt?
wd_flag |= 1; wd_flag |= 1;
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
} }
/// intialise watchdog /// intialise watchdog