xref: /nrf52832-nimble/rt-thread/libcpu/arm/cortex-m0/context_rvds.S (revision 104654410c56c573564690304ae786df310c91fc)
1;/*
2; * Copyright (c) 2006-2018, RT-Thread Development Team
3; *
4; * SPDX-License-Identifier: Apache-2.0
5; *
6; * Change Logs:
7; * Date           Author       Notes
8; * 2010-01-25     Bernard      first version
9; * 2012-06-01     aozima       set pendsv priority to 0xFF.
10; * 2012-08-17     aozima       fixed bug: store r8 - r11.
11; * 2013-06-18     aozima       add restore MSP feature.
12; */
13
14;/**
15; * @addtogroup CORTEX-M0
16; */
17;/*@{*/
18
19SCB_VTOR        EQU     0xE000ED08               ; Vector Table Offset Register
20NVIC_INT_CTRL   EQU     0xE000ED04               ; interrupt control state register
21NVIC_SHPR3      EQU     0xE000ED20               ; system priority register (2)
22NVIC_PENDSV_PRI EQU     0x00FF0000               ; PendSV priority value (lowest)
23NVIC_PENDSVSET  EQU     0x10000000               ; value to trigger PendSV exception
24
25    AREA |.text|, CODE, READONLY, ALIGN=2
26    THUMB
27    REQUIRE8
28    PRESERVE8
29
30    IMPORT rt_thread_switch_interrupt_flag
31    IMPORT rt_interrupt_from_thread
32    IMPORT rt_interrupt_to_thread
33
34;/*
35; * rt_base_t rt_hw_interrupt_disable();
36; */
37rt_hw_interrupt_disable    PROC
38    EXPORT  rt_hw_interrupt_disable
39    MRS     r0, PRIMASK
40    CPSID   I
41    BX      LR
42    ENDP
43
44;/*
45; * void rt_hw_interrupt_enable(rt_base_t level);
46; */
47rt_hw_interrupt_enable    PROC
48    EXPORT  rt_hw_interrupt_enable
49    MSR		PRIMASK, r0
50    BX		LR
51    ENDP
52
53;/*
54; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
55; * r0 --> from
56; * r1 --> to
57; */
58rt_hw_context_switch_interrupt
59    EXPORT rt_hw_context_switch_interrupt
60rt_hw_context_switch    PROC
61    EXPORT rt_hw_context_switch
62
63    ; set rt_thread_switch_interrupt_flag to 1
64    LDR     r2, =rt_thread_switch_interrupt_flag
65    LDR     r3, [r2]
66    CMP     r3, #1
67    BEQ     _reswitch
68    MOVS    r3, #0x01
69    STR     r3, [r2]
70
71    LDR     r2, =rt_interrupt_from_thread   ; set rt_interrupt_from_thread
72    STR     r0, [r2]
73
74_reswitch
75    LDR     r2, =rt_interrupt_to_thread     ; set rt_interrupt_to_thread
76    STR     r1, [r2]
77
78    LDR     r0, =NVIC_INT_CTRL              ; trigger the PendSV exception (causes context switch)
79    LDR     r1, =NVIC_PENDSVSET
80    STR     r1, [r0]
81    BX      LR
82    ENDP
83
84; r0 --> switch from thread stack
85; r1 --> switch to thread stack
86; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
87PendSV_Handler    PROC
88    EXPORT PendSV_Handler
89
90    ; disable interrupt to protect context switch
91    MRS     r2, PRIMASK
92    CPSID   I
93
94    ; get rt_thread_switch_interrupt_flag
95    LDR     r0, =rt_thread_switch_interrupt_flag
96    LDR     r1, [r0]
97    CMP     r1, #0x00
98    BEQ     pendsv_exit                ; pendsv already handled
99
100    ; clear rt_thread_switch_interrupt_flag to 0
101    MOVS    r1, #0x00
102    STR     r1, [r0]
103
104    LDR     r0, =rt_interrupt_from_thread
105    LDR     r1, [r0]
106    CMP     r1, #0x00
107    BEQ     switch_to_thread        ; skip register save at the first time
108
109    MRS     r1, psp                 ; get from thread stack pointer
110
111    SUBS    r1, r1, #0x20           ; space for {r4 - r7} and {r8 - r11}
112    LDR     r0, [r0]
113    STR     r1, [r0]                ; update from thread stack pointer
114
115    STMIA   r1!, {r4 - r7}          ; push thread {r4 - r7} register to thread stack
116
117    MOV     r4, r8                  ; mov thread {r8 - r11} to {r4 - r7}
118    MOV     r5, r9
119    MOV     r6, r10
120    MOV     r7, r11
121    STMIA   r1!, {r4 - r7}          ; push thread {r8 - r11} high register to thread stack
122
123switch_to_thread
124    LDR     r1, =rt_interrupt_to_thread
125    LDR     r1, [r1]
126    LDR     r1, [r1]                ; load thread stack pointer
127
128    LDMIA   r1!, {r4 - r7}          ; pop thread {r4 - r7} register from thread stack
129    PUSH    {r4 - r7}               ; push {r4 - r7} to MSP for copy {r8 - r11}
130
131    LDMIA   r1!, {r4 - r7}          ; pop thread {r8 - r11} high register from thread stack to {r4 - r7}
132    MOV     r8,  r4                 ; mov {r4 - r7} to {r8 - r11}
133    MOV     r9,  r5
134    MOV     r10, r6
135    MOV     r11, r7
136
137    POP     {r4 - r7}               ; pop {r4 - r7} from MSP
138
139    MSR     psp, r1                 ; update stack pointer
140
141pendsv_exit
142    ; restore interrupt
143    MSR     PRIMASK, r2
144
145    MOVS    r0, #0x04
146    RSBS    r0, r0, #0x00
147    BX      r0
148    ENDP
149
150;/*
151; * void rt_hw_context_switch_to(rt_uint32 to);
152; * r0 --> to
153; * this fucntion is used to perform the first thread switch
154; */
155rt_hw_context_switch_to    PROC
156    EXPORT rt_hw_context_switch_to
157    ; set to thread
158    LDR     r1, =rt_interrupt_to_thread
159    STR     r0, [r1]
160
161    ; set from thread to 0
162    LDR     r1, =rt_interrupt_from_thread
163    MOVS    r0, #0x0
164    STR     r0, [r1]
165
166    ; set interrupt flag to 1
167    LDR     r1, =rt_thread_switch_interrupt_flag
168    MOVS    r0, #1
169    STR     r0, [r1]
170
171    ; set the PendSV exception priority
172    LDR     r0, =NVIC_SHPR3
173    LDR     r1, =NVIC_PENDSV_PRI
174    LDR     r2, [r0,#0x00]       ; read
175    ORRS    r1,r1,r2             ; modify
176    STR     r1, [r0]             ; write-back
177
178    ; trigger the PendSV exception (causes context switch)
179    LDR     r0, =NVIC_INT_CTRL
180    LDR     r1, =NVIC_PENDSVSET
181    STR     r1, [r0]
182
183    ; restore MSP
184    LDR     r0, =SCB_VTOR
185    LDR     r0, [r0]
186    LDR     r0, [r0]
187    MSR     msp, r0
188
189    ; enable interrupts at processor level
190    CPSIE   I
191
192    ; never reach here!
193    ENDP
194
195; compatible with old version
196rt_hw_interrupt_thread_switch PROC
197    EXPORT rt_hw_interrupt_thread_switch
198    BX      lr
199    ENDP
200
201    IMPORT rt_hw_hard_fault_exception
202
203HardFault_Handler    PROC
204    EXPORT HardFault_Handler
205
206    ; get current context
207    MRS     r0, psp                 ; get fault thread stack pointer
208    PUSH    {lr}
209    BL      rt_hw_hard_fault_exception
210    POP     {pc}
211    ENDP
212
213    ALIGN   4
214
215    END
216