]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/IAR/ARM_CRx_No_GIC/portASM.s
09bf3d83d58440598f490cee1bf7b75b7852c347
[freertos] / FreeRTOS / Source / portable / IAR / ARM_CRx_No_GIC / portASM.s
1 ;/*\r
2 ; * FreeRTOS Kernel V10.0.1\r
3 ; * Copyright (C) 2017 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 #include "FreeRTOSConfig.h"\r
29 \r
30         SECTION .text:CODE:ROOT(2)\r
31         arm\r
32 \r
33         /* Variables and functions. */\r
34         EXTERN pxCurrentTCB\r
35         EXTERN vTaskSwitchContext\r
36         EXTERN vApplicationIRQHandler\r
37         EXTERN ulPortInterruptNesting\r
38         EXTERN ulPortTaskHasFPUContext\r
39         EXTERN ulPortYieldRequired\r
40         EXTERN ulCriticalNesting\r
41 \r
42         PUBLIC FreeRTOS_IRQ_Handler\r
43         PUBLIC FreeRTOS_SVC_Handler\r
44         PUBLIC vPortRestoreTaskContext\r
45 \r
46 SYS_MODE                        EQU             0x1f\r
47 SVC_MODE                        EQU             0x13\r
48 IRQ_MODE                        EQU             0x12\r
49 \r
50 portSAVE_CONTEXT MACRO\r
51 \r
52         /* Save the LR and SPSR onto the system mode stack before switching to\r
53         system mode to save the remaining system mode registers. */\r
54         SRSDB   sp!, #SYS_MODE\r
55         CPS             #SYS_MODE\r
56         PUSH    {R0-R12, R14}\r
57 \r
58         /* Push the critical nesting count. */\r
59         LDR             R2, =ulCriticalNesting\r
60         LDR             R1, [R2]\r
61         PUSH    {R1}\r
62 \r
63         /* Does the task have a floating point context that needs saving?  If\r
64         ulPortTaskHasFPUContext is 0 then no. */\r
65         LDR             R2, =ulPortTaskHasFPUContext\r
66         LDR             R3, [R2]\r
67         CMP             R3, #0\r
68 \r
69         /* Save the floating point context, if any. */\r
70         FMRXNE  R1,  FPSCR\r
71         VPUSHNE {D0-D15}\r
72 #if configFPU_D32 == 1\r
73         VPUSHNE {D16-D31}\r
74 #endif /* configFPU_D32 */\r
75         PUSHNE  {R1}\r
76 \r
77         /* Save ulPortTaskHasFPUContext itself. */\r
78         PUSH    {R3}\r
79 \r
80         /* Save the stack pointer in the TCB. */\r
81         LDR             R0, =pxCurrentTCB\r
82         LDR             R1, [R0]\r
83         STR             SP, [R1]\r
84 \r
85         ENDM\r
86 \r
87 ; /**********************************************************************/\r
88 \r
89 portRESTORE_CONTEXT MACRO\r
90 \r
91         /* Set the SP to point to the stack of the task being restored. */\r
92         LDR             R0, =pxCurrentTCB\r
93         LDR             R1, [R0]\r
94         LDR             SP, [R1]\r
95 \r
96         /* Is there a floating point context to restore?  If the restored\r
97         ulPortTaskHasFPUContext is zero then no. */\r
98         LDR             R0, =ulPortTaskHasFPUContext\r
99         POP             {R1}\r
100         STR             R1, [R0]\r
101         CMP             R1, #0\r
102 \r
103         /* Restore the floating point context, if any. */\r
104         POPNE   {R0}\r
105 #if configFPU_D32 == 1\r
106         VPOPNE  {D16-D31}\r
107 #endif /* configFPU_D32 */\r
108         VPOPNE  {D0-D15}\r
109         VMSRNE  FPSCR, R0\r
110 \r
111         /* Restore the critical section nesting depth. */\r
112         LDR             R0, =ulCriticalNesting\r
113         POP             {R1}\r
114         STR             R1, [R0]\r
115 \r
116         /* Restore all system mode registers other than the SP (which is already\r
117         being used). */\r
118         POP             {R0-R12, R14}\r
119 \r
120         /* Return to the task code, loading CPSR on the way. */\r
121         RFEIA   sp!\r
122 \r
123         ENDM\r
124 \r
125 \r
126 \r
127 \r
128 /******************************************************************************\r
129  * SVC handler is used to yield.\r
130  *****************************************************************************/\r
131 FreeRTOS_SVC_Handler:\r
132         /* Save the context of the current task and select a new task to run. */\r
133         portSAVE_CONTEXT\r
134         LDR R0, =vTaskSwitchContext\r
135         BLX     R0\r
136         portRESTORE_CONTEXT\r
137 \r
138 \r
139 /******************************************************************************\r
140  * vPortRestoreTaskContext is used to start the scheduler.\r
141  *****************************************************************************/\r
142 vPortRestoreTaskContext:\r
143         /* Switch to system mode. */\r
144         CPS             #SYS_MODE\r
145         portRESTORE_CONTEXT\r
146 \r
147 FreeRTOS_IRQ_Handler:\r
148         /* Return to the interrupted instruction. */\r
149         SUB             lr, lr, #4\r
150 \r
151         /* Push the return address and SPSR. */\r
152         PUSH    {lr}\r
153         MRS             lr, SPSR\r
154         PUSH    {lr}\r
155 \r
156         /* Change to supervisor mode to allow reentry. */\r
157         CPS             #SVC_MODE\r
158 \r
159         /* Push used registers. */\r
160         PUSH    {r0-r3, r12}\r
161 \r
162         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
163         for future use.  r1 holds the original ulPortInterruptNesting value for\r
164         future use. */\r
165         LDR             r3, =ulPortInterruptNesting\r
166         LDR             r1, [r3]\r
167         ADD             r0, r1, #1\r
168         STR             r0, [r3]\r
169 \r
170         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
171         future use. */\r
172         MOV             r0, sp\r
173         AND             r2, r0, #4\r
174         SUB             sp, sp, r2\r
175 \r
176         /* Call the interrupt handler. */\r
177         PUSH    {r0-r3, lr}\r
178         LDR             r1, =vApplicationIRQHandler\r
179         BLX             r1\r
180         POP             {r0-r3, lr}\r
181         ADD             sp, sp, r2\r
182 \r
183         CPSID   i\r
184         DSB\r
185         ISB\r
186 \r
187         /* Write to the EOI register. */\r
188         LDR     r2, =configEOI_ADDRESS\r
189         STR             r0, [r2]\r
190 \r
191         /* Restore the old nesting count. */\r
192         STR             r1, [r3]\r
193 \r
194         /* A context switch is never performed if the nesting count is not 0. */\r
195         CMP             r1, #0\r
196         BNE             exit_without_switch\r
197 \r
198         /* Did the interrupt request a context switch?  r1 holds the address of\r
199         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
200         use. */\r
201         LDR             r1, =ulPortYieldRequired\r
202         LDR             r0, [r1]\r
203         CMP             r0, #0\r
204         BNE             switch_before_exit\r
205 \r
206 exit_without_switch:\r
207         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
208         returning. */\r
209         POP             {r0-r3, r12}\r
210         CPS             #IRQ_MODE\r
211         POP             {LR}\r
212         MSR             SPSR_cxsf, LR\r
213         POP             {LR}\r
214         MOVS    PC, LR\r
215 \r
216 switch_before_exit:\r
217         /* A context swtich is to be performed.  Clear the context switch pending\r
218         flag. */\r
219         MOV             r0, #0\r
220         STR             r0, [r1]\r
221 \r
222         /* Restore used registers, LR-irq and SPSR before saving the context\r
223         to the task stack. */\r
224         POP             {r0-r3, r12}\r
225         CPS             #IRQ_MODE\r
226         POP             {LR}\r
227         MSR             SPSR_cxsf, LR\r
228         POP             {LR}\r
229         portSAVE_CONTEXT\r
230 \r
231         /* Call the function that selects the new task to execute.\r
232         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
233         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
234         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
235         LDR             R0, =vTaskSwitchContext\r
236         BLX             R0\r
237 \r
238         /* Restore the context of, and branch to, the task selected to execute\r
239         next. */\r
240         portRESTORE_CONTEXT\r
241 \r
242         END\r
243 \r
244 \r
245 \r
246 \r
247 \r