X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Farm%2Fhw%2Fswitch.h;fp=bertos%2Fcpu%2Farm%2Fhw%2Fswitch.h;h=9ed15b94220ed7b8358411c0164d177b83b79ea8;hb=345f93de1963f49bdb194d2b06c8c5d7ba0a3e5f;hp=0000000000000000000000000000000000000000;hpb=791e167e053bdd9250d34a9a5ccae6ccde4d6679;p=bertos.git diff --git a/bertos/cpu/arm/hw/switch.h b/bertos/cpu/arm/hw/switch.h new file mode 100644 index 00000000..9ed15b94 --- /dev/null +++ b/bertos/cpu/arm/hw/switch.h @@ -0,0 +1,90 @@ +/** + * \file + * + * + * \brief Kernel scheduler macros. + * + * \version $Id$ + * + * \author Francesco Sacchi + * \author Stefano Fedrigo + */ + +#ifndef CPU_ARM_HW_SWITCH_H +#define CPU_ARM_HW_SWITCH_H + +#include + +/** + * Interrupt entry point. + * Needed because AT91 uses an Interrupt Controller with auto-vectoring. + */ +#define SCHEDULER_IRQ_ENTRY \ + asm volatile("sub lr, lr, #4 \n\t" /* Adjust LR */ \ + "stmfd sp!, {r0} \n\t" /* Save r0 */ \ + "stmfd sp, {sp}^ \n\t" /* Save user SP */ \ + "sub sp, sp, #4 \n\t" /* Decrement irq SP, writeback is illegal */ \ + "ldmfd sp!, {r0} \n\t" /* Restore user SP immedately in r0 */ \ + "stmfd r0!, {lr} \n\t" /* Store system LR in user stack */ \ + "stmfd r0, {r1-r12,lr}^ \n\t" /* Store registers on user stack (user LR too) */ \ + "sub r0, r0, #52 \n\t" /* Decrement r0, writeback is illegal */ \ + "ldmfd sp!, {r1} \n\t" /* Restore r0 */ \ + "stmfd r0!, {r1} \n\t" /* Store r0 in user stack too */ \ + "mrs r1, spsr \n\t" /* Save SPSR... */ \ + "stmfd r0!, {r1} \n\t" /* ... in user stack */ \ + "ldr r1, =CurrentProcess \n\t" /* Load in r1 &CurrentProcess->stack */ \ + "ldr r1, [r1, %0] \n\t" \ + "str r0, [r1] \n\t" /* Store the process SP */ \ + "sub fp, sp, #4 \n\t" /* Store the process SP */ \ + : /* no output */ \ + : "n" (offsetof(Process, stack)) \ + ) + + +#define SCHEDULER_IRQ_EXIT \ + asm volatile("ldr lr, =CurrentProcess \n\t" /* Load &CurrentProcess->stack */ \ + "ldr lr, [lr, %0] \n\t" \ + "ldr lr, [lr] \n\t" /* Load current process SP */ \ + "ldr r0, =0xFFFFF000 \n\t" /* End of interrupt for AT91 */ \ + "str r0, [r0, #0x130] \n\t" /* */ \ + "ldmfd lr!, {r0} \n\t" /* Pop status reg */ \ + "msr spsr, r0 \n\t" /* ... */ \ + "ldmfd lr, {r0-r12,lr}^ \n\t" /* Restore user regs */ \ + "add lr, lr, #56 \n\t" /* 52 + irq link register (extracted below) */ \ + "stmfd sp!, {lr} \n\t" /* Push user stack pointer in irq stack */ \ + "ldmfd sp, {sp}^ \n\t" /* Restore user SP */ \ + "sub sp, sp, #4 \n\t" /* Align irq SP */ \ + "ldmdb lr, {pc}^ \n\t" /* And return to user space (We use ldmdb cause lr is sp+4) */ \ + : /* no output */ \ + : "n" (offsetof(Process, stack)) \ + ) + +#endif /* CPU_ARM_HW_SWITCH_H */