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