xref: /Kernel-v11.0.1/portable/GCC/ARM_CM35P_NTZ/non_secure/portasm.c (revision 65c72e485a63577f5d15096d5a53c9dca8822d65)
1 /*
2  * FreeRTOS Kernel V11.0.1
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 /* System call numbers includes. */
40 #include "mpu_syscall_numbers.h"
41 
42 /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
43  * header files. */
44 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
45 
46 #if ( configENABLE_MPU == 1 )
47 
vRestoreContextOfFirstTask(void)48     void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
49     {
50         __asm volatile
51         (
52             " .syntax unified                                 \n"
53             "                                                 \n"
54             " program_mpu_first_task:                         \n"
55             "    ldr r2, pxCurrentTCBConst2                   \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
56             "    ldr r0, [r2]                                 \n" /* r0 = pxCurrentTCB. */
57             "                                                 \n"
58             "    dmb                                          \n" /* Complete outstanding transfers before disabling MPU. */
59             "    ldr r1, xMPUCTRLConst2                       \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
60             "    ldr r2, [r1]                                 \n" /* Read the value of MPU_CTRL. */
61             "    bic r2, #1                                   \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
62             "    str r2, [r1]                                 \n" /* Disable MPU. */
63             "                                                 \n"
64             "    adds r0, #4                                  \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
65             "    ldr r1, [r0]                                 \n" /* r1 = *r0 i.e. r1 = MAIR0. */
66             "    ldr r2, xMAIR0Const2                         \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
67             "    str r1, [r2]                                 \n" /* Program MAIR0. */
68             "                                                 \n"
69             "    adds r0, #4                                  \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
70             "    ldr r1, xRNRConst2                           \n" /* r1 = 0xe000ed98 [Location of RNR]. */
71             "    ldr r2, xRBARConst2                          \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
72             "                                                 \n"
73             "    movs r3, #4                                  \n" /* r3 = 4. */
74             "    str r3, [r1]                                 \n" /* Program RNR = 4. */
75             "    ldmia r0!, {r4-r11}                          \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
76             "    stmia r2, {r4-r11}                           \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
77             "                                                 \n"
78             #if ( configTOTAL_MPU_REGIONS == 16 )
79                 "    movs r3, #8                                  \n" /* r3 = 8. */
80                 "    str r3, [r1]                                 \n" /* Program RNR = 8. */
81                 "    ldmia r0!, {r4-r11}                          \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
82                 "    stmia r2, {r4-r11}                           \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
83                 "    movs r3, #12                                 \n" /* r3 = 12. */
84                 "    str r3, [r1]                                 \n" /* Program RNR = 12. */
85                 "    ldmia r0!, {r4-r11}                          \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
86                 "    stmia r2, {r4-r11}                           \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
87             #endif /* configTOTAL_MPU_REGIONS == 16 */
88             "                                                 \n"
89             "   ldr r1, xMPUCTRLConst2                        \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
90             "   ldr r2, [r1]                                  \n" /* Read the value of MPU_CTRL. */
91             "   orr r2, #1                                    \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
92             "   str r2, [r1]                                  \n" /* Enable MPU. */
93             "   dsb                                           \n" /* Force memory writes before continuing. */
94             "                                                 \n"
95             " restore_context_first_task:                     \n"
96             "    ldr r2, pxCurrentTCBConst2                   \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
97             "    ldr r0, [r2]                                 \n" /* r0 = pxCurrentTCB.*/
98             "    ldr r1, [r0]                                 \n" /* r1 = Location of saved context in TCB. */
99             "                                                 \n"
100             " restore_special_regs_first_task:                \n"
101             "    ldmdb r1!, {r2-r4, lr}                       \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
102             "    msr psp, r2                                  \n"
103             "    msr psplim, r3                               \n"
104             "    msr control, r4                              \n"
105             "                                                 \n"
106             " restore_general_regs_first_task:                \n"
107             "    ldmdb r1!, {r4-r11}                          \n" /* r4-r11 contain hardware saved context. */
108             "    stmia r2!, {r4-r11}                          \n" /* Copy the hardware saved context on the task stack. */
109             "    ldmdb r1!, {r4-r11}                          \n" /* r4-r11 restored. */
110             "                                                 \n"
111             " restore_context_done_first_task:                \n"
112             "    str r1, [r0]                                 \n" /* Save the location where the context should be saved next as the first member of TCB. */
113             "    mov r0, #0                                   \n"
114             "    msr basepri, r0                              \n" /* Ensure that interrupts are enabled when the first task starts. */
115             "    bx lr                                        \n"
116             "                                                 \n"
117             " .align 4                                        \n"
118             " pxCurrentTCBConst2: .word pxCurrentTCB          \n"
119             " xMPUCTRLConst2: .word 0xe000ed94                \n"
120             " xMAIR0Const2: .word 0xe000edc0                  \n"
121             " xRNRConst2: .word 0xe000ed98                    \n"
122             " xRBARConst2: .word 0xe000ed9c                   \n"
123         );
124     }
125 
126 #else /* configENABLE_MPU */
127 
vRestoreContextOfFirstTask(void)128     void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
129     {
130         __asm volatile
131         (
132             "   .syntax unified                                 \n"
133             "                                                   \n"
134             "   ldr  r2, pxCurrentTCBConst2                     \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
135             "   ldr  r1, [r2]                                   \n" /* Read pxCurrentTCB. */
136             "   ldr  r0, [r1]                                   \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
137             "                                                   \n"
138             "   ldm  r0!, {r1-r2}                               \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
139             "   msr  psplim, r1                                 \n" /* Set this task's PSPLIM value. */
140             "   movs r1, #2                                     \n" /* r1 = 2. */
141             "   msr  CONTROL, r1                                \n" /* Switch to use PSP in the thread mode. */
142             "   adds r0, #32                                    \n" /* Discard everything up to r0. */
143             "   msr  psp, r0                                    \n" /* This is now the new top of stack to use in the task. */
144             "   isb                                             \n"
145             "   mov  r0, #0                                     \n"
146             "   msr  basepri, r0                                \n" /* Ensure that interrupts are enabled when the first task starts. */
147             "   bx   r2                                         \n" /* Finally, branch to EXC_RETURN. */
148             "                                                   \n"
149             "   .align 4                                        \n"
150             "pxCurrentTCBConst2: .word pxCurrentTCB             \n"
151         );
152     }
153 
154 #endif /* configENABLE_MPU */
155 /*-----------------------------------------------------------*/
156 
xIsPrivileged(void)157 BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
158 {
159     __asm volatile
160     (
161         "   .syntax unified                                 \n"
162         "                                                   \n"
163         "   mrs r0, control                                 \n" /* r0 = CONTROL. */
164         "   tst r0, #1                                      \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
165         "   ite ne                                          \n"
166         "   movne r0, #0                                    \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
167         "   moveq r0, #1                                    \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
168         "   bx lr                                           \n" /* Return. */
169         "                                                   \n"
170         "   .align 4                                        \n"
171         ::: "r0", "memory"
172     );
173 }
174 /*-----------------------------------------------------------*/
175 
vRaisePrivilege(void)176 void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
177 {
178     __asm volatile
179     (
180         "   .syntax unified                                 \n"
181         "                                                   \n"
182         "   mrs  r0, control                                \n" /* Read the CONTROL register. */
183         "   bic r0, #1                                      \n" /* Clear the bit 0. */
184         "   msr  control, r0                                \n" /* Write back the new CONTROL value. */
185         "   bx lr                                           \n" /* Return to the caller. */
186         ::: "r0", "memory"
187     );
188 }
189 /*-----------------------------------------------------------*/
190 
vResetPrivilege(void)191 void vResetPrivilege( void ) /* __attribute__ (( naked )) */
192 {
193     __asm volatile
194     (
195         "   .syntax unified                                 \n"
196         "                                                   \n"
197         "   mrs r0, control                                 \n" /* r0 = CONTROL. */
198         "   orr r0, #1                                      \n" /* r0 = r0 | 1. */
199         "   msr control, r0                                 \n" /* CONTROL = r0. */
200         "   bx lr                                           \n" /* Return to the caller. */
201         ::: "r0", "memory"
202     );
203 }
204 /*-----------------------------------------------------------*/
205 
vStartFirstTask(void)206 void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
207 {
208     __asm volatile
209     (
210         "   .syntax unified                                 \n"
211         "                                                   \n"
212         "   ldr r0, xVTORConst                              \n" /* Use the NVIC offset register to locate the stack. */
213         "   ldr r0, [r0]                                    \n" /* Read the VTOR register which gives the address of vector table. */
214         "   ldr r0, [r0]                                    \n" /* The first entry in vector table is stack pointer. */
215         "   msr msp, r0                                     \n" /* Set the MSP back to the start of the stack. */
216         "   cpsie i                                         \n" /* Globally enable interrupts. */
217         "   cpsie f                                         \n"
218         "   dsb                                             \n"
219         "   isb                                             \n"
220         "   svc %0                                          \n" /* System call to start the first task. */
221         "   nop                                             \n"
222         "                                                   \n"
223         "   .align 4                                        \n"
224         "xVTORConst: .word 0xe000ed08                       \n"
225         ::"i" ( portSVC_START_SCHEDULER ) : "memory"
226     );
227 }
228 /*-----------------------------------------------------------*/
229 
ulSetInterruptMask(void)230 uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
231 {
232     __asm volatile
233     (
234         "   .syntax unified                                 \n"
235         "                                                   \n"
236         "   mrs r0, basepri                                 \n" /* r0 = basepri. Return original basepri value. */
237         "   mov r1, %0                                      \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
238         "   msr basepri, r1                                 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
239         "   dsb                                             \n"
240         "   isb                                             \n"
241         "   bx lr                                           \n" /* Return. */
242         ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
243     );
244 }
245 /*-----------------------------------------------------------*/
246 
vClearInterruptMask(uint32_t ulMask)247 void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
248 {
249     __asm volatile
250     (
251         "   .syntax unified                                 \n"
252         "                                                   \n"
253         "   msr basepri, r0                                 \n" /* basepri = ulMask. */
254         "   dsb                                             \n"
255         "   isb                                             \n"
256         "   bx lr                                           \n" /* Return. */
257         ::: "memory"
258     );
259 }
260 /*-----------------------------------------------------------*/
261 
262 #if ( configENABLE_MPU == 1 )
263 
PendSV_Handler(void)264     void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
265     {
266         __asm volatile
267         (
268             " .syntax unified                                 \n"
269             "                                                 \n"
270             " ldr r2, pxCurrentTCBConst                       \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
271             " ldr r0, [r2]                                    \n" /* r0 = pxCurrentTCB. */
272             " ldr r1, [r0]                                    \n" /* r1 = Location in TCB where the context should be saved. */
273             " mrs r2, psp                                     \n" /* r2 = PSP. */
274             "                                                 \n"
275             " save_general_regs:                              \n"
276             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
277                 "    add r2, r2, #0x20                            \n" /* Move r2 to location where s0 is saved. */
278                 "    tst lr, #0x10                                \n"
279                 "    ittt eq                                      \n"
280                 "    vstmiaeq r1!, {s16-s31}                      \n" /* Store s16-s31. */
281                 "    vldmiaeq r2, {s0-s16}                        \n" /* Copy hardware saved FP context into s0-s16. */
282                 "    vstmiaeq r1!, {s0-s16}                       \n" /* Store hardware saved FP context. */
283                 "    sub r2, r2, #0x20                            \n" /* Set r2 back to the location of hardware saved context. */
284             #endif /* configENABLE_FPU || configENABLE_MVE */
285             "                                                 \n"
286             "    stmia r1!, {r4-r11}                          \n" /* Store r4-r11. */
287             "    ldmia r2, {r4-r11}                           \n" /* Copy the hardware saved context into r4-r11. */
288             "    stmia r1!, {r4-r11}                          \n" /* Store the hardware saved context. */
289             "                                                 \n"
290             " save_special_regs:                              \n"
291             "    mrs r3, psplim                               \n" /* r3 = PSPLIM. */
292             "    mrs r4, control                              \n" /* r4 = CONTROL. */
293             "    stmia r1!, {r2-r4, lr}                       \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
294             "    str r1, [r0]                                 \n" /* Save the location from where the context should be restored as the first member of TCB. */
295             "                                                 \n"
296             " select_next_task:                               \n"
297             "    mov r0, %0                                   \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
298             "    msr basepri, r0                              \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
299             "    dsb                                          \n"
300             "    isb                                          \n"
301             "    bl vTaskSwitchContext                        \n"
302             "    mov r0, #0                                   \n" /* r0 = 0. */
303             "    msr basepri, r0                              \n" /* Enable interrupts. */
304             "                                                 \n"
305             " program_mpu:                                    \n"
306             "    ldr r2, pxCurrentTCBConst                    \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
307             "    ldr r0, [r2]                                 \n" /* r0 = pxCurrentTCB. */
308             "                                                 \n"
309             "    dmb                                          \n" /* Complete outstanding transfers before disabling MPU. */
310             "    ldr r1, xMPUCTRLConst                        \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
311             "    ldr r2, [r1]                                 \n" /* Read the value of MPU_CTRL. */
312             "    bic r2, #1                                   \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
313             "    str r2, [r1]                                 \n" /* Disable MPU. */
314             "                                                 \n"
315             "    adds r0, #4                                  \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
316             "    ldr r1, [r0]                                 \n" /* r1 = *r0 i.e. r1 = MAIR0. */
317             "    ldr r2, xMAIR0Const                          \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
318             "    str r1, [r2]                                 \n" /* Program MAIR0. */
319             "                                                 \n"
320             "    adds r0, #4                                  \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
321             "    ldr r1, xRNRConst                            \n" /* r1 = 0xe000ed98 [Location of RNR]. */
322             "    ldr r2, xRBARConst                           \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
323             "                                                 \n"
324             "    movs r3, #4                                  \n" /* r3 = 4. */
325             "    str r3, [r1]                                 \n" /* Program RNR = 4. */
326             "    ldmia r0!, {r4-r11}                          \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
327             "    stmia r2, {r4-r11}                           \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
328             "                                                 \n"
329             #if ( configTOTAL_MPU_REGIONS == 16 )
330                 "    movs r3, #8                                  \n" /* r3 = 8. */
331                 "    str r3, [r1]                                 \n" /* Program RNR = 8. */
332                 "    ldmia r0!, {r4-r11}                          \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
333                 "    stmia r2, {r4-r11}                           \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
334                 "    movs r3, #12                                 \n" /* r3 = 12. */
335                 "    str r3, [r1]                                 \n" /* Program RNR = 12. */
336                 "    ldmia r0!, {r4-r11}                          \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
337                 "    stmia r2, {r4-r11}                           \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
338             #endif /* configTOTAL_MPU_REGIONS == 16 */
339             "                                                 \n"
340             "   ldr r1, xMPUCTRLConst                         \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
341             "   ldr r2, [r1]                                  \n" /* Read the value of MPU_CTRL. */
342             "   orr r2, #1                                    \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
343             "   str r2, [r1]                                  \n" /* Enable MPU. */
344             "   dsb                                           \n" /* Force memory writes before continuing. */
345             "                                                 \n"
346             " restore_context:                                \n"
347             "    ldr r2, pxCurrentTCBConst                    \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
348             "    ldr r0, [r2]                                 \n" /* r0 = pxCurrentTCB.*/
349             "    ldr r1, [r0]                                 \n" /* r1 = Location of saved context in TCB. */
350             "                                                 \n"
351             " restore_special_regs:                           \n"
352             "    ldmdb r1!, {r2-r4, lr}                       \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
353             "    msr psp, r2                                  \n"
354             "    msr psplim, r3                               \n"
355             "    msr control, r4                              \n"
356             "                                                 \n"
357             " restore_general_regs:                           \n"
358             "    ldmdb r1!, {r4-r11}                          \n" /* r4-r11 contain hardware saved context. */
359             "    stmia r2!, {r4-r11}                          \n" /* Copy the hardware saved context on the task stack. */
360             "    ldmdb r1!, {r4-r11}                          \n" /* r4-r11 restored. */
361             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
362                 "    tst lr, #0x10                                \n"
363                 "    ittt eq                                      \n"
364                 "    vldmdbeq r1!, {s0-s16}                       \n" /* s0-s16 contain hardware saved FP context. */
365                 "    vstmiaeq r2!, {s0-s16}                       \n" /* Copy hardware saved FP context on the task stack. */
366                 "    vldmdbeq r1!, {s16-s31}                      \n" /* Restore s16-s31. */
367             #endif /* configENABLE_FPU || configENABLE_MVE */
368             "                                                 \n"
369             " restore_context_done:                           \n"
370             "    str r1, [r0]                                 \n" /* Save the location where the context should be saved next as the first member of TCB. */
371             "    bx lr                                        \n"
372             "                                                 \n"
373             " .align 4                                        \n"
374             " pxCurrentTCBConst: .word pxCurrentTCB           \n"
375             " xMPUCTRLConst: .word 0xe000ed94                 \n"
376             " xMAIR0Const: .word 0xe000edc0                   \n"
377             " xRNRConst: .word 0xe000ed98                     \n"
378             " xRBARConst: .word 0xe000ed9c                    \n"
379             ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
380         );
381     }
382 
383 #else /* configENABLE_MPU */
384 
PendSV_Handler(void)385     void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
386     {
387         __asm volatile
388         (
389             "   .syntax unified                                 \n"
390             "                                                   \n"
391             "   mrs r0, psp                                     \n" /* Read PSP in r0. */
392             "                                                   \n"
393             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
394                 "   tst lr, #0x10                                   \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
395                 "   it eq                                           \n"
396                 "   vstmdbeq r0!, {s16-s31}                         \n" /* Store the additional FP context registers which are not saved automatically. */
397             #endif /* configENABLE_FPU || configENABLE_MVE */
398             "                                                   \n"
399             "   mrs r2, psplim                                  \n" /* r2 = PSPLIM. */
400             "   mov r3, lr                                      \n" /* r3 = LR/EXC_RETURN. */
401             "   stmdb r0!, {r2-r11}                             \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
402             "                                                   \n"
403             "   ldr r2, pxCurrentTCBConst                       \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
404             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
405             "   str r0, [r1]                                    \n" /* Save the new top of stack in TCB. */
406             "                                                   \n"
407             "   mov r0, %0                                      \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
408             "   msr basepri, r0                                 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
409             "   dsb                                             \n"
410             "   isb                                             \n"
411             "   bl vTaskSwitchContext                           \n"
412             "   mov r0, #0                                      \n" /* r0 = 0. */
413             "   msr basepri, r0                                 \n" /* Enable interrupts. */
414             "                                                   \n"
415             "   ldr r2, pxCurrentTCBConst                       \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
416             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
417             "   ldr r0, [r1]                                    \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
418             "                                                   \n"
419             "   ldmia r0!, {r2-r11}                             \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
420             "                                                   \n"
421             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
422                 "   tst r3, #0x10                                   \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
423                 "   it eq                                           \n"
424                 "   vldmiaeq r0!, {s16-s31}                         \n" /* Restore the additional FP context registers which are not restored automatically. */
425             #endif /* configENABLE_FPU || configENABLE_MVE */
426             "                                                   \n"
427             "   msr psplim, r2                                  \n" /* Restore the PSPLIM register value for the task. */
428             "   msr psp, r0                                     \n" /* Remember the new top of stack for the task. */
429             "   bx r3                                           \n"
430             "                                                   \n"
431             "   .align 4                                        \n"
432             "pxCurrentTCBConst: .word pxCurrentTCB              \n"
433             ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
434         );
435     }
436 
437 #endif /* configENABLE_MPU */
438 /*-----------------------------------------------------------*/
439 
440 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
441 
SVC_Handler(void)442     void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
443     {
444         __asm volatile
445         (
446             ".syntax unified                \n"
447             ".extern vPortSVCHandler_C      \n"
448             ".extern vSystemCallEnter       \n"
449             ".extern vSystemCallExit        \n"
450             "                               \n"
451             "tst lr, #4                     \n"
452             "ite eq                         \n"
453             "mrseq r0, msp                  \n"
454             "mrsne r0, psp                  \n"
455             "                               \n"
456             "ldr r1, [r0, #24]              \n"
457             "ldrb r2, [r1, #-2]             \n"
458             "cmp r2, %0                     \n"
459             "blt syscall_enter              \n"
460             "cmp r2, %1                     \n"
461             "beq syscall_exit               \n"
462             "b vPortSVCHandler_C            \n"
463             "                               \n"
464             "syscall_enter:                 \n"
465             "    mov r1, lr                 \n"
466             "    b vSystemCallEnter         \n"
467             "                               \n"
468             "syscall_exit:                  \n"
469             "    mov r1, lr                 \n"
470             "    b vSystemCallExit          \n"
471             "                               \n"
472             : /* No outputs. */
473             : "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
474             : "r0", "r1", "r2", "memory"
475         );
476     }
477 
478 #else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
479 
SVC_Handler(void)480     void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
481     {
482         __asm volatile
483         (
484             "   .syntax unified                                 \n"
485             "                                                   \n"
486             "   tst lr, #4                                      \n"
487             "   ite eq                                          \n"
488             "   mrseq r0, msp                                   \n"
489             "   mrsne r0, psp                                   \n"
490             "   ldr r1, svchandler_address_const                \n"
491             "   bx r1                                           \n"
492             "                                                   \n"
493             "   .align 4                                        \n"
494             "svchandler_address_const: .word vPortSVCHandler_C  \n"
495         );
496     }
497 
498 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
499 /*-----------------------------------------------------------*/
500