1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/arm7_common/common.s

164 lines
3.9 KiB
ArmAsm

/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/* GCC ARM assembler */
.text
.code 32
.align 4 /* 0 */
/* Constants */
.equ USERMODE, 0x10
.equ FIQMODE, 0x11
.equ IRQMODE, 0x12
.equ SVCMODE, 0x13
.equ ABORTMODE, 0x17
.equ UNDEFMODE, 0x1b
.equ SYSTEMMODE, 0x1f
.equ MODEMASK, 0x1f
.equ NOINT, 0xc0 /* Disable both IRQ & FIR */
.equ TBIT, 0x20
.equ IRQMASK, 0x80
.equ FIQMASK, 0x40
/* External references */
.extern sched_active_thread
.extern sched_context_switch_request
.extern sched_run
/* Public functions declared in this file */
.global arm_irq_handler
.global cpu_switch_context_exit
.global task_return
.global ctx_switch
ctx_switch:
/* Save return address on stack */
stmfd sp!, {lr}
/* disable interrupts */
mov lr, #NOINT|SVCMODE
msr CPSR_c, lr
ctx_switch2:
/* get stack pointer from user mode into lr */
stmfd sp, {sp}^
sub sp, sp, #4
ldmfd sp!, {lr}
/* save registers on user mode stack pointed to by lr */
stmfd lr, {r0-r14}^
sub lr, lr, #60
/* restore saved return address from stack */
ldmfd sp!, {r1}
/* get spsr into register */
mrs r0, spsr
/* store return address and spsr on user mode stack */
stmfd lr!, {r0, r1}
/* save user mode stack pointer in *sched_active_thread */
ldr r1, =sched_active_thread /* r1 = &sched_active_thread */
ldr r1, [r1] /* r1 = *r1 = sched_active_thread */
str lr, [r1] /* store stack pointer in tasks tcb*/
/* now the calling task has all its registers saved on its stack and it's SP is saved in its tcb */
/* call scheduler so sched_active_thread points to the next task */
bl sched_run
b task_return
/* never coming back */
cpu_switch_context_exit:
mov r0, #NOINT|SVCMODE
msr cpsr, r0
/* call scheduler so sched_active_thread points to the next task */
bl sched_run
/* continue in task_return: */
task_return:
/* load tcb->stackpointer in r0 */
ldr r0, =sched_active_thread /* r0 = &sched_active_thread */
ldr r0, [r0] /* r0 = *r0 = sched_active_thread */
ldr r0, [r0]
/* restore saved spsr and return address from tasks stack */
ldmfd r0!, {r1,lr}
msr SPSR, r1
/* Restore all registers, PC & cpsr */
ldmfd r0, {r0-lr}^
/* According to ARM Architecture Reference Manual DDI 0100I,
* ldms which affect banked registers must be followed by a nop.
*/
nop
/* return to task */
movs pc, lr
/*----------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
arm_irq_handler:
sub lr, lr, #4
/* save interrupted tasks PC onto stack */
stmfd sp!, {lr}
/* save all registers on isr stack */
stmfd sp!, {r0-r12}
/* save spsr on stack */
MRS R0, SPSR
STMFD SP!, {R0}
MRS R1, CPSR
MSR SPSR, R1
/* jump into vic interrupt */
mov r0, #0xffffff00 /* lpc23xx */
ldr r0, [r0]
add lr,pc,#4
mov pc, r0
/* restore spsr from stack */
LDMFD SP!, {R0}
MSR SPSR, R0
/* check if context switch was requested by irq */
ldr r0, =sched_context_switch_request
ldr r0, [r0]
cmp r0, #0x00
bne switch_context_int
exit_irq_int:
/* recover general purpose registers */
ldmfd sp!, {r0-r12}
/* recover tasks PC into lr */
ldmfd sp!, {lr}
/* now jump back into task */
movs pc, lr
switch_context_int:
/* recover general purpose registers */
ldmfd sp!, {r0-r12}
b ctx_switch2