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