From 3cc5ac6d9a6555ba70ea83c9eb9cae1bb1f44fd9 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 6 Mar 2011 08:02:26 +0000 Subject: Improved preemption for Cortex-M0 port. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2797 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ports/GCC/ARMCMx/chcore_v6m.c | 54 ++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 30 deletions(-) (limited to 'os/ports/GCC/ARMCMx/chcore_v6m.c') diff --git a/os/ports/GCC/ARMCMx/chcore_v6m.c b/os/ports/GCC/ARMCMx/chcore_v6m.c index 4e49e6256..5004b2256 100644 --- a/os/ports/GCC/ARMCMx/chcore_v6m.c +++ b/os/ports/GCC/ARMCMx/chcore_v6m.c @@ -27,11 +27,6 @@ #include "ch.h" -/** - * @brief PC register temporary storage. - */ -regarm_t _port_saved_pc; - /** * @brief System Timer vector. * @details This interrupt is used as system tick. @@ -48,40 +43,39 @@ CH_IRQ_HANDLER(SysTickVector) { CH_IRQ_EPILOGUE(); } +/** + * @brief NMI vector. + * @details The NMI vector is used for exception mode re-entering after a + * context switch. + */ +void NMIVector(void) { + register struct extctx *ctxp; + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory"); + ctxp++; + asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); + port_unlock_from_isr(); +} + /** * @brief Post-IRQ switch code. - * @details On entry the stack and the registers are restored by the exception - * return, the PC value is stored in @p _port_saved_pc, the interrupts - * are disabled. + * @details The switch is performed in thread context then an NMI exception + * is enforced in order to return to the exact point before the + * preemption. */ #if !defined(__DOXYGEN__) __attribute__((naked)) #endif void _port_switch_from_isr(void) { - /* Note, saves r4 to make space for the PC.*/ - asm volatile ("push {r0, r1, r2, r3, r4} \n\t" - "mrs r0, APSR \n\t" - "mov r1, r12 \n\t" - "push {r0, r1, lr} \n\t" - "ldr r0, =_port_saved_pc \n\t" - "ldr r0, [r0] \n\t" - "add r0, r0, #1 \n\t" - "str r0, [sp, #28]" : : : "memory"); chSchDoRescheduleI(); - - /* Note, the last register is restored alone after re-enabling the - interrupts in order to minimize the (very remote and unlikely) - possibility that the stack is filled by continuous and saturating - interrupts that would not allow that last words to be pulled out of - the stack.*/ - asm volatile ("pop {r0, r1, r2} \n\t" - "mov r12, r1 \n\t" - "msr APSR, r0 \n\t" - "mov lr, r2 \n\t" - "pop {r0, r1, r2, r3} \n\t" - "cpsie i \n\t" - "pop {pc}" : : : "memory"); + SCB_ICSR = ICSR_NMIPENDSET; + /* The following loop should never be executed, the NMI will kick in + immediately.*/ + while (TRUE) + ; } #define PUSH_CONTEXT(sp) { \ -- cgit v1.2.3