1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu: msp430-common: fix context save/restore

Previously, __restore_context was meddling with the to-be-restored
context SR on the stack, not correctly restoring GIE.
Now, we let the CPU restore the correct status register as saved in
__save_context.

Contains some simplification of the context save/restore logic.
This commit is contained in:
Kaspar Schleiser 2015-09-14 15:36:36 +02:00
parent 00a0c90269
commit c122571801
3 changed files with 36 additions and 60 deletions

View File

@ -21,18 +21,15 @@
*/
__attribute__((naked)) void thread_yield_higher(void)
{
/*
* disable IRQ, remembering if they are
* to be reactivated after context switch
*/
unsigned int irqen = disableIRQ();
__asm__("push r2"); /* save SR */
__disable_irq();
__save_context();
/* have sched_active_thread point to the next thread */
sched_run();
__restore_context(irqen);
__restore_context();
UNREACHABLE();
}
@ -42,7 +39,7 @@ NORETURN void cpu_switch_context_exit(void)
sched_active_thread = sched_threads[0];
sched_run();
__restore_context(GIE);
__restore_context();
UNREACHABLE();
}

View File

@ -52,6 +52,28 @@ extern "C" {
#define dINT disableIRQ
/** @} */
/**
* @brief Globally disable IRQs
*/
static inline void __attribute__((always_inline)) __disable_irq(void)
{
__asm__ __volatile__("bic %0, r2" : : "i"(GIE));
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
__asm__ __volatile__("nop");
}
/**
* @brief Globally enable IRQs
*/
static inline void __attribute__((always_inline)) __enable_irq(void)
{
__asm__ __volatile__("bis %0, r2" : : "i"(GIE));
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
__asm__ __volatile__("nop");
}
/**
* @brief The current ISR state (inside or not)
*/
@ -65,7 +87,7 @@ extern char __isr_stack[MSP430_ISR_STACK_SIZE];
/**
* @brief Save the current thread context from inside an ISR
*/
inline void __save_context_isr(void)
static inline void __attribute__((always_inline)) __save_context(void)
{
__asm__("push r15");
__asm__("push r14");
@ -86,7 +108,7 @@ inline void __save_context_isr(void)
/**
* @brief Restore the thread context from inside an ISR
*/
inline void __restore_context_isr(void)
static inline void __attribute__((always_inline)) __restore_context(void)
{
__asm__("mov.w %0,r1" : : "m"(sched_active_thread->sp));
@ -102,14 +124,15 @@ inline void __restore_context_isr(void)
__asm__("pop r13");
__asm__("pop r14");
__asm__("pop r15");
__asm__("reti");
}
/**
* @brief Run this code on entering interrupt routines
*/
inline void __enter_isr(void)
static inline void __attribute__((always_inline)) __enter_isr(void)
{
__save_context_isr();
__save_context();
__asm__("mov.w %0,r1" : : "i"(__isr_stack + MSP430_ISR_STACK_SIZE));
__inISR = 1;
}
@ -117,7 +140,7 @@ inline void __enter_isr(void)
/**
* @brief Run this code on exiting interrupt routines
*/
inline void __exit_isr(void)
static inline void __attribute__((always_inline)) __exit_isr(void)
{
__inISR = 0;
@ -125,41 +148,7 @@ inline void __exit_isr(void)
sched_run();
}
__restore_context_isr();
__asm__("reti");
}
/**
* @brief Save the current context on the stack
*/
inline void __save_context(void)
{
__asm__("push r2"); /* save SR */
__save_context_isr();
}
/**
* @brief Restore the thread context from the stack
*
* @param[in] irqen former interrupt state
*/
inline void __restore_context(unsigned int irqen)
{
__restore_context_isr();
/*
* we want to enable appropriate IRQs *just after*
* quitting the interrupt handler; to that end,
* we change the GIE bit in the value to be restored
* in R2 (a.k.a. SR) by the next RETI instruction
*/
if (irqen) {
__asm__("bis.w #8, 0(r1)");
} else {
__asm__("bic.w #8, 0(r1)");
}
__asm__("reti");
__restore_context();
}
/**

View File

@ -33,11 +33,7 @@ unsigned int disableIRQ(void)
state &= GIE;
if (state) {
/* puts("-"); */
__asm__ __volatile__("bic %0, r2" : : "i"(GIE));
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
__asm__ __volatile__("nop");
__disable_irq();
}
return state;
@ -50,10 +46,7 @@ unsigned int enableIRQ(void)
state &= GIE;
if (!state) {
__asm__ __volatile__("bis %0, r2" : : "i"(GIE));
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
__asm__ __volatile__("nop");
__enable_irq();
}
return state;
@ -62,10 +55,7 @@ unsigned int enableIRQ(void)
void restoreIRQ(unsigned int state)
{
if (state) {
__asm__ __volatile__("bis %0, r2" : : "i"(GIE));
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
__asm__ __volatile__("nop");
__enable_irq();
}
}