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 <avr/interrupt.h>
#include "memory_barrier.h"
/* OR-combined mask of all channels */
#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
*/
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
if (analog_mask > 0) {
// store next result
@ -102,6 +106,10 @@ ISR(ADC_vect, ISR_NOBLOCK) {
// After the mux has been set, start a new conversion
ADCSRA |= MASK(ADSC);
}
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
}
/*! Read analog value from saved result array

View File

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

View File

@ -11,6 +11,7 @@
*/
#include <avr/interrupt.h>
#include "memory_barrier.h"
#include "config.h"
#include "arduino.h"
@ -110,6 +111,9 @@ ISR(USART_RX_vect)
ISR(USART0_RX_vect)
#endif
{
// save status register
uint8_t sreg_save = SREG;
if (buf_canwrite(rx))
buf_push(rx, UDR0);
else {
@ -128,6 +132,10 @@ ISR(USART0_RX_vect)
UCSR0B |= MASK(UDRIE0);
}
#endif
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
}
/// transmit buffer ready interrupt
@ -139,6 +147,9 @@ ISR(USART_UDRE_vect)
ISR(USART0_UDRE_vect)
#endif
{
// save status register
uint8_t sreg_save = SREG;
#ifdef XONXOFF
if (flowflags & FLOWFLAG_SEND_XON) {
UDR0 = ASCII_XON;
@ -154,6 +165,10 @@ ISR(USART0_UDRE_vect)
buf_pop(tx, UDR0);
else
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 "memory_barrier.h"
#include "arduino.h"
#include "config.h"
@ -19,7 +20,6 @@
#include "dda_queue.h"
#endif
#include "memory_barrier.h"
/// how often we overflow and update our clock; with F_CPU=16MHz, max is < 4.096ms (TICK_TIME = 65535)
#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
ISR(TIMER1_COMPB_vect) {
// save status register
uint8_t sreg_save = SREG;
// set output compare register to the next clock tick
OCR1B = (OCR1B + TICK_TIME) & 0xFFFF;
@ -71,12 +74,19 @@ ISR(TIMER1_COMPB_vect) {
}
}
}
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
}
#ifdef HOST
/// comparator A is the step timer. It has higher priority then B.
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"
if (next_step_time < 65536) {
// step!
@ -108,6 +118,10 @@ ISR(TIMER1_COMPA_vect) {
next_step_time += 10000;
}
// leave OCR1A as it was
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
}
#endif /* ifdef HOST */
@ -136,8 +150,6 @@ void timer_init()
*/
void setTimer(uint32_t delay)
{
// save interrupt flag
uint8_t sreg = SREG;
uint16_t step_start = 0;
#ifdef ACCELERATION_TEMPORAL
uint16_t current_time;
@ -211,10 +223,6 @@ void setTimer(uint32_t delay)
// timer1a interrupt to the far side of the return, protecting the
// stack from recursively clobbering memory.
TIMSK1 |= MASK(OCIE1A);
// restore interrupt flag
MEMORY_BARRIER();
SREG = sreg;
}
/// stop timers - emergency stop

View File

@ -14,6 +14,7 @@
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include "memory_barrier.h"
#include "arduino.h"
#ifndef EXTRUDER
@ -31,10 +32,17 @@ volatile uint8_t wd_flag = 0;
// }
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
// if watchdog fires again, we will reset
// perhaps we should do something more intelligent in this interrupt?
wd_flag |= 1;
// restore status register
MEMORY_BARRIER();
SREG = sreg_save;
}
/// intialise watchdog