1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 14:33:52 +01:00

Merge pull request #1618 from rousselk/msp430-fix-thread-yield

Fix thread_yield() on MSP430 platforms
This commit is contained in:
Oleg Hahm 2014-09-12 20:14:18 +02:00
commit fa8c70bbb8
2 changed files with 36 additions and 9 deletions

View File

@ -1,12 +1,14 @@
/*
* Copyright (C) 2013, Freie Universitaet Berlin (FUB). All rights reserved.
* Copyright (C) 2014, Freie Universitaet Berlin (FUB) & INRIA.
* All rights reserved.
*
* 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
* directory for more details.
*/
#include "cpu.h"
#include "irq.h"
#include "kernel.h"
#include "kernel_internal.h"
#include "sched.h"
@ -16,16 +18,27 @@ volatile int __inISR = 0;
char __isr_stack[MSP430_ISR_STACK_SIZE];
void thread_yield(void)
/*
* we must prevent the compiler to generate a prologue or an epilogue
* for thread_yield(), since we rely on the RETI instruction at the end
* of its execution, in the inlined __restore_context() sub-function
*/
__attribute__((naked)) void thread_yield(void)
{
/*
* disable IRQ, remembering if they are
* to be reactivated after context switch
*/
unsigned int irqen = disableIRQ();
__save_context();
dINT();
/* have sched_active_thread point to the next thread */
sched_run();
eINT();
__restore_context();
__restore_context(irqen);
UNREACHABLE();
}
NORETURN void cpu_switch_context_exit(void)
@ -33,7 +46,7 @@ NORETURN void cpu_switch_context_exit(void)
sched_active_thread = sched_threads[0];
sched_run();
__restore_context();
__restore_context(GIE);
UNREACHABLE();
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2013, Freie Universitaet Berlin (FUB). All rights reserved.
* Copyright (C) 2014, Freie Universitaet Berlin (FUB) & INRIA.
* All rights reserved.
*
* 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
@ -99,9 +100,22 @@ inline void __save_context(void)
__save_context_isr();
}
inline void __restore_context(void)
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");
}