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