X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Farm%2Fhw%2Fswitch_ctx_arm.S;h=db4f297ff71e93c7d3157e2591546131bbecb877;hb=57fa5e371a8b40afc99b922731b77d17c55330a4;hp=bde843cda734cd14ed7066fcb69dfa096dc2c4b2;hpb=71743c2a5a8bf9dbf66a945fd9656baed0d16329;p=bertos.git diff --git a/bertos/cpu/arm/hw/switch_ctx_arm.S b/bertos/cpu/arm/hw/switch_ctx_arm.S index bde843cd..db4f297f 100644 --- a/bertos/cpu/arm/hw/switch_ctx_arm.S +++ b/bertos/cpu/arm/hw/switch_ctx_arm.S @@ -32,22 +32,68 @@ * * \brief ARM context switch * - * \version $Id: proc.c 18271 2007-10-11 14:51:31Z batt $ * * \author Stefano Fedrigo * \author Francesco Sacchi + * \author Andrea Righi */ +#include "cfg/cfg_proc.h" + /* void asm_switch_context(void **new_sp [r0], void **save_sp [r1]) */ .globl asm_switch_context asm_switch_context: - mrs r2, cpsr /* Save status. */ - stmfd sp!, {r2, r4-r11, lr} /* Save registers. */ + /* Save registers */ + stmfd sp!, {r4 - r11, lr} + /* Save old stack pointer */ + str sp, [r1] + /* Load new stack pointer */ + ldr sp, [r0] + /* Load new registers */ + ldmfd sp!, {r4 - r11, pc} + +#if CONFIG_KERN_PREEMPT + +/* ARM interrupt mode with IRQ and FIQ disabled */ +#define ARM_IRQ_MODE 0xD2 +/* ARM supervisor mode with IRQ and FIQ disabled */ +#define ARM_SVC_MODE 0xD3 + +.globl asm_irq_switch_context +asm_irq_switch_context: + /* Return if preemption is not needed */ + bl proc_needPreempt + cmp r0, #0 + ldmeqfd sp!, {r0 - r3, ip, pc}^ + + /* Otherwise restore regs used by the ISR */ + ldmfd sp!, {r0 - r3, ip, lr} + + /* Save current process context */ + msr cpsr_c, #ARM_SVC_MODE + stmfd sp!, {r0 - r3, ip, lr} + + /* Save lr_irq and spsr_irq in process stack */ + msr cpsr_c, #ARM_IRQ_MODE + mov r0, lr + mrs r1, spsr + msr cpsr_c, #ARM_SVC_MODE + stmfd sp!, {r0, r1} + + /* Perform the context switch */ + bl proc_preempt - str sp, [r1] /* Save old stack pointer. */ - ldr sp, [r0] /* Load new stack pointer */ + /* Restore lr_irq and spsr_irq from process stack */ + ldmfd sp!, {r0, r1} + msr cpsr_c, #ARM_IRQ_MODE + mov lr, r0 + msr spsr_cxsf, r1 - ldmfd sp!, {r2, r4-r11, lr} /* Load new registers. */ - msr cpsr, r2 /* restore flags reg. */ + /* Restore process regs */ + msr cpsr_c, #ARM_SVC_MODE + ldmfd sp!, {r0 - r3, ip, lr} - mov pc, lr + /* Exit from ISR */ + msr cpsr_c, #ARM_IRQ_MODE + movs pc, lr +#endif /* CONFIG_KERN_PREEMPT */