aboutsummaryrefslogtreecommitdiffstats
path: root/os/rt/ports
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-10-16 07:44:08 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-10-16 07:44:08 +0000
commit05fbfd18f87f14d932849f013cea0cdef46a3443 (patch)
treeeedb1359233fbb76677682868bd44d4cc96bac44 /os/rt/ports
parent46c3999c09d2018cfdd96d2de8a10a236016aef2 (diff)
downloadChibiOS-05fbfd18f87f14d932849f013cea0cdef46a3443.tar.gz
ChibiOS-05fbfd18f87f14d932849f013cea0cdef46a3443.tar.bz2
ChibiOS-05fbfd18f87f14d932849f013cea0cdef46a3443.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7403 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/rt/ports')
-rw-r--r--os/rt/ports/ARM/compilers/GCC/chcoreasm.s91
1 files changed, 80 insertions, 11 deletions
diff --git a/os/rt/ports/ARM/compilers/GCC/chcoreasm.s b/os/rt/ports/ARM/compilers/GCC/chcoreasm.s
index 4e3e1f744..01f9434b1 100644
--- a/os/rt/ports/ARM/compilers/GCC/chcoreasm.s
+++ b/os/rt/ports/ARM/compilers/GCC/chcoreasm.s
@@ -147,21 +147,12 @@ _port_switch_arm:
* of a register holding the address of the ISR to be invoked, the ISR
* then returns in the common epilogue code where the context switch will
* be performed, if required.
- * Note that registers are saved in the system stack in order to have the
- * IRQ stack empty if a context switch has to be performed.
*/
.code 32
.func
.global Irq_Handler
Irq_Handler:
- msr CPSR_c, #MODE_SYS | I_BIT
- stmfd sp!, {r0-r3, r12, lr} // Registers on System Stack.
- msr CPSR_c, #MODE_IRQ | I_BIT
- mrs r0, SPSR
- mov r1, lr
- msr CPSR_c, #MODE_SYS | I_BIT
- stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ.
- msr CPSR_c, #MODE_IRQ | I_BIT
+ stmfd sp!, {r0-r3, r12, lr}
#if defined(THUMB_NO_INTERWORKING)
add r0, pc, #1
bx r0
@@ -201,10 +192,89 @@ Irq_Handler:
* Low +------------+
*/
.balign 16
+#if defined(THUMB_NO_INTERWORKING)
+ .code 16
+ .thumb_func
+ .globl _port_irq_common
+_port_irq_common:
+ bl chSchIsPreemptionRequired
+ mov lr, pc
+ bx lr
+ .code 32
+#else /* !defined(THUMB_NO_INTERWORKING) */
.code 32
.func
.globl _port_irq_common
_port_irq_common:
+ bl chSchIsPreemptionRequired
+#endif /* !defined(THUMB_NO_INTERWORKING) */
+ cmp r0, #0
+ ldmeq sp!, {r0-r3, r12, lr}
+ subeqs pc, lr, #4 // No reschedule, returns.
+
+ // Saves the IRQ mode registers in the system stack.
+ stmfd sp!, {r0-r3, r12, lr}
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ mrs r0, SPSR
+ mov r1, lr
+ msr CPSR_c, #MODE_SYS | I_BIT
+ stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ.
+
+ // Context switch.
+#if defined(THUMB_NO_INTERWORKING)
+ add r0, pc, #1
+ bx r0
+ .code 16
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+ mov lr, pc
+ bx lr
+ .code 32
+#else /* !defined(THUMB_NO_INTERWORKING) */
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#endif /* !defined(THUMB_NO_INTERWORKING) */
+
+ // Re-establish the IRQ conditions again.
+ ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ.
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ msr SPSR_fsxc, r0
+ mov lr, r1
+ msr CPSR_c, #MODE_SYS | I_BIT
+ ldmfd sp!, {r0-r3, r12, lr}
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ subs pc, lr, #4
+ .endfunc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
msr CPSR_c, #MODE_SYS | I_BIT
bl chSchIsPreemptionRequired
cmp r0, #0
@@ -225,7 +295,6 @@ noschd:
ldmfd sp!, {r0-r3, r12, lr}
msr CPSR_c, #MODE_IRQ | I_BIT
subs pc, lr, #4
- .endfunc
/*
* Threads trampoline code.