]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CR5/portASM.S
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CR5 / portASM.S
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 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         /* Hardware registers. */\r
36         .extern ulICCIAR\r
37         .extern ulICCEOIR\r
38         .extern ulICCPMR\r
39 \r
40         /* Variables and functions. */\r
41         .extern ulMaxAPIPriorityMask\r
42         .extern _freertos_vector_table\r
43         .extern pxCurrentTCB\r
44         .extern vTaskSwitchContext\r
45         .extern vApplicationIRQHandler\r
46         .extern ulPortInterruptNesting\r
47         .extern ulPortTaskHasFPUContext\r
48 \r
49         .global FreeRTOS_IRQ_Handler\r
50         .global FreeRTOS_SWI_Handler\r
51         .global vPortRestoreTaskContext\r
52 \r
53 .macro portSAVE_CONTEXT\r
54 \r
55         /* Save the LR and SPSR onto the system mode stack before switching to\r
56         system mode to save the remaining system mode registers. */\r
57         SRSDB   sp!, #SYS_MODE\r
58         CPS             #SYS_MODE\r
59         PUSH    {R0-R12, R14}\r
60 \r
61         /* Push the critical nesting count. */\r
62         LDR             R2, ulCriticalNestingConst\r
63         LDR             R1, [R2]\r
64         PUSH    {R1}\r
65 \r
66         /* Does the task have a floating point context that needs saving?  If\r
67         ulPortTaskHasFPUContext is 0 then no. */\r
68         LDR             R2, ulPortTaskHasFPUContextConst\r
69         LDR             R3, [R2]\r
70         CMP             R3, #0\r
71 \r
72         /* Save the floating point context, if any. */\r
73         FMRXNE  R1,  FPSCR\r
74         VPUSHNE {D0-D15}\r
75         /*VPUSHNE       {D16-D31}*/\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         /*VPOPNE        {D16-D31}*/\r
107         VPOPNE  {D0-D15}\r
108         VMSRNE  FPSCR, R0\r
109 \r
110         /* Restore the critical section nesting depth. */\r
111         LDR             R0, ulCriticalNestingConst\r
112         POP             {R1}\r
113         STR             R1, [R0]\r
114 \r
115         /* Ensure the priority mask is correct for the critical nesting depth. */\r
116         LDR             R2, ulICCPMRConst\r
117         LDR             R2, [R2]\r
118         CMP             R1, #0\r
119         MOVEQ   R4, #255\r
120         LDRNE   R4, ulMaxAPIPriorityMaskConst\r
121         LDRNE   R4, [R4]\r
122         STR             R4, [R2]\r
123 \r
124         /* Restore all system mode registers other than the SP (which is already\r
125         being used). */\r
126         POP             {R0-R12, R14}\r
127 \r
128         /* Return to the task code, loading CPSR on the way. */\r
129         RFEIA   sp!\r
130 \r
131         .endm\r
132 \r
133 \r
134 \r
135 \r
136 /******************************************************************************\r
137  * SVC handler is used to start the scheduler.\r
138  *****************************************************************************/\r
139 .align 4\r
140 .type FreeRTOS_SWI_Handler, %function\r
141 FreeRTOS_SWI_Handler:\r
142         /* Save the context of the current task and select a new task to run. */\r
143         portSAVE_CONTEXT\r
144         LDR R0, vTaskSwitchContextConst\r
145         BLX     R0\r
146         portRESTORE_CONTEXT\r
147 \r
148 \r
149 /******************************************************************************\r
150  * vPortRestoreTaskContext is used to start the scheduler.\r
151  *****************************************************************************/\r
152 .type vPortRestoreTaskContext, %function\r
153 vPortRestoreTaskContext:\r
154         /* Switch to system mode. */\r
155         CPS             #SYS_MODE\r
156         portRESTORE_CONTEXT\r
157 \r
158 .align 4\r
159 .type FreeRTOS_IRQ_Handler, %function\r
160 FreeRTOS_IRQ_Handler:\r
161 \r
162         /* Return to the interrupted instruction. */\r
163         SUB             lr, lr, #4\r
164 \r
165         /* Push the return address and SPSR. */\r
166         PUSH    {lr}\r
167         MRS             lr, SPSR\r
168         PUSH    {lr}\r
169 \r
170         /* Change to supervisor mode to allow reentry. */\r
171         CPS             #SVC_MODE\r
172 \r
173         /* Push used registers. */\r
174         PUSH    {r0-r4, r12}\r
175 \r
176         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
177         for future use.  r1 holds the original ulPortInterruptNesting value for\r
178         future use. */\r
179         LDR             r3, ulPortInterruptNestingConst\r
180         LDR             r1, [r3]\r
181         ADD             r4, r1, #1\r
182         STR             r4, [r3]\r
183 \r
184         /* Read value from the interrupt acknowledge register, which is stored in r0\r
185         for future parameter and interrupt clearing use. */\r
186         LDR     r2, ulICCIARConst\r
187         LDR             r2, [r2]\r
188         LDR             r0, [r2]\r
189 \r
190         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
191         future use.  _RB_ Is this ever needed provided the start of the stack is\r
192         alligned on an 8-byte boundary? */\r
193         MOV             r2, sp\r
194         AND             r2, r2, #4\r
195         SUB             sp, sp, r2\r
196 \r
197         /* Call the interrupt handler. */\r
198         PUSH    {r0-r4, lr}\r
199         LDR             r1, vApplicationIRQHandlerConst\r
200         BLX             r1\r
201         POP             {r0-r4, lr}\r
202         ADD             sp, sp, r2\r
203 \r
204         CPSID   i\r
205         DSB\r
206         ISB\r
207 \r
208         /* Write the value read from ICCIAR to ICCEOIR. */\r
209         LDR     r4, ulICCEOIRConst\r
210         LDR             r4, [r4]\r
211         STR             r0, [r4]\r
212 \r
213         /* Restore the old nesting count. */\r
214         STR             r1, [r3]\r
215 \r
216         /* A context switch is never performed if the nesting count is not 0. */\r
217         CMP             r1, #0\r
218         BNE             exit_without_switch\r
219 \r
220         /* Did the interrupt request a context switch?  r1 holds the address of\r
221         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
222         use. */\r
223         LDR             r1, =ulPortYieldRequired\r
224         LDR             r0, [r1]\r
225         CMP             r0, #0\r
226         BNE             switch_before_exit\r
227 \r
228 exit_without_switch:\r
229         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
230         returning. */\r
231         POP             {r0-r4, r12}\r
232         CPS             #IRQ_MODE\r
233         POP             {LR}\r
234         MSR             SPSR_cxsf, LR\r
235         POP             {LR}\r
236         MOVS    PC, LR\r
237 \r
238 switch_before_exit:\r
239         /* A context swtich is to be performed.  Clear the context switch pending\r
240         flag. */\r
241         MOV             r0, #0\r
242         STR             r0, [r1]\r
243 \r
244         /* Restore used registers, LR-irq and SPSR before saving the context\r
245         to the task stack. */\r
246         POP             {r0-r4, r12}\r
247         CPS             #IRQ_MODE\r
248         POP             {LR}\r
249         MSR             SPSR_cxsf, LR\r
250         POP             {LR}\r
251         portSAVE_CONTEXT\r
252 \r
253         /* Call the function that selects the new task to execute.\r
254         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
255         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
256         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
257         LDR             R0, vTaskSwitchContextConst\r
258         BLX             R0\r
259 \r
260         /* Restore the context of, and branch to, the task selected to execute\r
261         next. */\r
262         portRESTORE_CONTEXT\r
263 \r
264 ulICCIARConst:  .word ulICCIAR\r
265 ulICCEOIRConst: .word ulICCEOIR\r
266 ulICCPMRConst: .word ulICCPMR\r
267 pxCurrentTCBConst: .word pxCurrentTCB\r
268 ulCriticalNestingConst: .word ulCriticalNesting\r
269 ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext\r
270 ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask\r
271 vTaskSwitchContextConst: .word vTaskSwitchContext\r
272 vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
273 ulPortInterruptNestingConst: .word ulPortInterruptNesting\r
274 \r
275 .end\r
276 \r
277 \r
278 \r
279 \r
280 \r