diff --git a/cpu/atmega_common/include/cpu.h b/cpu/atmega_common/include/cpu.h index 0fc6a078ae..5f00593f38 100644 --- a/cpu/atmega_common/include/cpu.h +++ b/cpu/atmega_common/include/cpu.h @@ -97,6 +97,13 @@ __attribute__((always_inline)) static inline void cpu_print_last_instruction(voi */ void atmega_stdio_init(void); +/** + * @brief Exit ISR mode and yield with a return from interrupt. Use at the + * end of ISRs in place of thread_yield_higher. If thread_yield is needed, use + * thread_yield followed by thread_yield_isr instead of thread_yield alone. + */ +void thread_yield_isr(void); + #ifdef __cplusplus } #endif diff --git a/cpu/atmega_common/periph/timer.c b/cpu/atmega_common/periph/timer.c index 9eb2b1a87f..3b860ee1be 100644 --- a/cpu/atmega_common/periph/timer.c +++ b/cpu/atmega_common/periph/timer.c @@ -176,6 +176,7 @@ static inline void _isr(tim_t tim, int chan) if (sched_context_switch_request) { thread_yield(); + thread_yield_isr(); } __exit_isr(); diff --git a/cpu/atmega_common/periph/uart.c b/cpu/atmega_common/periph/uart.c index c1abacd068..3d13a3bf30 100644 --- a/cpu/atmega_common/periph/uart.c +++ b/cpu/atmega_common/periph/uart.c @@ -170,6 +170,7 @@ static inline void isr_handler(int num) if (sched_context_switch_request) { thread_yield(); + thread_yield_isr(); } } diff --git a/cpu/atmega_common/thread_arch.c b/cpu/atmega_common/thread_arch.c index dd3d0200e6..d76995e4e1 100644 --- a/cpu/atmega_common/thread_arch.c +++ b/cpu/atmega_common/thread_arch.c @@ -29,31 +29,6 @@ #include "board.h" -/** - * @brief AVR_CONTEXT_SWAP_INIT initialize the context swap trigger - * Called when threading is first started. - */ -#ifndef AVR_CONTEXT_SWAP_INIT -#error AVR_CONTEXT_SWAP_INIT must be defined in board.h -#endif - -/** - * @brief AVR_CONTEXT_SWAP_INTERRUPT_VECT Name of the ISR to use for context swapping - */ -#ifndef AVR_CONTEXT_SWAP_INTERRUPT_VECT -#error AVR_CONTEXT_SWAP_INTERRUPT_VECT must be defined in board.h -#endif - -/** - * @brief AVR_CONTEXT_SWAP_TRIGGER executed to start the context swap - * When executed, this should result in the interrupt named in - * AVR_CONTEXT_SWAP_INTERRUPT_VECT being called - */ -#ifndef AVR_CONTEXT_SWAP_TRIGGER -#error ARV_CONTEXT_SWAP_TRIGGER must be defined in board.h -#endif - - /* * local function declarations (prefixed with __) */ @@ -228,7 +203,6 @@ void cpu_switch_context_exit(void) __attribute__((naked)); void cpu_switch_context_exit(void) { sched_run(); - AVR_CONTEXT_SWAP_INIT; __enter_thread_mode(); } @@ -247,19 +221,26 @@ void NORETURN __enter_thread_mode(void) } void thread_yield_higher(void) { - AVR_CONTEXT_SWAP_TRIGGER; + if (irq_is_in() == 0) { + __context_save(); + sched_run(); + __context_restore(); + __asm__ volatile("ret"); + } else { + sched_context_switch_request = 1; + } } - -/* Use this interrupt to perform all context switches */ -ISR(AVR_CONTEXT_SWAP_INTERRUPT_VECT, ISR_NAKED) { +void thread_yield_isr(void) { __context_save(); sched_run(); __context_restore(); + + __exit_isr(); + __asm__ volatile("reti"); } - __attribute__((always_inline)) static inline void __context_save(void) { __asm__ volatile(