From 1d6d312d43a5cceda95705b3a04eb21a5c4cb310 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 13 Nov 2018 10:36:05 +0000 Subject: Tentative fix for bug #985. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12416 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/common/ports/ARMCMx/chcore_v6m.c | 32 ++++++++++++++------------------ os/common/ports/ARMCMx/chcore_v6m.h | 16 +++------------- 2 files changed, 17 insertions(+), 31 deletions(-) (limited to 'os/common/ports/ARMCMx') diff --git a/os/common/ports/ARMCMx/chcore_v6m.c b/os/common/ports/ARMCMx/chcore_v6m.c index 62daff813..5e43cb01a 100644 --- a/os/common/ports/ARMCMx/chcore_v6m.c +++ b/os/common/ports/ARMCMx/chcore_v6m.c @@ -107,15 +107,16 @@ void PendSV_Handler(void) { * * @param[in] lr value of the @p LR register on ISR entry */ -void _port_irq_epilogue(regarm_t lr) { +void _port_irq_epilogue(void) { + struct port_extctx *ctxp; - if (lr != (regarm_t)0xFFFFFFF1U) { - struct port_extctx *ctxp; + port_lock_from_isr(); - port_lock_from_isr(); - - /* The extctx structure is pointed by the PSP register.*/ - ctxp = (struct port_extctx *)__get_PSP(); + /* Checking if the artificial exception return context has already been + added.*/ + ctxp = (struct port_extctx *)__get_PSP(); + if ((ctxp->pc != (regarm_t)_port_switch_from_isr) && + chSchIsPreemptionRequired()) { /* Adding an artificial exception return context, there is no need to populate it fully.*/ @@ -127,21 +128,16 @@ void _port_irq_epilogue(regarm_t lr) { /* Setting up a fake XPSR register value.*/ ctxp->xpsr = (regarm_t)0x01000000; - /* The exit sequence is different depending on if a preemption is - required or not.*/ - if (chSchIsPreemptionRequired()) { - /* Preemption is required we need to enforce a context switch.*/ - ctxp->pc = (regarm_t)_port_switch_from_isr; - } - else { - /* Preemption not required, we just need to exit the exception - atomically.*/ - ctxp->pc = (regarm_t)_port_exit_from_isr; - } + /* Return address set to OS code, there context switch will be + performed.*/ + ctxp->pc = (regarm_t)_port_switch_from_isr; /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ + return; } + + port_unlock_from_isr(); } /** @} */ diff --git a/os/common/ports/ARMCMx/chcore_v6m.h b/os/common/ports/ARMCMx/chcore_v6m.h index d895f84a8..3d640506b 100644 --- a/os/common/ports/ARMCMx/chcore_v6m.h +++ b/os/common/ports/ARMCMx/chcore_v6m.h @@ -246,23 +246,14 @@ struct port_intctx { * @details This macro must be inserted at the start of all IRQ handlers * enabled to invoke system APIs. */ -#if defined(__GNUC__) || defined(__DOXYGEN__) -#define PORT_IRQ_PROLOGUE() \ - regarm_t _saved_lr = (regarm_t)__builtin_return_address(0) -#elif defined(__ICCARM__) -#define PORT_IRQ_PROLOGUE() \ - regarm_t _saved_lr = (regarm_t)__get_LR() -#elif defined(__CC_ARM) -#define PORT_IRQ_PROLOGUE() \ - regarm_t _saved_lr = (regarm_t)__return_address() -#endif +#define PORT_IRQ_PROLOGUE() /** * @brief IRQ epilogue code. * @details This macro must be inserted at the end of all IRQ handlers * enabled to invoke system APIs. */ -#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) +#define PORT_IRQ_EPILOGUE() _port_irq_epilogue() /** * @brief IRQ handler function declaration. @@ -307,11 +298,10 @@ struct port_intctx { #ifdef __cplusplus extern "C" { #endif - void _port_irq_epilogue(regarm_t lr); + void _port_irq_epilogue(void); void _port_switch(thread_t *ntp, thread_t *otp); void _port_thread_start(void); void _port_switch_from_isr(void); - void _port_exit_from_isr(void); #ifdef __cplusplus } #endif -- cgit v1.2.3