]> begriffs open source - freertos/blob - portable/IAR/ARM_CRx_No_GIC/portASM.s
[AUTO][RELEASE]: Bump file header version to "10.5.1"
[freertos] / portable / IAR / ARM_CRx_No_GIC / portASM.s
1 ;/*\r
2 ; * FreeRTOS Kernel V10.5.1\r
3 ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4 ; *\r
5 ; * SPDX-License-Identifier: MIT\r
6 ; *\r
7 ; * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
8 ; * this software and associated documentation files (the "Software"), to deal in\r
9 ; * the Software without restriction, including without limitation the rights to\r
10 ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
11 ; * the Software, and to permit persons to whom the Software is furnished to do so,\r
12 ; * subject to the following conditions:\r
13 ; *\r
14 ; * The above copyright notice and this permission notice shall be included in all\r
15 ; * copies or substantial portions of the Software.\r
16 ; *\r
17 ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18 ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
19 ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
20 ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
21 ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
22 ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
23 ; *\r
24 ; * https://www.FreeRTOS.org\r
25 ; * https://github.com/FreeRTOS\r
26 ; *\r
27 ; */\r
28 \r
29 #include "FreeRTOSConfig.h"\r
30 \r
31         SECTION .text:CODE:ROOT(2)\r
32         arm\r
33 \r
34         /* Variables and functions. */\r
35         EXTERN pxCurrentTCB\r
36         EXTERN vTaskSwitchContext\r
37         EXTERN vApplicationIRQHandler\r
38         EXTERN ulPortInterruptNesting\r
39         EXTERN ulPortTaskHasFPUContext\r
40         EXTERN ulPortYieldRequired\r
41         EXTERN ulCriticalNesting\r
42 \r
43         PUBLIC FreeRTOS_IRQ_Handler\r
44         PUBLIC FreeRTOS_SVC_Handler\r
45         PUBLIC vPortRestoreTaskContext\r
46 \r
47 SYS_MODE                        EQU             0x1f\r
48 SVC_MODE                        EQU             0x13\r
49 IRQ_MODE                        EQU             0x12\r
50 \r
51 portSAVE_CONTEXT MACRO\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, =ulCriticalNesting\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, =ulPortTaskHasFPUContext\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, =pxCurrentTCB\r
83         LDR             R1, [R0]\r
84         STR             SP, [R1]\r
85 \r
86         ENDM\r
87 \r
88 ; /**********************************************************************/\r
89 \r
90 portRESTORE_CONTEXT MACRO\r
91 \r
92         /* Set the SP to point to the stack of the task being restored. */\r
93         LDR             R0, =pxCurrentTCB\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, =ulPortTaskHasFPUContext\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, =ulCriticalNesting\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 FreeRTOS_SVC_Handler:\r
133         /* Save the context of the current task and select a new task to run. */\r
134         portSAVE_CONTEXT\r
135         LDR R0, =vTaskSwitchContext\r
136         BLX     R0\r
137         portRESTORE_CONTEXT\r
138 \r
139 \r
140 /******************************************************************************\r
141  * vPortRestoreTaskContext is used to start the scheduler.\r
142  *****************************************************************************/\r
143 vPortRestoreTaskContext:\r
144         /* Switch to system mode. */\r
145         CPS             #SYS_MODE\r
146         portRESTORE_CONTEXT\r
147 \r
148 FreeRTOS_IRQ_Handler:\r
149         /* Return to the interrupted instruction. */\r
150         SUB             lr, lr, #4\r
151 \r
152         /* Push the return address and SPSR. */\r
153         PUSH    {lr}\r
154         MRS             lr, SPSR\r
155         PUSH    {lr}\r
156 \r
157         /* Change to supervisor mode to allow reentry. */\r
158         CPS             #SVC_MODE\r
159 \r
160         /* Push used registers. */\r
161         PUSH    {r0-r3, r12}\r
162 \r
163         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
164         for future use.  r1 holds the original ulPortInterruptNesting value for\r
165         future use. */\r
166         LDR             r3, =ulPortInterruptNesting\r
167         LDR             r1, [r3]\r
168         ADD             r0, r1, #1\r
169         STR             r0, [r3]\r
170 \r
171         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
172         future use. */\r
173         MOV             r0, sp\r
174         AND             r2, r0, #4\r
175         SUB             sp, sp, r2\r
176 \r
177         /* Call the interrupt handler. */\r
178         PUSH    {r0-r3, lr}\r
179         LDR             r1, =vApplicationIRQHandler\r
180         BLX             r1\r
181         POP             {r0-r3, lr}\r
182         ADD             sp, sp, r2\r
183 \r
184         CPSID   i\r
185         DSB\r
186         ISB\r
187 \r
188         /* Write to the EOI register. */\r
189         LDR     r2, =configEOI_ADDRESS\r
190         STR             r0, [r2]\r
191 \r
192         /* Restore the old nesting count. */\r
193         STR             r1, [r3]\r
194 \r
195         /* A context switch is never performed if the nesting count is not 0. */\r
196         CMP             r1, #0\r
197         BNE             exit_without_switch\r
198 \r
199         /* Did the interrupt request a context switch?  r1 holds the address of\r
200         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
201         use. */\r
202         LDR             r1, =ulPortYieldRequired\r
203         LDR             r0, [r1]\r
204         CMP             r0, #0\r
205         BNE             switch_before_exit\r
206 \r
207 exit_without_switch:\r
208         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
209         returning. */\r
210         POP             {r0-r3, r12}\r
211         CPS             #IRQ_MODE\r
212         POP             {LR}\r
213         MSR             SPSR_cxsf, LR\r
214         POP             {LR}\r
215         MOVS    PC, LR\r
216 \r
217 switch_before_exit:\r
218         /* A context swtich is to be performed.  Clear the context switch pending\r
219         flag. */\r
220         MOV             r0, #0\r
221         STR             r0, [r1]\r
222 \r
223         /* Restore used registers, LR-irq and SPSR before saving the context\r
224         to the task stack. */\r
225         POP             {r0-r3, r12}\r
226         CPS             #IRQ_MODE\r
227         POP             {LR}\r
228         MSR             SPSR_cxsf, LR\r
229         POP             {LR}\r
230         portSAVE_CONTEXT\r
231 \r
232         /* Call the function that selects the new task to execute.\r
233         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
234         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
235         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
236         LDR             R0, =vTaskSwitchContext\r
237         BLX             R0\r
238 \r
239         /* Restore the context of, and branch to, the task selected to execute\r
240         next. */\r
241         portRESTORE_CONTEXT\r
242 \r
243         END\r
244 \r
245 \r
246 \r
247 \r
248 \r