1/*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2009-01-20     Bernard      first version
9 */
10
11NOINT   EQU     0xc0    ; disable interrupt in psr
12
13    AREA |.text|, CODE, READONLY, ALIGN=2
14    ARM
15    REQUIRE8
16    PRESERVE8
17
18;/*
19; * rt_base_t rt_hw_interrupt_disable();
20; */
21rt_hw_interrupt_disable PROC
22    EXPORT rt_hw_interrupt_disable
23    MRS r0, cpsr
24    ORR r1, r0, #NOINT
25    MSR cpsr_c, r1
26    BX  lr
27    ENDP
28
29;/*
30; * void rt_hw_interrupt_enable(rt_base_t level);
31; */
32rt_hw_interrupt_enable  PROC
33    EXPORT rt_hw_interrupt_enable
34    MSR cpsr_c, r0
35    BX  lr
36    ENDP
37
38;/*
39; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
40; * r0 --> from
41; * r1 --> to
42; */
43rt_hw_context_switch    PROC
44    EXPORT rt_hw_context_switch
45    STMFD   sp!, {lr}           ; push pc (lr should be pushed in place of PC)
46    STMFD   sp!, {r0-r12, lr}   ; push lr & register file
47
48    MRS     r4, cpsr
49    STMFD   sp!, {r4}           ; push cpsr
50    MRS     r4, spsr
51    STMFD   sp!, {r4}           ; push spsr
52
53    STR sp, [r0]                ; store sp in preempted tasks TCB
54    LDR sp, [r1]                ; get new task stack pointer
55
56    LDMFD   sp!, {r4}           ; pop new task spsr
57    MSR spsr_cxsf, r4
58    LDMFD   sp!, {r4}           ; pop new task cpsr
59    MSR cpsr_cxsf, r4
60
61    LDMFD   sp!, {r0-r12, lr, pc}   ; pop new task r0-r12, lr & pc
62    ENDP
63
64;/*
65; * void rt_hw_context_switch_to(rt_uint32 to);
66; * r0 --> to
67; */
68rt_hw_context_switch_to PROC
69    EXPORT rt_hw_context_switch_to
70    LDR sp, [r0]                ; get new task stack pointer
71
72    LDMFD   sp!, {r4}           ; pop new task spsr
73    MSR spsr_cxsf, r4
74    LDMFD   sp!, {r4}           ; pop new task cpsr
75    MSR cpsr_cxsf, r4
76
77    LDMFD   sp!, {r0-r12, lr, pc}   ; pop new task r0-r12, lr & pc
78    ENDP
79
80;/*
81; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
82; */
83    IMPORT rt_thread_switch_interrupt_flag
84    IMPORT rt_interrupt_from_thread
85    IMPORT rt_interrupt_to_thread
86
87rt_hw_context_switch_interrupt  PROC
88    EXPORT rt_hw_context_switch_interrupt
89    LDR r2, =rt_thread_switch_interrupt_flag
90    LDR r3, [r2]
91    CMP r3, #1
92    BEQ _reswitch
93    MOV r3, #1                          ; set rt_thread_switch_interrupt_flag to 1
94    STR r3, [r2]
95    LDR r2, =rt_interrupt_from_thread   ; set rt_interrupt_from_thread
96    STR r0, [r2]
97_reswitch
98    LDR r2, =rt_interrupt_to_thread     ; set rt_interrupt_to_thread
99    STR r1, [r2]
100    BX  lr
101    ENDP
102
103    END
104