xref: /nrf52832-nimble/rt-thread/libcpu/arm/lpc214x/context_rvds.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero;/*
2*10465441SEvalZero; * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero; *
4*10465441SEvalZero; * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero; *
6*10465441SEvalZero; * Change Logs:
7*10465441SEvalZero; * Date           Author       Notes
8*10465441SEvalZero; * 2009-01-20     Bernard      first version
9*10465441SEvalZero; * 2011-07-22     Bernard      added thumb mode porting
10*10465441SEvalZero; */
11*10465441SEvalZero
12*10465441SEvalZeroMode_USR        EQU     0x10
13*10465441SEvalZeroMode_FIQ        EQU     0x11
14*10465441SEvalZeroMode_IRQ        EQU     0x12
15*10465441SEvalZeroMode_SVC        EQU     0x13
16*10465441SEvalZeroMode_ABT        EQU     0x17
17*10465441SEvalZeroMode_UND        EQU     0x1B
18*10465441SEvalZeroMode_SYS        EQU     0x1F
19*10465441SEvalZero
20*10465441SEvalZeroI_Bit           EQU     0x80            ; when I bit is set, IRQ is disabled
21*10465441SEvalZeroF_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled
22*10465441SEvalZero
23*10465441SEvalZeroNOINT	        EQU     0xc0	; disable interrupt in psr
24*10465441SEvalZero
25*10465441SEvalZero	AREA |.text|, CODE, READONLY, ALIGN=2
26*10465441SEvalZero	ARM
27*10465441SEvalZero	REQUIRE8
28*10465441SEvalZero	PRESERVE8
29*10465441SEvalZero
30*10465441SEvalZero;/*
31*10465441SEvalZero; * rt_base_t rt_hw_interrupt_disable();
32*10465441SEvalZero; */
33*10465441SEvalZerort_hw_interrupt_disable	PROC
34*10465441SEvalZero	EXPORT rt_hw_interrupt_disable
35*10465441SEvalZero	MRS r0, cpsr
36*10465441SEvalZero	ORR r1, r0, #NOINT
37*10465441SEvalZero	MSR cpsr_c, r1
38*10465441SEvalZero	BX	lr
39*10465441SEvalZero	ENDP
40*10465441SEvalZero
41*10465441SEvalZero;/*
42*10465441SEvalZero; * void rt_hw_interrupt_enable(rt_base_t level);
43*10465441SEvalZero; */
44*10465441SEvalZerort_hw_interrupt_enable	PROC
45*10465441SEvalZero	EXPORT rt_hw_interrupt_enable
46*10465441SEvalZero	MSR cpsr_c, r0
47*10465441SEvalZero	BX	lr
48*10465441SEvalZero	ENDP
49*10465441SEvalZero
50*10465441SEvalZero;/*
51*10465441SEvalZero; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
52*10465441SEvalZero; * r0 --> from
53*10465441SEvalZero; * r1 --> to
54*10465441SEvalZero; */
55*10465441SEvalZerort_hw_context_switch	PROC
56*10465441SEvalZero	EXPORT rt_hw_context_switch
57*10465441SEvalZero	STMFD	sp!, {lr}			; push pc (lr should be pushed in place of PC)
58*10465441SEvalZero	STMFD	sp!, {r0-r12, lr}	; push lr & register file
59*10465441SEvalZero
60*10465441SEvalZero	MRS		r4, cpsr
61*10465441SEvalZero        TST     lr, #0x01
62*10465441SEvalZero        BEQ     _ARM_MODE
63*10465441SEvalZero        ORR     r4, r4, #0x20           ; it's thumb code
64*10465441SEvalZero_ARM_MODE
65*10465441SEvalZero	STMFD	sp!, {r4}			; push cpsr
66*10465441SEvalZero
67*10465441SEvalZero	STR	sp, [r0]				; store sp in preempted tasks TCB
68*10465441SEvalZero	LDR	sp, [r1]				; get new task stack pointer
69*10465441SEvalZero
70*10465441SEvalZero    LDMFD   sp!, {r4}               ; pop new task cpsr to spsr
71*10465441SEvalZero	MSR	spsr_cxsf, r4
72*10465441SEvalZero    BIC     r4, r4, #0x20           ; must be ARM mode
73*10465441SEvalZero	MSR	cpsr_cxsf, r4
74*10465441SEvalZero
75*10465441SEvalZero    LDMFD   sp!, {r0-r12, lr, pc}^  ; pop new task r0-r12, lr & pc, copy spsr to cpsr
76*10465441SEvalZero	ENDP
77*10465441SEvalZero
78*10465441SEvalZero;/*
79*10465441SEvalZero; * void rt_hw_context_switch_to(rt_uint32 to);
80*10465441SEvalZero; * r0 --> to
81*10465441SEvalZero; */
82*10465441SEvalZerort_hw_context_switch_to	PROC
83*10465441SEvalZero	EXPORT rt_hw_context_switch_to
84*10465441SEvalZero	LDR	sp, [r0]				; get new task stack pointer
85*10465441SEvalZero
86*10465441SEvalZero    LDMFD   sp!, {r4}               ; pop new task cpsr to spsr
87*10465441SEvalZero	MSR	spsr_cxsf, r4
88*10465441SEvalZero    BIC     r4, r4, #0x20           ; must be ARM mode
89*10465441SEvalZero	MSR	cpsr_cxsf, r4
90*10465441SEvalZero
91*10465441SEvalZero    LDMFD   sp!, {r0-r12, lr, pc}^  ; pop new task r0-r12, lr & pc, copy spsr to cpsr
92*10465441SEvalZero	ENDP
93*10465441SEvalZero
94*10465441SEvalZero;/*
95*10465441SEvalZero; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
96*10465441SEvalZero; */
97*10465441SEvalZero	IMPORT rt_thread_switch_interrupt_flag
98*10465441SEvalZero	IMPORT rt_interrupt_from_thread
99*10465441SEvalZero	IMPORT rt_interrupt_to_thread
100*10465441SEvalZero
101*10465441SEvalZerort_hw_context_switch_interrupt	PROC
102*10465441SEvalZero	EXPORT rt_hw_context_switch_interrupt
103*10465441SEvalZero	LDR r2, =rt_thread_switch_interrupt_flag
104*10465441SEvalZero	LDR r3, [r2]
105*10465441SEvalZero	CMP r3, #1
106*10465441SEvalZero	BEQ _reswitch
107*10465441SEvalZero	MOV r3, #1							; set rt_thread_switch_interrupt_flag to 1
108*10465441SEvalZero	STR r3, [r2]
109*10465441SEvalZero	LDR r2, =rt_interrupt_from_thread	; set rt_interrupt_from_thread
110*10465441SEvalZero	STR r0, [r2]
111*10465441SEvalZero_reswitch
112*10465441SEvalZero	LDR r2, =rt_interrupt_to_thread		; set rt_interrupt_to_thread
113*10465441SEvalZero	STR r1, [r2]
114*10465441SEvalZero	BX	lr
115*10465441SEvalZero	ENDP
116*10465441SEvalZero
117*10465441SEvalZero; /*
118*10465441SEvalZero; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
119*10465441SEvalZero; */
120*10465441SEvalZerort_hw_context_switch_interrupt_do	PROC
121*10465441SEvalZero	EXPORT rt_hw_context_switch_interrupt_do
122*10465441SEvalZero	MOV		r1,  #0			; clear flag
123*10465441SEvalZero	STR		r1,  [r0]
124*10465441SEvalZero
125*10465441SEvalZero	LDMFD	sp!, {r0-r12,lr}; reload saved registers
126*10465441SEvalZero	STMFD	sp!, {r0-r3}	; save r0-r3
127*10465441SEvalZero	MOV		r1,  sp
128*10465441SEvalZero	ADD		sp,  sp, #16	; restore sp
129*10465441SEvalZero	SUB		r2,  lr, #4		; save old task's pc to r2
130*10465441SEvalZero
131*10465441SEvalZero	MRS		r3,  spsr		; get cpsr of interrupt thread
132*10465441SEvalZero
133*10465441SEvalZero	; switch to SVC mode and no interrupt
134*10465441SEvalZero	MSR     cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC
135*10465441SEvalZero
136*10465441SEvalZero	STMFD	sp!, {r2}		; push old task's pc
137*10465441SEvalZero	STMFD	sp!, {r4-r12,lr}; push old task's lr,r12-r4
138*10465441SEvalZero	MOV		r4,  r1			; Special optimised code below
139*10465441SEvalZero	MOV		r5,  r3
140*10465441SEvalZero	LDMFD	r4!, {r0-r3}
141*10465441SEvalZero	STMFD	sp!, {r0-r3}	; push old task's r3-r0
142*10465441SEvalZero	STMFD	sp!, {r5}		; push old task's cpsr
143*10465441SEvalZero
144*10465441SEvalZero	LDR		r4,  =rt_interrupt_from_thread
145*10465441SEvalZero	LDR		r5,  [r4]
146*10465441SEvalZero	STR		sp,  [r5]		; store sp in preempted tasks's TCB
147*10465441SEvalZero
148*10465441SEvalZero	LDR		r6,  =rt_interrupt_to_thread
149*10465441SEvalZero	LDR		r6,  [r6]
150*10465441SEvalZero	LDR		sp,  [r6]		; get new task's stack pointer
151*10465441SEvalZero
152*10465441SEvalZero	LDMFD   sp!, {r4}       ; pop new task's cpsr to spsr
153*10465441SEvalZero	MSR		spsr_cxsf, r4
154*10465441SEvalZero	BIC     r4, r4, #0x20   ; must be ARM mode
155*10465441SEvalZero	MSR		cpsr_cxsf, r4
156*10465441SEvalZero
157*10465441SEvalZero	LDMFD   sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr
158*10465441SEvalZero	ENDP
159*10465441SEvalZero
160*10465441SEvalZero	END