mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 14:33:52 +01:00
cpu/msp430_common: fix thread_yield_higher() when called in isr
This commit is contained in:
parent
22e9ba12a3
commit
1d46cf70eb
@ -14,23 +14,49 @@
|
||||
#include "thread.h"
|
||||
|
||||
/*
|
||||
* we must prevent the compiler to generate a prologue or an epilogue
|
||||
* for thread_yield_higher(), since we rely on the RETI instruction at the end
|
||||
* of its execution, in the inlined __restore_context() sub-function
|
||||
* This function can both be called from ISR and from thread context.
|
||||
*
|
||||
* In both cases, the caller will use "CALL", which pushes the return
|
||||
* address on the stack before executing the function's first instruction.
|
||||
*
|
||||
* If called within ISR, just set sched_context_switch_request and
|
||||
* directly return to the call site. A regular function return does this.
|
||||
*
|
||||
* If called from stack context, it needs to prepare the stack so it looks exactly
|
||||
* as if the thread had been interrupted by an ISR, which requires the SR to be on
|
||||
* stack right after the return address. So we do this manually.
|
||||
* __save_context() will then save the remaining registers, then store the stack
|
||||
* pointer in the thread's thread_t.
|
||||
*
|
||||
* At this point, the thread context is properly saved. sched_run (possibly) changes
|
||||
* the currently active thread, which __restore_context() then restores, resuming
|
||||
* execution at the call site using reti.
|
||||
*
|
||||
*/
|
||||
__attribute__((naked)) void thread_yield_higher(void)
|
||||
void thread_yield_higher(void)
|
||||
{
|
||||
__asm__("push r2"); /* save SR */
|
||||
irq_disable();
|
||||
if (irq_is_in()) {
|
||||
sched_context_switch_request = 1;
|
||||
}
|
||||
else {
|
||||
__asm__ volatile (
|
||||
"push r2" "\n\t" /* save SR */
|
||||
"dint" "\n\t" /* reti will restore SR, and thus, IRQ state */
|
||||
"nop" "\n\t" /* dint takes an additional CPU cycle to take into effect */
|
||||
: /* no outputs */
|
||||
: /* no inputs */
|
||||
: /* no clobbers */
|
||||
);
|
||||
|
||||
__save_context();
|
||||
__save_context();
|
||||
|
||||
/* have sched_active_thread point to the next thread */
|
||||
sched_run();
|
||||
/* have sched_active_thread point to the next thread */
|
||||
sched_run();
|
||||
|
||||
__restore_context();
|
||||
__restore_context();
|
||||
|
||||
UNREACHABLE();
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/* This function calculates the ISR_usage */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user