aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2018-11-15 08:30:03 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2018-11-15 08:30:03 +0000
commit4464b4a0d563ee49842ca11704aaf83e2f0ab991 (patch)
tree779633e5ad7777a101ce9e7717ebea9019fd58f5 /os
parent27ad46cdfdfd3565b0376a96a3068839a3c63250 (diff)
downloadChibiOS-4464b4a0d563ee49842ca11704aaf83e2f0ab991.tar.gz
ChibiOS-4464b4a0d563ee49842ca11704aaf83e2f0ab991.tar.bz2
ChibiOS-4464b4a0d563ee49842ca11704aaf83e2f0ab991.zip
Reverted bug #985.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12423 110e8d01-0319-4d1e-a829-52ad28d1bb01
Diffstat (limited to 'os')
-rw-r--r--os/common/ports/ARMCMx/chcore_v6m.c34
-rw-r--r--os/common/ports/ARMCMx/chcore_v6m.h16
2 files changed, 33 insertions, 17 deletions
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) {
+
+ if (lr != (regarm_t)0xFFFFFFF1U) {
+ struct port_extctx *ctxp;
- port_lock_from_isr();
+ port_lock_from_isr();
- /* 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()) {
+ /* 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