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