Merge pull request #8904 from ZetaR60/RIOT_atmega_race_fix_alt

cpu/atmega_common: return to non-interrupt context swaps
This commit is contained in:
Francisco Acosta 2018-05-04 12:08:59 +02:00 committed by GitHub
commit 53c3f833af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 23 additions and 106 deletions

View File

@ -59,32 +59,6 @@ extern "C" {
#define LED0_TOGGLE (PORTB ^= LED0_MASK) #define LED0_TOGGLE (PORTB ^= LED0_MASK)
/** @} */ /** @} */
/**
* @brief Context swap defines
*
* Setup to use PC5 which is pin change interrupt 13 (PCINT13)
* This emulates a software triggered interrupt
*/
#ifdef CPU_ATMEGA328P
#define AVR_CONTEXT_SWAP_INIT do { \
DDRD |= (1 << PD7); \
PCICR |= (1 << PCIE2); \
PCMSK2 |= (1 << PCINT23); \
} while (0)
#define AVR_CONTEXT_SWAP_INTERRUPT_VECT PCINT2_vect
#define AVR_CONTEXT_SWAP_TRIGGER PORTD ^= (1 << PD7)
#endif
#ifdef CPU_ATMEGA2560
#define AVR_CONTEXT_SWAP_INIT do { \
DDRJ |= (1 << PJ6); \
PCICR |= (1 << PCIE1); \
PCMSK1 |= (1 << PCINT15); \
} while (0)
#define AVR_CONTEXT_SWAP_INTERRUPT_VECT PCINT1_vect
#define AVR_CONTEXT_SWAP_TRIGGER PORTJ ^= (1 << PJ6)
#endif
/** /**
* @name xtimer configuration values * @name xtimer configuration values
* @{ * @{

View File

@ -75,21 +75,6 @@ extern "C" {
#define LED2_TOGGLE (LED_PORT ^= LED2_MASK) #define LED2_TOGGLE (LED_PORT ^= LED2_MASK)
/** @} */ /** @} */
/**
* @name Context swap defines
* This emulates a software triggered interrupt
* @{
*/
#define AVR_CONTEXT_SWAP_INIT do { \
DDRE |= (1 << PE7); \
EICRB |= (1 << ISC70); \
EIMSK |= (1 << INT7); \
sei(); \
} while (0)
#define AVR_CONTEXT_SWAP_INTERRUPT_VECT INT7_vect
#define AVR_CONTEXT_SWAP_TRIGGER PORTE ^= (1 << PE7)
/** @} */
/** /**
* @name xtimer configuration values * @name xtimer configuration values
* @{ * @{

View File

@ -49,22 +49,6 @@ extern "C" {
*/ */
#define UART_STDIO_DEV (UART_DEV(1)) #define UART_STDIO_DEV (UART_DEV(1))
/**
* @name Context swap defines
*
* Setup to use PD7 which is pin change interrupt 31 (PCINT31)
* This emulates a software triggered interrupt
* @{
*/
#define AVR_CONTEXT_SWAP_INIT do { \
DDRD |= (1 << PD7); \
PCICR |= (1 << PCIE3); \
PCMSK3 |= (1 << PCINT31); \
} while (0)
#define AVR_CONTEXT_SWAP_INTERRUPT_VECT PCINT3_vect
#define AVR_CONTEXT_SWAP_TRIGGER PORTD ^= (1 << PD7)
/** @} */
/** /**
* @name xtimer configuration values * @name xtimer configuration values
* *

View File

@ -145,21 +145,6 @@ extern "C" {
MUX_USB_XBEE_ON MUX_USB_XBEE_ON
/** @} */ /** @} */
/**
* @brief Context swap defines
* Setup to use PB5 which is pin change interrupt 5
* This emulates a software triggered interrupt
**/
#define AVR_CONTEXT_SWAP_INIT do { \
DDRB |= (1 << PB5); \
PCICR |= (1 << PCIE0); \
PCMSK0 |= (1 << PCINT5); \
} while (0)
/** @cond INTERNAL */
#define AVR_CONTEXT_SWAP_INTERRUPT_VECT PCINT0_vect
#define AVR_CONTEXT_SWAP_TRIGGER PORTB ^= (1 << PB5)
/** @endcond */
/** /**
* @name xtimer configuration values * @name xtimer configuration values
* @{ * @{

View File

@ -97,6 +97,13 @@ __attribute__((always_inline)) static inline void cpu_print_last_instruction(voi
*/ */
void atmega_stdio_init(void); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -313,10 +313,9 @@ ISR(INT6_vect, ISR_BLOCK)
} }
#endif #endif
#if defined(INT7_vect) && !defined(BOARD_JIMINY_MEGA256RFR2) #if defined(INT7_vect)
/**< INT7 is context swap pin for the Jiminy board */
ISR(INT7_vect, ISR_BLOCK) ISR(INT7_vect, ISR_BLOCK)
{ {
irq_handler(7); /**< predefined interrupt pin */ irq_handler(7); /**< predefined interrupt pin */
} }
#endif /* INT7_vect && END BOARD_JIMINY_MEGA256RFR2 */ #endif

View File

@ -176,6 +176,7 @@ static inline void _isr(tim_t tim, int chan)
if (sched_context_switch_request) { if (sched_context_switch_request) {
thread_yield(); thread_yield();
thread_yield_isr();
} }
__exit_isr(); __exit_isr();

View File

@ -170,6 +170,7 @@ static inline void isr_handler(int num)
if (sched_context_switch_request) { if (sched_context_switch_request) {
thread_yield(); thread_yield();
thread_yield_isr();
} }
} }

View File

@ -29,31 +29,6 @@
#include "board.h" #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 __) * local function declarations (prefixed with __)
*/ */
@ -228,7 +203,6 @@ void cpu_switch_context_exit(void) __attribute__((naked));
void cpu_switch_context_exit(void) void cpu_switch_context_exit(void)
{ {
sched_run(); sched_run();
AVR_CONTEXT_SWAP_INIT;
__enter_thread_mode(); __enter_thread_mode();
} }
@ -247,19 +221,26 @@ void NORETURN __enter_thread_mode(void)
} }
void thread_yield_higher(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;
}
} }
void thread_yield_isr(void) {
/* Use this interrupt to perform all context switches */
ISR(AVR_CONTEXT_SWAP_INTERRUPT_VECT, ISR_NAKED) {
__context_save(); __context_save();
sched_run(); sched_run();
__context_restore(); __context_restore();
__exit_isr();
__asm__ volatile("reti"); __asm__ volatile("reti");
} }
__attribute__((always_inline)) static inline void __context_save(void) __attribute__((always_inline)) static inline void __context_save(void)
{ {
__asm__ volatile( __asm__ volatile(