2 * FreeRTOS Kernel V10.4.4
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * SPDX-License-Identifier: MIT
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
29 /* Standard includes. */
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
33 * is defined correctly and privileged functions are placed in correct sections. */
34 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
36 /* Portasm includes. */
39 /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
41 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
43 #if ( configENABLE_FPU == 1 )
44 #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
47 void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
53 " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
54 " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
55 " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
57 #if ( configENABLE_MPU == 1 )
58 " dmb \n"/* Complete outstanding transfers before disabling MPU. */
59 " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
60 " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
61 " movs r5, #1 \n"/* r5 = 1. */
62 " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
63 " str r4, [r2] \n"/* Disable MPU. */
65 " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
66 " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
67 " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
68 " str r4, [r2] \n"/* Program MAIR0. */
69 " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
70 " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
71 " movs r5, #4 \n"/* r5 = 4. */
72 " str r5, [r2] \n"/* Program RNR = 4. */
73 " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
74 " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
75 " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
76 " movs r5, #5 \n"/* r5 = 5. */
77 " str r5, [r2] \n"/* Program RNR = 5. */
78 " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
79 " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
80 " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
81 " movs r5, #6 \n"/* r5 = 6. */
82 " str r5, [r2] \n"/* Program RNR = 6. */
83 " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
84 " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
85 " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
86 " movs r5, #7 \n"/* r5 = 7. */
87 " str r5, [r2] \n"/* Program RNR = 7. */
88 " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
89 " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
90 " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
92 " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
93 " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
94 " movs r5, #1 \n"/* r5 = 1. */
95 " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
96 " str r4, [r2] \n"/* Enable MPU. */
97 " dsb \n"/* Force memory writes before continuing. */
98 #endif /* configENABLE_MPU */
100 #if ( configENABLE_MPU == 1 )
101 " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
102 " ldr r5, xSecureContextConst2 \n"
103 " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
104 " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
105 " msr control, r3 \n"/* Set this task's CONTROL value. */
106 " adds r0, #32 \n"/* Discard everything up to r0. */
107 " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
109 " bx r4 \n"/* Finally, branch to EXC_RETURN. */
110 #else /* configENABLE_MPU */
111 " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
112 " ldr r4, xSecureContextConst2 \n"
113 " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
114 " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
115 " movs r1, #2 \n"/* r1 = 2. */
116 " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
117 " adds r0, #32 \n"/* Discard everything up to r0. */
118 " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
120 " bx r3 \n"/* Finally, branch to EXC_RETURN. */
121 #endif /* configENABLE_MPU */
124 "pxCurrentTCBConst2: .word pxCurrentTCB \n"
125 "xSecureContextConst2: .word xSecureContext \n"
126 #if ( configENABLE_MPU == 1 )
127 "xMPUCTRLConst2: .word 0xe000ed94 \n"
128 "xMAIR0Const2: .word 0xe000edc0 \n"
129 "xRNRConst2: .word 0xe000ed98 \n"
130 "xRBARConst2: .word 0xe000ed9c \n"
131 #endif /* configENABLE_MPU */
134 /*-----------------------------------------------------------*/
136 BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
140 " mrs r0, control \n"/* r0 = CONTROL. */
141 " movs r1, #1 \n"/* r1 = 1. */
142 " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
143 " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
144 " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
145 " bx lr \n"/* Return. */
146 " running_privileged: \n"
147 " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
148 " bx lr \n"/* Return. */
151 ::: "r0", "r1", "memory"
154 /*-----------------------------------------------------------*/
156 void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
160 " mrs r0, control \n"/* Read the CONTROL register. */
161 " movs r1, #1 \n"/* r1 = 1. */
162 " bics r0, r1 \n"/* Clear the bit 0. */
163 " msr control, r0 \n"/* Write back the new CONTROL value. */
164 " bx lr \n"/* Return to the caller. */
165 ::: "r0", "r1", "memory"
168 /*-----------------------------------------------------------*/
170 void vResetPrivilege( void ) /* __attribute__ (( naked )) */
174 " mrs r0, control \n"/* r0 = CONTROL. */
175 " movs r1, #1 \n"/* r1 = 1. */
176 " orrs r0, r1 \n"/* r0 = r0 | r1. */
177 " msr control, r0 \n"/* CONTROL = r0. */
178 " bx lr \n"/* Return to the caller. */
179 ::: "r0", "r1", "memory"
182 /*-----------------------------------------------------------*/
184 void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
188 " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
189 " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
190 " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
191 " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
192 " cpsie i \n"/* Globally enable interrupts. */
195 " svc %0 \n"/* System call to start the first task. */
199 "xVTORConst: .word 0xe000ed08 \n"
200 ::"i" ( portSVC_START_SCHEDULER ) : "memory"
203 /*-----------------------------------------------------------*/
205 uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
209 " mrs r0, PRIMASK \n"
215 /*-----------------------------------------------------------*/
217 void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
221 " msr PRIMASK, r0 \n"
226 /*-----------------------------------------------------------*/
228 void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
232 " .syntax unified \n"
233 " .extern SecureContext_SaveContext \n"
234 " .extern SecureContext_LoadContext \n"
236 " mrs r1, psp \n"/* Read PSP in r1. */
237 " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
238 " ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
240 " cbz r0, save_ns_context \n"/* No secure context to save. */
241 " push {r0-r2, r14} \n"
242 " bl SecureContext_SaveContext \n"
243 " pop {r0-r3} \n"/* LR is now in r3. */
244 " mov lr, r3 \n"/* LR = r3. */
245 " 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. */
246 " 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. */
247 " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
248 " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
249 #if ( configENABLE_MPU == 1 )
250 " subs r1, r1, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
251 " str r1, [r2] \n"/* Save the new top of stack in TCB. */
252 " mrs r2, psplim \n"/* r2 = PSPLIM. */
253 " mrs r3, control \n"/* r3 = CONTROL. */
254 " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
255 " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
256 #else /* configENABLE_MPU */
257 " subs r1, r1, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
258 " str r1, [r2] \n"/* Save the new top of stack in TCB. */
259 " mrs r2, psplim \n"/* r2 = PSPLIM. */
260 " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
261 " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
262 #endif /* configENABLE_MPU */
263 " b select_next_task \n"
265 " save_ns_context: \n"
266 " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
267 " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
268 #if ( configENABLE_MPU == 1 )
269 " subs r1, r1, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
270 " str r1, [r2] \n"/* Save the new top of stack in TCB. */
271 " adds r1, r1, #16 \n"/* r1 = r1 + 16. */
272 " stmia r1!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
273 " mov r4, r8 \n"/* r4 = r8. */
274 " mov r5, r9 \n"/* r5 = r9. */
275 " mov r6, r10 \n"/* r6 = r10. */
276 " mov r7, r11 \n"/* r7 = r11. */
277 " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
278 " mrs r2, psplim \n"/* r2 = PSPLIM. */
279 " mrs r3, control \n"/* r3 = CONTROL. */
280 " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
281 " subs r1, r1, #48 \n"/* r1 = r1 - 48. */
282 " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
283 #else /* configENABLE_MPU */
284 " subs r1, r1, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
285 " str r1, [r2] \n"/* Save the new top of stack in TCB. */
286 " mrs r2, psplim \n"/* r2 = PSPLIM. */
287 " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
288 " stmia r1!, {r0, r2-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
289 " mov r4, r8 \n"/* r4 = r8. */
290 " mov r5, r9 \n"/* r5 = r9. */
291 " mov r6, r10 \n"/* r6 = r10. */
292 " mov r7, r11 \n"/* r7 = r11. */
293 " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
294 #endif /* configENABLE_MPU */
296 " select_next_task: \n"
298 " bl vTaskSwitchContext \n"
301 " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
302 " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
303 " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
305 #if ( configENABLE_MPU == 1 )
306 " dmb \n"/* Complete outstanding transfers before disabling MPU. */
307 " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
308 " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
309 " movs r5, #1 \n"/* r5 = 1. */
310 " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
311 " str r4, [r2] \n"/* Disable MPU. */
313 " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
314 " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
315 " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
316 " str r4, [r2] \n"/* Program MAIR0. */
317 " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
318 " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
319 " movs r5, #4 \n"/* r5 = 4. */
320 " str r5, [r2] \n"/* Program RNR = 4. */
321 " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
322 " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
323 " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
324 " movs r5, #5 \n"/* r5 = 5. */
325 " str r5, [r2] \n"/* Program RNR = 5. */
326 " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
327 " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
328 " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
329 " movs r5, #6 \n"/* r5 = 6. */
330 " str r5, [r2] \n"/* Program RNR = 6. */
331 " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
332 " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
333 " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
334 " movs r5, #7 \n"/* r5 = 7. */
335 " str r5, [r2] \n"/* Program RNR = 7. */
336 " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
337 " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
338 " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
340 " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
341 " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
342 " movs r5, #1 \n"/* r5 = 1. */
343 " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
344 " str r4, [r2] \n"/* Enable MPU. */
345 " dsb \n"/* Force memory writes before continuing. */
346 #endif /* configENABLE_MPU */
348 #if ( configENABLE_MPU == 1 )
349 " ldmia r1!, {r0, r2-r4} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
350 " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
351 " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
352 " mov lr, r4 \n"/* LR = r4. */
353 " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
354 " str r0, [r2] \n"/* Restore the task's xSecureContext. */
355 " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
357 " bl SecureContext_LoadContext \n"/* Restore the secure context. */
359 " mov lr, r4 \n"/* LR = r4. */
360 " 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. */
361 " 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. */
362 " msr psp, r1 \n"/* Remember the new top of stack for the task. */
364 #else /* configENABLE_MPU */
365 " ldmia r1!, {r0, r2-r3} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
366 " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
367 " mov lr, r3 \n"/* LR = r3. */
368 " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
369 " str r0, [r2] \n"/* Restore the task's xSecureContext. */
370 " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
372 " bl SecureContext_LoadContext \n"/* Restore the secure context. */
374 " mov lr, r3 \n"/* LR = r3. */
375 " 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. */
376 " 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. */
377 " msr psp, r1 \n"/* Remember the new top of stack for the task. */
379 #endif /* configENABLE_MPU */
381 " restore_ns_context: \n"
382 " adds r1, r1, #16 \n"/* Move to the high registers. */
383 " ldmia r1!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
384 " mov r8, r4 \n"/* r8 = r4. */
385 " mov r9, r5 \n"/* r9 = r5. */
386 " mov r10, r6 \n"/* r10 = r6. */
387 " mov r11, r7 \n"/* r11 = r7. */
388 " msr psp, r1 \n"/* Remember the new top of stack for the task. */
389 " subs r1, r1, #32 \n"/* Go back to the low registers. */
390 " ldmia r1!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
394 "pxCurrentTCBConst: .word pxCurrentTCB \n"
395 "xSecureContextConst: .word xSecureContext \n"
396 #if ( configENABLE_MPU == 1 )
397 "xMPUCTRLConst: .word 0xe000ed94 \n"
398 "xMAIR0Const: .word 0xe000edc0 \n"
399 "xRNRConst: .word 0xe000ed98 \n"
400 "xRBARConst: .word 0xe000ed9c \n"
401 #endif /* configENABLE_MPU */
404 /*-----------------------------------------------------------*/
406 void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
413 " beq stacking_used_msp \n"
415 " ldr r2, svchandler_address_const \n"
417 " stacking_used_msp: \n"
419 " ldr r2, svchandler_address_const \n"
423 "svchandler_address_const: .word vPortSVCHandler_C \n"
426 /*-----------------------------------------------------------*/
428 void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
432 " svc %0 \n"/* Secure context is allocated in the supervisor call. */
433 " bx lr \n"/* Return. */
434 ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
437 /*-----------------------------------------------------------*/
439 void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
443 " ldr r1, [r0] \n"/* The first item in the TCB is the top of the stack. */
444 " ldr r0, [r1] \n"/* The first item on the stack is the task's xSecureContext. */
445 " cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
446 " beq free_secure_context \n"
447 " bx lr \n"/* There is no secure context (xSecureContext is NULL). */
448 " free_secure_context: \n"
449 " svc %0 \n"/* Secure context is freed in the supervisor call. */
450 " bx lr \n"/* Return. */
451 ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
454 /*-----------------------------------------------------------*/