diff --git a/os/common/ports/ARMCMx/chcore_v6m.c b/os/common/ports/ARMCMx/chcore_v6m.c index b68e97eb4..62daff813 100644 --- a/os/common/ports/ARMCMx/chcore_v6m.c +++ b/os/common/ports/ARMCMx/chcore_v6m.c @@ -104,17 +104,18 @@ void PendSV_Handler(void) { /** * @brief IRQ epilogue code. + * + * @param[in] lr value of the @p LR register on ISR entry */ -void _port_irq_epilogue(void) { - struct port_extctx *ctxp; +void _port_irq_epilogue(regarm_t lr) { - port_lock_from_isr(); + if (lr != (regarm_t)0xFFFFFFF1U) { + struct port_extctx *ctxp; - /* 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()) { + port_lock_from_isr(); + + /* The extctx structure is pointed by the PSP register.*/ + ctxp = (struct port_extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ @@ -126,16 +127,21 @@ void _port_irq_epilogue(void) { /* Setting up a fake XPSR register value.*/ ctxp->xpsr = (regarm_t)0x01000000; - /* Return address set to OS code, there context switch will be - performed.*/ - ctxp->pc = (regarm_t)_port_switch_from_isr; + /* 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; + } /* 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 3d640506b..d895f84a8 100644 --- a/os/common/ports/ARMCMx/chcore_v6m.h +++ b/os/common/ports/ARMCMx/chcore_v6m.h @@ -246,14 +246,23 @@ struct port_intctx { * @details This macro must be inserted at the start of all IRQ handlers * enabled to invoke system APIs. */ -#define PORT_IRQ_PROLOGUE() +#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 /** * @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() +#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) /** * @brief IRQ handler function declaration. @@ -298,10 +307,11 @@ struct port_intctx { #ifdef __cplusplus extern "C" { #endif - void _port_irq_epilogue(void); + void _port_irq_epilogue(regarm_t lr); 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 diff --git a/readme.txt b/readme.txt index 7cff28c1c..95c594290 100644 --- a/readme.txt +++ b/readme.txt @@ -161,7 +161,6 @@ - EX: Updated LPS25H to 1.1.0 (backported to 18.2.1). - EX: Updated LSM303DLHC to 1.1.0 (backported to 18.2.1). - HAL: Fixed broken functionality of MFS module (bug #986). -- RT: Fixed GCC6 problem breaks Cortex-M0 port (bug #985). - NIL: Fixed scheduler misbehaving in rare cases (bug #983) (backported to 18.2.2 and 17.6.5). - NIL: Fixed function chThdSuspendTimeoutS() ignoring TIME_IMMEDIATE (bug #982)