diff --git a/boards/arduino-mega2560/include/periph_conf.h b/boards/arduino-mega2560/include/periph_conf.h index 19f1d3dc1f..f763ed22e0 100644 --- a/boards/arduino-mega2560/include/periph_conf.h +++ b/boards/arduino-mega2560/include/periph_conf.h @@ -64,6 +64,8 @@ extern "C" { #define TIMER0_COMP_B_EN OCIE1B #define TIMER0_COMP_C_EN OCIE1C #define TIMER0_FREQ_16MHZ (0 << CS12) | (0 << CS11) | (1 << CS10) +#define TIMER0_FREQ_2MHZ (0 << CS12) | (1 << CS11) | (0 << CS10) +#define TIMER0_FREQ_250KHZ (0 << CS12) | (1 << CS11) | (1 << CS10) #define TIMER0_FREQ_DISABLE (0 << CS12) | (0 << CS11) | (0 << CS10) #define TIMER0_COMPA_ISR TIMER1_COMPA_vect #define TIMER0_COMPB_ISR TIMER1_COMPB_vect @@ -90,6 +92,8 @@ extern "C" { #define TIMER1_COMP_B_EN OCIE3B #define TIMER1_COMP_C_EN OCIE3C #define TIMER1_FREQ_16MHZ (0 << CS32) | (0 << CS31) | (1 << CS30) +#define TIMER1_FREQ_2MHZ (0 << CS32) | (1 << CS31) | (0 << CS30) +#define TIMER1_FREQ_250KHZ (0 << CS32) | (1 << CS31) | (1 << CS30) #define TIMER1_FREQ_DISABLE (0 << CS32) | (0 << CS31) | (0 << CS30) #define TIMER1_COMPA_ISR TIMER3_COMPA_vect #define TIMER1_COMPB_ISR TIMER3_COMPB_vect @@ -116,6 +120,8 @@ extern "C" { #define TIMER2_COMP_B_EN OCIE4B #define TIMER2_COMP_C_EN OCIE4C #define TIMER2_FREQ_16MHZ (0 << CS42) | (0 << CS41) | (1 << CS40) +#define TIMER2_FREQ_2MHZ (0 << CS42) | (1 << CS41) | (0 << CS40) +#define TIMER2_FREQ_250KHZ (0 << CS42) | (1 << CS41) | (1 << CS40) #define TIMER2_FREQ_DISABLE (0 << CS42) | (0 << CS41) | (0 << CS40) #define TIMER2_COMPA_ISR TIMER4_COMPA_vect #define TIMER2_COMPB_ISR TIMER4_COMPB_vect diff --git a/cpu/atmega2560/periph/gpio.c b/cpu/atmega2560/periph/gpio.c index 275e1dc7eb..610fa9936e 100644 --- a/cpu/atmega2560/periph/gpio.c +++ b/cpu/atmega2560/periph/gpio.c @@ -215,7 +215,9 @@ void gpio_write(gpio_t pin, int value) static inline void irq_handler(uint8_t pin_num) { + __enter_isr(); config[pin_num].cb(config[pin_num].arg); + __exit_isr(); } ISR(INT0_vect, ISR_BLOCK) diff --git a/cpu/atmega2560/periph/timer.c b/cpu/atmega2560/periph/timer.c index c10312ff05..d4e5eb660a 100644 --- a/cpu/atmega2560/periph/timer.c +++ b/cpu/atmega2560/periph/timer.c @@ -26,27 +26,15 @@ #include "board.h" #include "cpu.h" +#include "thread.h" #include "periph/timer.h" #include "periph_conf.h" -static inline int __set_timer(tim_t dev, - int channel, - unsigned int timeout, - unsigned int interval - ); - #define IRQ_DISABLED 0x00 typedef struct { void (*cb)(int); - volatile uint8_t ctr_a; - volatile uint8_t ctr_b; - volatile uint8_t ctr_c; - uint8_t limit; - uint16_t timeout_a; - uint16_t timeout_b; - uint16_t timeout_c; } timer_conf_t; /** @@ -58,17 +46,13 @@ timer_conf_t config[TIMER_NUMOF]; * @brief Setup the given timer * */ -int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int)) +int timer_init(tim_t dev, unsigned int us_per_ticks, void (*callback)(int)) { - /* reject impossible ticks_per_us values */ - if ((ticks_per_us > 16) && (ticks_per_us == 0)) { + /* reject impossible us_per_ticks values */ + if ((us_per_ticks != 4)) { return -1; } - config[dev].limit = 16 / ticks_per_us; - config[dev].ctr_a = 0x00; - config[dev].ctr_b = 0x00; - config[dev].ctr_c = 0x00; /* select the timer and enable the timer specific peripheral clocks */ switch (dev) { @@ -76,21 +60,21 @@ int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int)) case TIMER_0: TIMER0_COUNTER = 0; - TIMER0_CONTROL_B |= TIMER0_FREQ_16MHZ; + TIMER0_CONTROL_B |= TIMER0_FREQ_250KHZ; break; #endif #if TIMER_1_EN case TIMER_1: TIMER1_COUNTER = 0; - TIMER1_CONTROL_B |= TIMER1_FREQ_16MHZ; + TIMER1_CONTROL_B |= TIMER1_FREQ_250KHZ; break; #endif #if TIMER_2_EN case TIMER_2: TIMER2_COUNTER = 0; - TIMER2_CONTROL_B |= TIMER2_FREQ_16MHZ; + TIMER2_CONTROL_B |= TIMER2_FREQ_250KHZ; break; #endif @@ -107,35 +91,128 @@ int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int)) int timer_set(tim_t dev, int channel, unsigned int timeout) { - return __set_timer(dev, channel, timer_read(dev) + timeout, timeout); + return timer_set_absolute(dev, channel, timer_read(dev) + timeout); } -int timer_set_absolute(tim_t dev, int channel, unsigned int timeout) +int timer_set_absolute(tim_t dev, int channel, unsigned int value) { - return __set_timer(dev, channel, timeout, timeout); + unsigned state = disableIRQ(); + + switch (dev) { +#if TIMER_0_EN + case TIMER_0: + switch (channel) { + case 0: + TIMER0_COMP_A = (uint16_t) value; + TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_A_FLAG); + TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_A_EN); + break; + + case 1: + TIMER0_COMP_B = (uint16_t) value; + TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_B_FLAG); + TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_B_EN); + break; + + case 2: + TIMER0_COMP_C = (uint16_t) value; + TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_C_FLAG); + TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_C_EN); + break; + + default: + restoreIRQ(state); + return -1; + } + + break; +#endif +#if TIMER_1_EN + case TIMER_1: + switch (channel) { + case 0: + TIMER1_COMP_A = (uint16_t) value; + TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_A_FLAG); + TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_A_EN); + break; + + case 1: + TIMER1_COMP_B = (uint16_t) value; + TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_B_FLAG); + TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_B_EN); + break; + + case 2: + TIMER1_COMP_C = (uint16_t) value; + TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_C_FLAG); + TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_C_EN); + break; + + default: + restoreIRQ(state); + return -1; + } + + break; +#endif +#if TIMER_2_EN + case TIMER_2: + switch (channel) { + case 0: + TIMER2_COMP_A = (uint16_t) value; + TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_A_FLAG); + TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_A_EN); + break; + + case 1: + TIMER2_COMP_B = (uint16_t) value; + TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_B_FLAG); + TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_B_EN); + break; + + case 2: + TIMER2_COMP_C = (uint16_t) value; + TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_C_FLAG); + TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_C_EN); + break; + + default: + restoreIRQ(state); + return -1; + } + + break; +#endif + + case TIMER_UNDEFINED: + default: + restoreIRQ(state); + return -1; + } + + /* enable interrupts for given timer */ + timer_irq_enable(dev); + restoreIRQ(state); + + return 1; } int timer_clear(tim_t dev, int channel) { - switch (dev) { #if TIMER_0_EN - case TIMER_0: switch (channel) { case 0: TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_A_FLAG); - config[dev].timeout_a = IRQ_DISABLED; break; case 1: TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_B_FLAG); - config[dev].timeout_b = IRQ_DISABLED; break; case 2: TIMER0_IRQ_FLAG_REG &= ~(1 << TIMER0_COMP_C_FLAG); - config[dev].timeout_c = IRQ_DISABLED; break; default: @@ -145,22 +222,18 @@ int timer_clear(tim_t dev, int channel) break; #endif #if TIMER_1_EN - case TIMER_1: switch (channel) { case 0: TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_A_FLAG); - config[dev].timeout_a = IRQ_DISABLED; break; case 1: TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_B_FLAG); - config[dev].timeout_b = IRQ_DISABLED; break; case 2: TIMER1_IRQ_FLAG_REG &= ~(1 << TIMER1_COMP_C_FLAG); - config[dev].timeout_c = IRQ_DISABLED; break; default: @@ -176,17 +249,14 @@ int timer_clear(tim_t dev, int channel) switch (channel) { case 0: TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_A_FLAG); - config[dev].timeout_a = IRQ_DISABLED; break; case 1: TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_B_FLAG); - config[dev].timeout_b = IRQ_DISABLED; break; case 2: TIMER2_IRQ_FLAG_REG &= ~(1 << TIMER2_COMP_C_FLAG); - config[dev].timeout_c = IRQ_DISABLED; break; default: @@ -213,7 +283,7 @@ unsigned int timer_read(tim_t dev) * Disabling interrupts globally because read from 16 Bit register can * otherwise be messed up */ - disableIRQ(); + unsigned state = disableIRQ(); switch (dev) { #if TIMER_0_EN @@ -238,10 +308,9 @@ unsigned int timer_read(tim_t dev) case TIMER_UNDEFINED: default: value = 0; - enableIRQ(); } - enableIRQ(); + restoreIRQ(state); return value; } @@ -278,19 +347,19 @@ void timer_start(tim_t dev) #if TIMER_0_EN case TIMER_0: - TIMER0_CONTROL_B |= TIMER0_FREQ_16MHZ; + TIMER0_CONTROL_B |= TIMER0_FREQ_250KHZ; break; #endif #if TIMER_1_EN case TIMER_1: - TIMER1_CONTROL_B |= TIMER1_FREQ_16MHZ; + TIMER1_CONTROL_B |= TIMER1_FREQ_250KHZ; break; #endif #if TIMER_2_EN case TIMER_2: - TIMER1_CONTROL_B |= TIMER1_FREQ_16MHZ; + TIMER1_CONTROL_B |= TIMER1_FREQ_250KHZ; break; #endif @@ -301,121 +370,35 @@ void timer_start(tim_t dev) void timer_irq_enable(tim_t dev) { - switch (dev) { -#if TIMER_0_EN - - case TIMER_0: - if (config[dev].timeout_a != IRQ_DISABLED) { - TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_A_EN); - } - - if (config[dev].timeout_b != IRQ_DISABLED) { - TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_B_EN); - } - - if (config[dev].timeout_c != IRQ_DISABLED) { - TIMER0_IRQ_MASK_REG |= (1 << TIMER0_COMP_C_EN); - } - - break; +#ifdef DEVELHELP + printf("timer_irq_enable not implemented\n"); #endif -#if TIMER_1_EN - - case TIMER_1: - if (config[dev].timeout_a != IRQ_DISABLED) { - TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_A_EN); - } - - if (config[dev].timeout_b != IRQ_DISABLED) { - TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_B_EN); - } - - if (config[dev].timeout_c != IRQ_DISABLED) { - TIMER1_IRQ_MASK_REG |= (1 << TIMER1_COMP_C_EN); - } - - break; -#endif -#if TIMER_2_EN - - case TIMER_2: - if (config[dev].timeout_a != IRQ_DISABLED) { - TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_A_EN); - } - - if (config[dev].timeout_b != IRQ_DISABLED) { - TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_B_EN); - } - - if (config[dev].timeout_c != IRQ_DISABLED) { - TIMER2_IRQ_MASK_REG |= (1 << TIMER2_COMP_C_EN); - } - - break; -#endif - - case TIMER_UNDEFINED: - break; - } - - enableIRQ(); } void timer_irq_disable(tim_t dev) { switch (dev) { #if TIMER_0_EN - case TIMER_0: - if (config[dev].timeout_a == IRQ_DISABLED) { - TIMER0_IRQ_MASK_REG &= ~(1 << TIMER0_COMP_A_EN); - } - - if (config[dev].timeout_b == IRQ_DISABLED) { - TIMER0_IRQ_MASK_REG &= ~(1 << TIMER0_COMP_B_EN); - } - - if (config[dev].timeout_c == IRQ_DISABLED) { - TIMER0_IRQ_MASK_REG &= ~(1 << TIMER0_COMP_C_EN); - } - + TIMER0_IRQ_MASK_REG &= ~(1 << TIMER0_COMP_A_EN); + TIMER0_IRQ_MASK_REG &= ~(1 << TIMER0_COMP_B_EN); + TIMER0_IRQ_MASK_REG &= ~(1 << TIMER0_COMP_C_EN); break; #endif #if TIMER_1_EN - case TIMER_1: - if (config[dev].timeout_a == IRQ_DISABLED) { - TIMER1_IRQ_MASK_REG &= ~(1 << TIMER1_COMP_A_EN); - } - - if (config[dev].timeout_b == IRQ_DISABLED) { - TIMER1_IRQ_MASK_REG &= ~(1 << TIMER1_COMP_B_EN); - } - - if (config[dev].timeout_c == IRQ_DISABLED) { - TIMER1_IRQ_MASK_REG &= ~(1 << TIMER1_COMP_C_EN); - } - + TIMER1_IRQ_MASK_REG &= ~(1 << TIMER1_COMP_A_EN); + TIMER1_IRQ_MASK_REG &= ~(1 << TIMER1_COMP_B_EN); + TIMER1_IRQ_MASK_REG &= ~(1 << TIMER1_COMP_C_EN); break; #endif #if TIMER_2_EN - case TIMER_2: - if (config[dev].timeout_a == IRQ_DISABLED) { - TIMER2_IRQ_MASK_REG &= ~(1 << TIMER2_COMP_A_EN); - } - - if (config[dev].timeout_b == IRQ_DISABLED) { - TIMER2_IRQ_MASK_REG &= ~(1 << TIMER2_COMP_B_EN); - } - - if (config[dev].timeout_c == IRQ_DISABLED) { - TIMER2_IRQ_MASK_REG &= ~(1 << TIMER2_COMP_C_EN); - } - + TIMER2_IRQ_MASK_REG &= ~(1 << TIMER2_COMP_A_EN); + TIMER2_IRQ_MASK_REG &= ~(1 << TIMER2_COMP_B_EN); + TIMER2_IRQ_MASK_REG &= ~(1 << TIMER2_COMP_C_EN); break; #endif - case TIMER_UNDEFINED: break; } @@ -425,255 +408,85 @@ void timer_reset(tim_t dev) { switch (dev) { #if TIMER_0_EN - case TIMER_0: TIMER0_COUNTER = 0; break; #endif #if TIMER_1_EN - case TIMER_1: TIMER1_COUNTER = 0; break; #endif #if TIMER_2_EN - case TIMER_2: TIMER2_COUNTER = 0; break; #endif - case TIMER_UNDEFINED: break; } } -inline int __set_timer(tim_t dev, int channel, unsigned int timeout, unsigned int interval) +static inline void _isr(int timer, int chan) { - /* - * Disabling interrupts globally because write to 16 Bit register can - * otherwise be messed up - */ - disableIRQ(); + __enter_isr(); + timer_clear(timer, chan); - switch (dev) { -#if TIMER_0_EN + config[timer].cb(chan); - case TIMER_0: - switch (channel) { - case 0: - TIMER0_COMP_A = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_a = interval; - break; - - case 1: - TIMER0_COMP_B = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_b = interval; - break; - - case 2: - TIMER0_COMP_C = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_c = interval; - break; - - default: - enableIRQ(); - return -1; - } - - break; -#endif -#if TIMER_1_EN - - case TIMER_1: - switch (channel) { - case 0: - TIMER1_COMP_A = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_a = interval; - break; - - case 1: - TIMER1_COMP_B = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_b = interval; - break; - - case 2: - TIMER1_COMP_C = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_c = interval; - break; - - default: - enableIRQ(); - return -1; - } - - break; -#endif -#if TIMER_2_EN - - case TIMER_2: - switch (channel) { - case 0: - TIMER2_COMP_A = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_a = interval; - break; - - case 1: - TIMER2_COMP_B = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_b = interval; - break; - - case 2: - TIMER2_COMP_C = (uint16_t) timeout * config[dev].limit; - config[dev].timeout_c = interval; - break; - - default: - enableIRQ(); - return -1; - } - - break; -#endif - - case TIMER_UNDEFINED: - default: - enableIRQ(); - return -1; + if (sched_context_switch_request) { + thread_yield(); } - - /* enable interrupts for given timer */ - timer_irq_enable(dev); - enableIRQ(); - - return 1; + __exit_isr(); } #if TIMER_0_EN ISR(TIMER0_COMPA_ISR, ISR_BLOCK) { - config[TIMER_0].ctr_a++; - - if (config[TIMER_0].ctr_a >= config[TIMER_0].limit) { - config[TIMER_0].limit = 0; - config[TIMER_0].cb(0); - TIMER0_COMP_A = TIMER0_COMP_A + config[TIMER_0].timeout_a * config[TIMER_0].limit; - } + _isr(0, 0); } ISR(TIMER0_COMPB_ISR, ISR_BLOCK) { - config[TIMER_0].ctr_b++; - - if (config[TIMER_0].ctr_b >= config[TIMER_0].limit) { - config[TIMER_0].limit = 0; - config[TIMER_0].cb(1); - TIMER0_COMP_B = TIMER0_COMP_B + config[TIMER_0].timeout_b * config[TIMER_0].limit; - } + _isr(0, 1); } ISR(TIMER0_COMPC_ISR, ISR_BLOCK) { - config[TIMER_0].ctr_c++; - - if (config[TIMER_0].ctr_c >= config[TIMER_0].limit) { - config[TIMER_0].limit = 0; - config[TIMER_0].cb(2); - TIMER0_COMP_C = TIMER0_COMP_C + config[TIMER_0].timeout_c * config[TIMER_0].limit; - } + _isr(0, 2); } #endif /* TIMER_0_EN */ #if TIMER_1_EN ISR(TIMER1_COMPA_ISR, ISR_BLOCK) { - config[TIMER_1].ctr_a++; - - if (config[TIMER_1].ctr_a >= config[TIMER_1].limit) { - config[TIMER_1].limit = 0; - config[TIMER_1].cb(0); - TIMER1_COMP_A = TIMER1_COMP_A + config[TIMER_1].timeout_a * config[TIMER_1].limit; - } - - if (sched_context_switch_request) { - thread_yield(); - } + _isr(1, 0); } ISR(TIMER1_COMPB_ISR, ISR_BLOCK) { - config[TIMER_1].ctr_b++; - - if (config[TIMER_1].ctr_b >= config[TIMER_1].limit) { - config[TIMER_1].limit = 0; - config[TIMER_1].cb(1); - TIMER1_COMP_B = TIMER1_COMP_B + config[TIMER_1].timeout_b * config[TIMER_1].limit; - } - - if (sched_context_switch_request) { - thread_yield(); - } + _isr(1, 1); } ISR(TIMER1_COMPC_ISR, ISR_BLOCK) { - config[TIMER_1].ctr_c++; - - if (config[TIMER_1].ctr_c >= config[TIMER_1].limit) { - config[TIMER_1].limit = 0; - config[TIMER_1].cb(2); - TIMER1_COMP_C = TIMER1_COMP_C + config[TIMER_1].timeout_c * config[TIMER_1].limit; - } - - if (sched_context_switch_request) { - thread_yield(); - } + _isr(1, 2); } #endif /* TIMER_1_EN */ #if TIMER_2_EN ISR(TIMER2_COMPA_ISR, ISR_BLOCK) { - config[TIMER_2].ctr_a++; - - if (config[TIMER_2].ctr_a >= config[TIMER_2].limit) { - config[TIMER_2].limit = 0; - config[TIMER_2].cb(0); - TIMER2_COMP_A = TIMER2_COMP_A + config[TIMER_2].timeout_a * config[TIMER_2].limit; - } - - if (sched_context_switch_request) { - thread_yield(); - } + _isr(2, 0); } ISR(TIMER2_COMPB_ISR, ISR_BLOCK) { - config[TIMER_2].ctr_b++; - - if (config[TIMER_2].ctr_b >= config[TIMER_2].limit) { - config[TIMER_2].limit = 0; - config[TIMER_2].cb(1); - TIMER2_COMP_B = TIMER2_COMP_B + config[TIMER_2].timeout_b * config[TIMER_2].limit; - } - - if (sched_context_switch_request) { - thread_yield(); - } + _isr(2, 1); } ISR(TIMER2_COMPC_ISR, ISR_BLOCK) { - config[TIMER_2].ctr_c++; - - if (config[TIMER_2].ctr_c >= config[TIMER_2].limit) { - config[TIMER_2].limit = 0; - config[TIMER_2].cb(2); - TIMER2_COMP_C = TIMER2_COMP_C + config[TIMER_2].timeout_c * config[TIMER_2].limit; - } - - if (sched_context_switch_request) { - thread_yield(); - } + _isr(2, 2); } #endif /* TIMER_2_EN */ diff --git a/cpu/atmega2560/periph/uart.c b/cpu/atmega2560/periph/uart.c index b68aeb1194..e2a1643e5c 100644 --- a/cpu/atmega2560/periph/uart.c +++ b/cpu/atmega2560/periph/uart.c @@ -276,44 +276,52 @@ int uart_write_blocking(uart_t uart, char data) #if UART_0_EN ISR(USART0_RX_vect, ISR_BLOCK) { + __enter_isr(); config[UART_0].rx_cb(config[UART_0].arg, UART0_DATA_REGISTER); if (sched_context_switch_request) { thread_yield(); } + __exit_isr(); } #endif /* UART_0_EN */ #if UART_1_EN ISR(USART1_RX_vect, ISR_BLOCK) { + __enter_isr(); config[UART_1].rx_cb(config[UART_1].arg, UART0_DATA_REGISTER); if (sched_context_switch_request) { thread_yield(); } + __exit_isr(); } #endif /* UART_1_EN */ #if UART_1_EN ISR(USART2_RX_vect, ISR_BLOCK) { + __enter_isr(); config[UART_2].rx_cb(config[UART_2].arg, UART0_DATA_REGISTER); if (sched_context_switch_request) { thread_yield(); } + __exit_isr(); } #endif /* UART_2_EN */ #if UART_2_EN ISR(USART2_RX_vect, ISR_BLOCK) { + __enter_isr(); config[UART_3].rx_cb(config[UART_3].arg, UART0_DATA_REGISTER); if (sched_context_switch_request) { thread_yield(); } + __exit_isr(); } #endif /* UART_3_EN */ #endif /* UART_0_EN || UART_1_EN |UART_2_EN| UART3 */ diff --git a/cpu/atmega_common/include/cpu.h b/cpu/atmega_common/include/cpu.h index 5af3727a4c..b7a83a9557 100644 --- a/cpu/atmega_common/include/cpu.h +++ b/cpu/atmega_common/include/cpu.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen + * Copyright (C) 2015 Kaspar Schleiser + * 2014 Freie Universität Berlin, Hinnerk van Bruinehsen * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -20,14 +21,16 @@ * @author Stefan Pfeiffer * @author Hauke Petersen * @author Hinnerk van Bruinehsen + * @author Kaspar Schleiser */ #ifndef __ATMEGA_COMMON_H #define __ATMEGA_COMMON_H #include -#include +#include +#include #include "cpu_conf.h" /** @@ -43,6 +46,27 @@ extern "C" { #define eINT enableIRQ #define dINT disableIRQ +/** + * @brief global in-ISR state variable + */ +extern volatile uint8_t __in_isr; + +/** + * @brief Flag entering of an ISR + */ +static inline void __enter_isr(void) +{ + __in_isr = 1; +} + +/** + * @brief Flag exiting of an ISR + */ +static inline void __exit_isr(void) +{ + __in_isr = 0; +} + /** * @brief Initialization of the CPU */ diff --git a/cpu/atmega_common/irq_arch.c b/cpu/atmega_common/irq_arch.c index f494aff41f..61747c4b1d 100644 --- a/cpu/atmega_common/irq_arch.c +++ b/cpu/atmega_common/irq_arch.c @@ -20,6 +20,7 @@ */ #include +#include #include "arch/irq_arch.h" #include "cpu.h" @@ -29,6 +30,8 @@ static uint8_t __get_interrupt_state(void); static void __set_interrupt_state(uint8_t state); +volatile uint8_t __in_isr = 0; + __attribute__((always_inline)) static inline uint8_t __get_interrupt_state(void) { uint8_t sreg; @@ -84,9 +87,5 @@ void irq_arch_restore(unsigned int state) */ int irq_arch_in(void) { - /* - * TODO: find a way to implement this function (e.g. a static variable dis- or - * set and unset in each ISR) - */ - return 0; + return __in_isr; }