]> begriffs open source - cmsis-freertos/blob - Source/portable/GCC/ARM_CRx_No_GIC/portASM.S
Updated pack to FreeRTOS 10.4.6
[cmsis-freertos] / Source / portable / GCC / ARM_CRx_No_GIC / portASM.S
1 /*
2  * FreeRTOS Kernel V10.4.6
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29         .text
30         .arm
31
32         .set SYS_MODE,  0x1f
33         .set SVC_MODE,  0x13
34         .set IRQ_MODE,  0x12
35
36         /* Variables and functions. */
37         .extern ulMaxAPIPriorityMask
38         .extern _freertos_vector_table
39         .extern pxCurrentTCB
40         .extern vTaskSwitchContext
41         .extern vApplicationIRQHandler
42         .extern ulPortInterruptNesting
43         .extern ulPortTaskHasFPUContext
44         .extern ulICCEOIR
45         .extern ulPortYieldRequired
46
47         .global FreeRTOS_IRQ_Handler
48         .global FreeRTOS_SVC_Handler
49         .global vPortRestoreTaskContext
50
51
52 .macro portSAVE_CONTEXT
53
54         /* Save the LR and SPSR onto the system mode stack before switching to
55         system mode to save the remaining system mode registers. */
56         SRSDB   sp!, #SYS_MODE
57         CPS             #SYS_MODE
58         PUSH    {R0-R12, R14}
59
60         /* Push the critical nesting count. */
61         LDR             R2, ulCriticalNestingConst
62         LDR             R1, [R2]
63         PUSH    {R1}
64
65         /* Does the task have a floating point context that needs saving?  If
66         ulPortTaskHasFPUContext is 0 then no. */
67         LDR             R2, ulPortTaskHasFPUContextConst
68         LDR             R3, [R2]
69         CMP             R3, #0
70
71         /* Save the floating point context, if any. */
72         FMRXNE  R1,  FPSCR
73         VPUSHNE {D0-D15}
74 #if configFPU_D32 == 1
75         VPUSHNE {D16-D31}
76 #endif /* configFPU_D32 */
77         PUSHNE  {R1}
78
79         /* Save ulPortTaskHasFPUContext itself. */
80         PUSH    {R3}
81
82         /* Save the stack pointer in the TCB. */
83         LDR             R0, pxCurrentTCBConst
84         LDR             R1, [R0]
85         STR             SP, [R1]
86
87         .endm
88
89 ; /**********************************************************************/
90
91 .macro portRESTORE_CONTEXT
92
93         /* Set the SP to point to the stack of the task being restored. */
94         LDR             R0, pxCurrentTCBConst
95         LDR             R1, [R0]
96         LDR             SP, [R1]
97
98         /* Is there a floating point context to restore?  If the restored
99         ulPortTaskHasFPUContext is zero then no. */
100         LDR             R0, ulPortTaskHasFPUContextConst
101         POP             {R1}
102         STR             R1, [R0]
103         CMP             R1, #0
104
105         /* Restore the floating point context, if any. */
106         POPNE   {R0}
107 #if configFPU_D32 == 1
108         VPOPNE  {D16-D31}
109 #endif /* configFPU_D32 */
110         VPOPNE  {D0-D15}
111         VMSRNE  FPSCR, R0
112
113         /* Restore the critical section nesting depth. */
114         LDR             R0, ulCriticalNestingConst
115         POP             {R1}
116         STR             R1, [R0]
117
118         /* Restore all system mode registers other than the SP (which is already
119         being used). */
120         POP             {R0-R12, R14}
121
122         /* Return to the task code, loading CPSR on the way. */
123         RFEIA   sp!
124
125         .endm
126
127
128
129
130 /******************************************************************************
131  * SVC handler is used to yield.
132  *****************************************************************************/
133 .align 4
134 .type FreeRTOS_SVC_Handler, %function
135 FreeRTOS_SVC_Handler:
136         /* Save the context of the current task and select a new task to run. */
137         portSAVE_CONTEXT
138         LDR R0, vTaskSwitchContextConst
139         BLX     R0
140         portRESTORE_CONTEXT
141
142
143 /******************************************************************************
144  * vPortRestoreTaskContext is used to start the scheduler.
145  *****************************************************************************/
146 .align 4
147 .type vPortRestoreTaskContext, %function
148 vPortRestoreTaskContext:
149         /* Switch to system mode. */
150         CPS             #SYS_MODE
151         portRESTORE_CONTEXT
152
153 .align 4
154 .type FreeRTOS_IRQ_Handler, %function
155 FreeRTOS_IRQ_Handler:
156         /* Return to the interrupted instruction. */
157         SUB             lr, lr, #4
158
159         /* Push the return address and SPSR. */
160         PUSH    {lr}
161         MRS             lr, SPSR
162         PUSH    {lr}
163
164         /* Change to supervisor mode to allow reentry. */
165         CPS             #0x13
166
167         /* Push used registers. */
168         PUSH    {r0-r3, r12}
169
170         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting
171         for future use.  r1 holds the original ulPortInterruptNesting value for
172         future use. */
173         LDR             r3, ulPortInterruptNestingConst
174         LDR             r1, [r3]
175         ADD             r0, r1, #1
176         STR             r0, [r3]
177
178         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for
179         future use. */
180         MOV             r0, sp
181         AND             r2, r0, #4
182         SUB             sp, sp, r2
183
184         /* Call the interrupt handler. */
185         PUSH    {r0-r3, lr}
186         LDR             r1, vApplicationIRQHandlerConst
187         BLX             r1
188         POP             {r0-r3, lr}
189         ADD             sp, sp, r2
190
191         CPSID   i
192         DSB
193         ISB
194
195         /* Write to the EOI register. */
196         LDR     r0, ulICCEOIRConst
197         LDR             r2, [r0]
198         STR             r0, [r2]
199
200         /* Restore the old nesting count. */
201         STR             r1, [r3]
202
203         /* A context switch is never performed if the nesting count is not 0. */
204         CMP             r1, #0
205         BNE             exit_without_switch
206
207         /* Did the interrupt request a context switch?  r1 holds the address of
208         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
209         use. */
210         LDR             r1, ulPortYieldRequiredConst
211         LDR             r0, [r1]
212         CMP             r0, #0
213         BNE             switch_before_exit
214
215 exit_without_switch:
216         /* No context switch.  Restore used registers, LR_irq and SPSR before
217         returning. */
218         POP             {r0-r3, r12}
219         CPS             #IRQ_MODE
220         POP             {LR}
221         MSR             SPSR_cxsf, LR
222         POP             {LR}
223         MOVS    PC, LR
224
225 switch_before_exit:
226         /* A context swtich is to be performed.  Clear the context switch pending
227         flag. */
228         MOV             r0, #0
229         STR             r0, [r1]
230
231         /* Restore used registers, LR-irq and SPSR before saving the context
232         to the task stack. */
233         POP             {r0-r3, r12}
234         CPS             #IRQ_MODE
235         POP             {LR}
236         MSR             SPSR_cxsf, LR
237         POP             {LR}
238         portSAVE_CONTEXT
239
240         /* Call the function that selects the new task to execute.
241         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
242         instructions, or 8 byte aligned stack allocated data.  LR does not need
243         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
244         LDR             R0, vTaskSwitchContextConst
245         BLX             R0
246
247         /* Restore the context of, and branch to, the task selected to execute
248         next. */
249         portRESTORE_CONTEXT
250
251 ulICCEOIRConst: .word ulICCEOIR
252 pxCurrentTCBConst: .word pxCurrentTCB
253 ulCriticalNestingConst: .word ulCriticalNesting
254 ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
255 vTaskSwitchContextConst: .word vTaskSwitchContext
256 vApplicationIRQHandlerConst: .word vApplicationIRQHandler
257 ulPortInterruptNestingConst: .word ulPortInterruptNesting
258 ulPortYieldRequiredConst: .word ulPortYieldRequired
259
260 .end
261
262
263
264
265