]> begriffs open source - cmsis-freertos/blob - Source/portable/GCC/ARM_CM23/non_secure/portasm.c
Updated pack to FreeRTOS 10.4.4
[cmsis-freertos] / Source / portable / GCC / ARM_CM23 / non_secure / portasm.c
1 /*
2  * FreeRTOS Kernel V10.4.4
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
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.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* Standard includes. */
30 #include <stdint.h>
31
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
35
36 /* Portasm includes. */
37 #include "portasm.h"
38
39 /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
40  * header files. */
41 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
42
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.
45 #endif
46
47 void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
48 {
49     __asm volatile
50     (
51         "       .syntax unified                                                                 \n"
52         "                                                                                                       \n"
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. */
56         "                                                                                                       \n"
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. */
64             "                                                                                                   \n"
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. */
91             "                                                                                                   \n"
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 */
99         "                                                                                                       \n"
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. */
108             "   isb                                                                                             \n"
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. */
119             "   isb                                                                                             \n"
120             "   bx   r3                                                                                 \n"/* Finally, branch to EXC_RETURN. */
121         #endif /* configENABLE_MPU */
122         "                                                                                                       \n"
123         "       .align 4                                                                                \n"
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 */
132     );
133 }
134 /*-----------------------------------------------------------*/
135
136 BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
137 {
138     __asm volatile
139     (
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. */
149         "                                                                                                       \n"
150         "       .align 4                                                                                \n"
151         ::: "r0", "r1", "memory"
152     );
153 }
154 /*-----------------------------------------------------------*/
155
156 void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
157 {
158     __asm volatile
159     (
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"
166     );
167 }
168 /*-----------------------------------------------------------*/
169
170 void vResetPrivilege( void ) /* __attribute__ (( naked )) */
171 {
172     __asm volatile
173     (
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"
180     );
181 }
182 /*-----------------------------------------------------------*/
183
184 void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
185 {
186     __asm volatile
187     (
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. */
193         "       dsb                                                                                             \n"
194         "       isb                                                                                             \n"
195         "       svc %0                                                                                  \n"/* System call to start the first task. */
196         "       nop                                                                                             \n"
197         "                                                                                                       \n"
198         "   .align 4                                                                            \n"
199         "xVTORConst: .word 0xe000ed08                                           \n"
200         ::"i" ( portSVC_START_SCHEDULER ) : "memory"
201     );
202 }
203 /*-----------------------------------------------------------*/
204
205 uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
206 {
207     __asm volatile
208     (
209         "       mrs r0, PRIMASK                                                                 \n"
210         "       cpsid i                                                                                 \n"
211         "       bx lr                                                                                   \n"
212         ::: "memory"
213     );
214 }
215 /*-----------------------------------------------------------*/
216
217 void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
218 {
219     __asm volatile
220     (
221         "       msr PRIMASK, r0                                                                 \n"
222         "       bx lr                                                                                   \n"
223         ::: "memory"
224     );
225 }
226 /*-----------------------------------------------------------*/
227
228 void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
229 {
230     __asm volatile
231     (
232         "       .syntax unified                                                                 \n"
233         "       .extern SecureContext_SaveContext                               \n"
234         "       .extern SecureContext_LoadContext                               \n"
235         "                                                                                                       \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. */
239         "                                                                                                       \n"
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"
264         "                                                                                                       \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 */
295         "                                                                                                       \n"
296         " select_next_task:                                                                     \n"
297         "       cpsid i                                                                                 \n"
298         "       bl vTaskSwitchContext                                                   \n"
299         "       cpsie i                                                                                 \n"
300         "                                                                                                       \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. */
304         "                                                                                                       \n"
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. */
312             "                                                                                                   \n"
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. */
339             "                                                                                                   \n"
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 */
347         "                                                                                                       \n"
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. */
356             "   push {r1,r4}                                                                    \n"
357             "   bl SecureContext_LoadContext                                    \n"/* Restore the secure context. */
358             "   pop {r1,r4}                                                                             \n"
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. */
363             "   bx lr                                                                                   \n"
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. */
371             "   push {r1,r3}                                                                    \n"
372             "   bl SecureContext_LoadContext                                    \n"/* Restore the secure context. */
373             "   pop {r1,r3}                                                                             \n"
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. */
378             "   bx lr                                                                                   \n"
379         #endif /* configENABLE_MPU */
380         "                                                                                                       \n"
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. */
391         "       bx lr                                                                                   \n"
392         "                                                                                                       \n"
393         "       .align 4                                                                                \n"
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 */
402     );
403 }
404 /*-----------------------------------------------------------*/
405
406 void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
407 {
408     __asm volatile
409     (
410         "       movs r0, #4                                                                             \n"
411         "       mov r1, lr                                                                              \n"
412         "       tst r0, r1                                                                              \n"
413         "       beq stacking_used_msp                                                   \n"
414         "       mrs r0, psp                                                                             \n"
415         "       ldr r2, svchandler_address_const                                \n"
416         "       bx r2                                                                                   \n"
417         " stacking_used_msp:                                                            \n"
418         "       mrs r0, msp                                                                             \n"
419         "       ldr r2, svchandler_address_const                                \n"
420         "       bx r2                                                                                   \n"
421         "                                                                                                       \n"
422         "       .align 4                                                                                \n"
423         "svchandler_address_const: .word vPortSVCHandler_C      \n"
424     );
425 }
426 /*-----------------------------------------------------------*/
427
428 void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
429 {
430     __asm volatile
431     (
432         "       svc %0                                                                                  \n"/* Secure context is allocated in the supervisor call. */
433         "       bx lr                                                                                   \n"/* Return. */
434         ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
435     );
436 }
437 /*-----------------------------------------------------------*/
438
439 void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
440 {
441     __asm volatile
442     (
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"
452     );
453 }
454 /*-----------------------------------------------------------*/