]> begriffs open source - freertos/blob - portable/GCC/ARM_CM33/non_secure/portasm.c
[AUTO][RELEASE]: Bump file header version to "10.4.3 LTS Patch 3"
[freertos] / portable / GCC / ARM_CM33 / non_secure / portasm.c
1 /*\r
2  * FreeRTOS Kernel V10.4.3 LTS Patch 3\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  * https://www.FreeRTOS.org\r
23  * https://github.com/FreeRTOS\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /* Standard includes. */\r
29 #include <stdint.h>\r
30 \r
31 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION\r
32  * is defined correctly and privileged functions are placed in correct sections. */\r
33 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
34 \r
35 /* Portasm includes. */\r
36 #include "portasm.h"\r
37 \r
38 /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the\r
39  * header files. */\r
40 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
41 \r
42 void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */\r
43 {\r
44     __asm volatile\r
45     (\r
46         "       .syntax unified                                                                 \n"\r
47         "                                                                                                       \n"\r
48         "       ldr  r2, pxCurrentTCBConst2                                             \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
49         "       ldr  r3, [r2]                                                                   \n"/* Read pxCurrentTCB. */\r
50         "       ldr  r0, [r3]                                                                   \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */\r
51         "                                                                                                       \n"\r
52         #if ( configENABLE_MPU == 1 )\r
53             "   dmb                                                                                     \n"/* Complete outstanding transfers before disabling MPU. */\r
54             "   ldr r2, xMPUCTRLConst2                                          \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */\r
55             "   ldr r4, [r2]                                                            \n"/* Read the value of MPU_CTRL. */\r
56             "   bic r4, #1                                                                      \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */\r
57             "   str r4, [r2]                                                            \n"/* Disable MPU. */\r
58             "                                                                                           \n"\r
59             "   adds r3, #4                                                                     \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */\r
60             "   ldr  r4, [r3]                                                           \n"/* r4 = *r3 i.e. r4 = MAIR0. */\r
61             "   ldr  r2, xMAIR0Const2                                           \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */\r
62             "   str  r4, [r2]                                                           \n"/* Program MAIR0. */\r
63             "   ldr  r2, xRNRConst2                                                     \n"/* r2 = 0xe000ed98 [Location of RNR]. */\r
64             "   movs r4, #4                                                                     \n"/* r4 = 4. */\r
65             "   str  r4, [r2]                                                           \n"/* Program RNR = 4. */\r
66             "   adds r3, #4                                                                     \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */\r
67             "   ldr  r2, xRBARConst2                                            \n"/* r2 = 0xe000ed9c [Location of RBAR]. */\r
68             "   ldmia r3!, {r4-r11}                                                     \n"/* Read 4 set of RBAR/RLAR registers from TCB. */\r
69             "   stmia r2!, {r4-r11}                                                     \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */\r
70             "                                                                                           \n"\r
71             "   ldr r2, xMPUCTRLConst2                                          \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */\r
72             "   ldr r4, [r2]                                                            \n"/* Read the value of MPU_CTRL. */\r
73             "   orr r4, #1                                                                      \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */\r
74             "   str r4, [r2]                                                            \n"/* Enable MPU. */\r
75             "   dsb                                                                                     \n"/* Force memory writes before continuing. */\r
76         #endif /* configENABLE_MPU */\r
77         "                                                                                                       \n"\r
78         #if ( configENABLE_MPU == 1 )\r
79             "   ldm  r0!, {r1-r4}                                                       \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */\r
80             "   ldr  r5, xSecureContextConst2                           \n"\r
81             "   str  r1, [r5]                                                           \n"/* Set xSecureContext to this task's value for the same. */\r
82             "   msr  psplim, r2                                                         \n"/* Set this task's PSPLIM value. */\r
83             "   msr  control, r3                                                        \n"/* Set this task's CONTROL value. */\r
84             "   adds r0, #32                                                            \n"/* Discard everything up to r0. */\r
85             "   msr  psp, r0                                                            \n"/* This is now the new top of stack to use in the task. */\r
86             "   isb                                                                                     \n"\r
87             "   mov  r0, #0                                                                     \n"\r
88             "   msr  basepri, r0                                                        \n"/* Ensure that interrupts are enabled when the first task starts. */\r
89             "   bx   r4                                                                         \n"/* Finally, branch to EXC_RETURN. */\r
90         #else /* configENABLE_MPU */\r
91             "   ldm  r0!, {r1-r3}                                                       \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */\r
92             "   ldr  r4, xSecureContextConst2                           \n"\r
93             "   str  r1, [r4]                                                           \n"/* Set xSecureContext to this task's value for the same. */\r
94             "   msr  psplim, r2                                                         \n"/* Set this task's PSPLIM value. */\r
95             "   movs r1, #2                                                                     \n"/* r1 = 2. */\r
96             "   msr  CONTROL, r1                                                        \n"/* Switch to use PSP in the thread mode. */\r
97             "   adds r0, #32                                                            \n"/* Discard everything up to r0. */\r
98             "   msr  psp, r0                                                            \n"/* This is now the new top of stack to use in the task. */\r
99             "   isb                                                                                     \n"\r
100             "   mov  r0, #0                                                                     \n"\r
101             "   msr  basepri, r0                                                        \n"/* Ensure that interrupts are enabled when the first task starts. */\r
102             "   bx   r3                                                                         \n"/* Finally, branch to EXC_RETURN. */\r
103         #endif /* configENABLE_MPU */\r
104         "                                                                                                       \n"\r
105         "       .align 4                                                                                \n"\r
106         "pxCurrentTCBConst2: .word pxCurrentTCB                         \n"\r
107         "xSecureContextConst2: .word xSecureContext                     \n"\r
108         #if ( configENABLE_MPU == 1 )\r
109             "xMPUCTRLConst2: .word 0xe000ed94                           \n"\r
110             "xMAIR0Const2: .word 0xe000edc0                                     \n"\r
111             "xRNRConst2: .word 0xe000ed98                                       \n"\r
112             "xRBARConst2: .word 0xe000ed9c                                      \n"\r
113         #endif /* configENABLE_MPU */\r
114     );\r
115 }\r
116 /*-----------------------------------------------------------*/\r
117 \r
118 BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */\r
119 {\r
120     __asm volatile\r
121     (\r
122         "       mrs r0, control                                                                 \n"/* r0 = CONTROL. */\r
123         "       tst r0, #1                                                                              \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */\r
124         "       ite ne                                                                                  \n"\r
125         "       movne r0, #0                                                                    \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */\r
126         "       moveq r0, #1                                                                    \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */\r
127         "       bx lr                                                                                   \n"/* Return. */\r
128         "                                                                                                       \n"\r
129         "       .align 4                                                                                \n"\r
130         ::: "r0", "memory"\r
131     );\r
132 }\r
133 /*-----------------------------------------------------------*/\r
134 \r
135 void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */\r
136 {\r
137     __asm volatile\r
138     (\r
139         "       mrs r0, control                                                                 \n"/* Read the CONTROL register. */\r
140         "       bic r0, #1                                                                              \n"/* Clear the bit 0. */\r
141         "       msr control, r0                                                                 \n"/* Write back the new CONTROL value. */\r
142         "       bx lr                                                                                   \n"/* Return to the caller. */\r
143         ::: "r0", "memory"\r
144     );\r
145 }\r
146 /*-----------------------------------------------------------*/\r
147 \r
148 void vResetPrivilege( void ) /* __attribute__ (( naked )) */\r
149 {\r
150     __asm volatile\r
151     (\r
152         "       mrs r0, control                                                                 \n"/* r0 = CONTROL. */\r
153         "       orr r0, #1                                                                              \n"/* r0 = r0 | 1. */\r
154         "       msr control, r0                                                                 \n"/* CONTROL = r0. */\r
155         "       bx lr                                                                                   \n"/* Return to the caller. */\r
156         ::: "r0", "memory"\r
157     );\r
158 }\r
159 /*-----------------------------------------------------------*/\r
160 \r
161 void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */\r
162 {\r
163     __asm volatile\r
164     (\r
165         "       ldr r0, xVTORConst                                                              \n"/* Use the NVIC offset register to locate the stack. */\r
166         "       ldr r0, [r0]                                                                    \n"/* Read the VTOR register which gives the address of vector table. */\r
167         "       ldr r0, [r0]                                                                    \n"/* The first entry in vector table is stack pointer. */\r
168         "       msr msp, r0                                                                             \n"/* Set the MSP back to the start of the stack. */\r
169         "       cpsie i                                                                                 \n"/* Globally enable interrupts. */\r
170         "       cpsie f                                                                                 \n"\r
171         "       dsb                                                                                             \n"\r
172         "       isb                                                                                             \n"\r
173         "       svc %0                                                                                  \n"/* System call to start the first task. */\r
174         "       nop                                                                                             \n"\r
175         "                                                                                                       \n"\r
176         "   .align 4                                                                            \n"\r
177         "xVTORConst: .word 0xe000ed08                                           \n"\r
178         ::"i" ( portSVC_START_SCHEDULER ) : "memory"\r
179     );\r
180 }\r
181 /*-----------------------------------------------------------*/\r
182 \r
183 uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */\r
184 {\r
185     __asm volatile\r
186     (\r
187         "       mrs r0, basepri                                                                 \n"/* r0 = basepri. Return original basepri value. */\r
188         "       mov r1, %0                                                                              \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
189         "       msr basepri, r1                                                                 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
190         "       dsb                                                                                             \n"\r
191         "       isb                                                                                             \n"\r
192         "       bx lr                                                                                   \n"/* Return. */\r
193         ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"\r
194     );\r
195 }\r
196 /*-----------------------------------------------------------*/\r
197 \r
198 void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */\r
199 {\r
200     __asm volatile\r
201     (\r
202         "       msr basepri, r0                                                                 \n"/* basepri = ulMask. */\r
203         "       dsb                                                                                             \n"\r
204         "       isb                                                                                             \n"\r
205         "       bx lr                                                                                   \n"/* Return. */\r
206         ::: "memory"\r
207     );\r
208 }\r
209 /*-----------------------------------------------------------*/\r
210 \r
211 void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */\r
212 {\r
213     __asm volatile\r
214     (\r
215         "       .syntax unified                                                                 \n"\r
216         "       .extern SecureContext_SaveContext                               \n"\r
217         "       .extern SecureContext_LoadContext                               \n"\r
218         "                                                                                                       \n"\r
219         "       ldr r3, xSecureContextConst                                             \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */\r
220         "       ldr r0, [r3]                                                                    \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */\r
221         "       ldr r3, pxCurrentTCBConst                                               \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
222         "       ldr r1, [r3]                                                                    \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */\r
223         "       mrs r2, psp                                                                             \n"/* Read PSP in r2. */\r
224         "                                                                                                       \n"\r
225         "       cbz r0, save_ns_context                                                 \n"/* No secure context to save. */\r
226         "       push {r0-r2, r14}                                                               \n"\r
227         "       bl SecureContext_SaveContext                                    \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */\r
228         "       pop {r0-r3}                                                                             \n"/* LR is now in r3. */\r
229         "       mov lr, r3                                                                              \n"/* LR = r3. */\r
230         "       lsls r1, r3, #25                                                                \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */\r
231         "       bpl save_ns_context                                                             \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */\r
232         "                                                                                                       \n"\r
233         "       ldr r3, pxCurrentTCBConst                                               \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
234         "       ldr r1, [r3]                                                                    \n"/* Read pxCurrentTCB.*/\r
235         #if ( configENABLE_MPU == 1 )\r
236             "   subs r2, r2, #16                                                        \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */\r
237             "   str r2, [r1]                                                            \n"/* Save the new top of stack in TCB. */\r
238             "   mrs r1, psplim                                                          \n"/* r1 = PSPLIM. */\r
239             "   mrs r3, control                                                         \n"/* r3 = CONTROL. */\r
240             "   mov r4, lr                                                                      \n"/* r4 = LR/EXC_RETURN. */\r
241             "   stmia r2!, {r0, r1, r3, r4}                                     \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */\r
242         #else /* configENABLE_MPU */\r
243             "   subs r2, r2, #12                                                        \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */\r
244             "   str r2, [r1]                                                            \n"/* Save the new top of stack in TCB. */\r
245             "   mrs r1, psplim                                                          \n"/* r1 = PSPLIM. */\r
246             "   mov r3, lr                                                                      \n"/* r3 = LR/EXC_RETURN. */\r
247             "   stmia r2!, {r0, r1, r3}                                         \n"/* Store xSecureContext, PSPLIM and LR on the stack. */\r
248         #endif /* configENABLE_MPU */\r
249         "       b select_next_task                                                              \n"\r
250         "                                                                                                       \n"\r
251         " save_ns_context:                                                                      \n"\r
252         "       ldr r3, pxCurrentTCBConst                                               \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
253         "       ldr r1, [r3]                                                                    \n"/* Read pxCurrentTCB. */\r
254         #if ( configENABLE_FPU == 1 )\r
255             "   tst lr, #0x10                                                           \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */\r
256             "   it eq                                                                           \n"\r
257             "   vstmdbeq r2!, {s16-s31}                                         \n"/* Store the FPU registers which are not saved automatically. */\r
258         #endif /* configENABLE_FPU */\r
259         #if ( configENABLE_MPU == 1 )\r
260             "   subs r2, r2, #48                                                        \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */\r
261             "   str r2, [r1]                                                            \n"/* Save the new top of stack in TCB. */\r
262             "   adds r2, r2, #16                                                        \n"/* r2 = r2 + 16. */\r
263             "   stm r2, {r4-r11}                                                        \n"/* Store the registers that are not saved automatically. */\r
264             "   mrs r1, psplim                                                          \n"/* r1 = PSPLIM. */\r
265             "   mrs r3, control                                                         \n"/* r3 = CONTROL. */\r
266             "   mov r4, lr                                                                      \n"/* r4 = LR/EXC_RETURN. */\r
267             "   subs r2, r2, #16                                                        \n"/* r2 = r2 - 16. */\r
268             "   stmia r2!, {r0, r1, r3, r4}                                     \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */\r
269         #else /* configENABLE_MPU */\r
270             "   subs r2, r2, #44                                                        \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */\r
271             "   str r2, [r1]                                                            \n"/* Save the new top of stack in TCB. */\r
272             "   adds r2, r2, #12                                                        \n"/* r2 = r2 + 12. */\r
273             "   stm r2, {r4-r11}                                                        \n"/* Store the registers that are not saved automatically. */\r
274             "   mrs r1, psplim                                                          \n"/* r1 = PSPLIM. */\r
275             "   mov r3, lr                                                                      \n"/* r3 = LR/EXC_RETURN. */\r
276             "   subs r2, r2, #12                                                        \n"/* r2 = r2 - 12. */\r
277             "   stmia r2!, {r0, r1, r3}                                         \n"/* Store xSecureContext, PSPLIM and LR on the stack. */\r
278         #endif /* configENABLE_MPU */\r
279         "                                                                                                       \n"\r
280         " select_next_task:                                                                     \n"\r
281         "       mov r0, %0                                                                              \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */\r
282         "       msr basepri, r0                                                                 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
283         "       dsb                                                                                             \n"\r
284         "       isb                                                                                             \n"\r
285         "       bl vTaskSwitchContext                                                   \n"\r
286         "       mov r0, #0                                                                              \n"/* r0 = 0. */\r
287         "       msr basepri, r0                                                                 \n"/* Enable interrupts. */\r
288         "                                                                                                       \n"\r
289         "       ldr r3, pxCurrentTCBConst                                               \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
290         "       ldr r1, [r3]                                                                    \n"/* Read pxCurrentTCB. */\r
291         "       ldr r2, [r1]                                                                    \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */\r
292         "                                                                                                       \n"\r
293         #if ( configENABLE_MPU == 1 )\r
294             "   dmb                                                                                     \n"/* Complete outstanding transfers before disabling MPU. */\r
295             "   ldr r3, xMPUCTRLConst                                           \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */\r
296             "   ldr r4, [r3]                                                            \n"/* Read the value of MPU_CTRL. */\r
297             "   bic r4, #1                                                                      \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */\r
298             "   str r4, [r3]                                                            \n"/* Disable MPU. */\r
299             "                                                                                           \n"\r
300             "   adds r1, #4                                                                     \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */\r
301             "   ldr r4, [r1]                                                            \n"/* r4 = *r1 i.e. r4 = MAIR0. */\r
302             "   ldr r3, xMAIR0Const                                                     \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */\r
303             "   str r4, [r3]                                                            \n"/* Program MAIR0. */\r
304             "   ldr r3, xRNRConst                                                       \n"/* r3 = 0xe000ed98 [Location of RNR]. */\r
305             "   movs r4, #4                                                                     \n"/* r4 = 4. */\r
306             "   str r4, [r3]                                                            \n"/* Program RNR = 4. */\r
307             "   adds r1, #4                                                                     \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */\r
308             "   ldr r3, xRBARConst                                                      \n"/* r3 = 0xe000ed9c [Location of RBAR]. */\r
309             "   ldmia r1!, {r4-r11}                                                     \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */\r
310             "   stmia r3!, {r4-r11}                                                     \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */\r
311             "                                                                                           \n"\r
312             "   ldr r3, xMPUCTRLConst                                           \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */\r
313             "   ldr r4, [r3]                                                            \n"/* Read the value of MPU_CTRL. */\r
314             "   orr r4, #1                                                                      \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */\r
315             "   str r4, [r3]                                                            \n"/* Enable MPU. */\r
316             "   dsb                                                                                     \n"/* Force memory writes before continuing. */\r
317         #endif /* configENABLE_MPU */\r
318         "                                                                                                       \n"\r
319         #if ( configENABLE_MPU == 1 )\r
320             "   ldmia r2!, {r0, r1, r3, r4}                                     \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */\r
321             "   msr psplim, r1                                                          \n"/* Restore the PSPLIM register value for the task. */\r
322             "   msr control, r3                                                         \n"/* Restore the CONTROL register value for the task. */\r
323             "   mov lr, r4                                                                      \n"/* LR = r4. */\r
324             "   ldr r3, xSecureContextConst                                     \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */\r
325             "   str r0, [r3]                                                            \n"/* Restore the task's xSecureContext. */\r
326             "   cbz r0, restore_ns_context                                      \n"/* If there is no secure context for the task, restore the non-secure context. */\r
327             "   ldr r3, pxCurrentTCBConst                                       \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
328             "   ldr r1, [r3]                                                            \n"/* Read pxCurrentTCB. */\r
329             "   push {r2, r4}                                                           \n"\r
330             "   bl SecureContext_LoadContext                            \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */\r
331             "   pop {r2, r4}                                                            \n"\r
332             "   mov lr, r4                                                                      \n"/* LR = r4. */\r
333             "   lsls r1, r4, #25                                                        \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */\r
334             "   bpl restore_ns_context                                          \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */\r
335             "   msr psp, r2                                                                     \n"/* Remember the new top of stack for the task. */\r
336             "   bx lr                                                                           \n"\r
337         #else /* configENABLE_MPU */\r
338             "   ldmia r2!, {r0, r1, r4}                                         \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */\r
339             "   msr psplim, r1                                                          \n"/* Restore the PSPLIM register value for the task. */\r
340             "   mov lr, r4                                                                      \n"/* LR = r4. */\r
341             "   ldr r3, xSecureContextConst                                     \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */\r
342             "   str r0, [r3]                                                            \n"/* Restore the task's xSecureContext. */\r
343             "   cbz r0, restore_ns_context                                      \n"/* If there is no secure context for the task, restore the non-secure context. */\r
344             "   ldr r3, pxCurrentTCBConst                                       \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */\r
345             "   ldr r1, [r3]                                                            \n"/* Read pxCurrentTCB. */\r
346             "   push {r2, r4}                                                           \n"\r
347             "   bl SecureContext_LoadContext                            \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */\r
348             "   pop {r2, r4}                                                            \n"\r
349             "   mov lr, r4                                                                      \n"/* LR = r4. */\r
350             "   lsls r1, r4, #25                                                        \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */\r
351             "   bpl restore_ns_context                                          \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */\r
352             "   msr psp, r2                                                                     \n"/* Remember the new top of stack for the task. */\r
353             "   bx lr                                                                           \n"\r
354         #endif /* configENABLE_MPU */\r
355         "                                                                                                       \n"\r
356         " restore_ns_context:                                                           \n"\r
357         "       ldmia r2!, {r4-r11}                                                             \n"/* Restore the registers that are not automatically restored. */\r
358         #if ( configENABLE_FPU == 1 )\r
359             "   tst lr, #0x10                                                           \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */\r
360             "   it eq                                                                           \n"\r
361             "   vldmiaeq r2!, {s16-s31}                                         \n"/* Restore the FPU registers which are not restored automatically. */\r
362         #endif /* configENABLE_FPU */\r
363         "       msr psp, r2                                                                             \n"/* Remember the new top of stack for the task. */\r
364         "       bx lr                                                                                   \n"\r
365         "                                                                                                       \n"\r
366         "       .align 4                                                                                \n"\r
367         "pxCurrentTCBConst: .word pxCurrentTCB                          \n"\r
368         "xSecureContextConst: .word xSecureContext                      \n"\r
369         #if ( configENABLE_MPU == 1 )\r
370             "xMPUCTRLConst: .word 0xe000ed94                            \n"\r
371             "xMAIR0Const: .word 0xe000edc0                                      \n"\r
372             "xRNRConst: .word 0xe000ed98                                        \n"\r
373             "xRBARConst: .word 0xe000ed9c                                       \n"\r
374         #endif /* configENABLE_MPU */\r
375         ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )\r
376     );\r
377 }\r
378 /*-----------------------------------------------------------*/\r
379 \r
380 void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */\r
381 {\r
382     __asm volatile\r
383     (\r
384         "       tst lr, #4                                                                              \n"\r
385         "       ite eq                                                                                  \n"\r
386         "       mrseq r0, msp                                                                   \n"\r
387         "       mrsne r0, psp                                                                   \n"\r
388         "       ldr r1, svchandler_address_const                                \n"\r
389         "       bx r1                                                                                   \n"\r
390         "                                                                                                       \n"\r
391         "       .align 4                                                                                \n"\r
392         "svchandler_address_const: .word vPortSVCHandler_C      \n"\r
393     );\r
394 }\r
395 /*-----------------------------------------------------------*/\r
396 \r
397 void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */\r
398 {\r
399     __asm volatile\r
400     (\r
401         "       svc %0                                                                                  \n"/* Secure context is allocated in the supervisor call. */\r
402         "       bx lr                                                                                   \n"/* Return. */\r
403         ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"\r
404     );\r
405 }\r
406 /*-----------------------------------------------------------*/\r
407 \r
408 void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */\r
409 {\r
410     __asm volatile\r
411     (\r
412         "       ldr r2, [r0]                                                                    \n"/* The first item in the TCB is the top of the stack. */\r
413         "       ldr r1, [r2]                                                                    \n"/* The first item on the stack is the task's xSecureContext. */\r
414         "       cmp r1, #0                                                                              \n"/* Raise svc if task's xSecureContext is not NULL. */\r
415         "       it ne                                                                                   \n"\r
416         "       svcne %0                                                                                \n"/* Secure context is freed in the supervisor call. */\r
417         "       bx lr                                                                                   \n"/* Return. */\r
418         ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"\r
419     );\r
420 }\r
421 /*-----------------------------------------------------------*/\r