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