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 29#include "FreeRTOSConfig.h" 30 31 SECTION .text:CODE:ROOT(2) 32 arm 33 34 /* Variables and functions. */ 35 EXTERN pxCurrentTCB 36 EXTERN vTaskSwitchContext 37 EXTERN vApplicationIRQHandler 38 EXTERN ulPortInterruptNesting 39 EXTERN ulPortTaskHasFPUContext 40 EXTERN ulPortYieldRequired 41 EXTERN ulCriticalNesting 42 43 PUBLIC FreeRTOS_IRQ_Handler 44 PUBLIC FreeRTOS_SVC_Handler 45 PUBLIC vPortRestoreTaskContext 46 47SYS_MODE EQU 0x1f 48SVC_MODE EQU 0x13 49IRQ_MODE EQU 0x12 50 51portSAVE_CONTEXT MACRO 52 53 /* Save the LR and SPSR onto the system mode stack before switching to 54 system mode to save the remaining system mode registers. */ 55 SRSDB sp!, #SYS_MODE 56 CPS #SYS_MODE 57 PUSH {R0-R12, R14} 58 59 /* Push the critical nesting count. */ 60 LDR R2, =ulCriticalNesting 61 LDR R1, [R2] 62 PUSH {R1} 63 64 /* Does the task have a floating point context that needs saving? If 65 ulPortTaskHasFPUContext is 0 then no. */ 66 LDR R2, =ulPortTaskHasFPUContext 67 LDR R3, [R2] 68 CMP R3, #0 69 70 /* Save the floating point context, if any. */ 71 FMRXNE R1, FPSCR 72 VPUSHNE {D0-D15} 73#if configFPU_D32 == 1 74 VPUSHNE {D16-D31} 75#endif /* configFPU_D32 */ 76 PUSHNE {R1} 77 78 /* Save ulPortTaskHasFPUContext itself. */ 79 PUSH {R3} 80 81 /* Save the stack pointer in the TCB. */ 82 LDR R0, =pxCurrentTCB 83 LDR R1, [R0] 84 STR SP, [R1] 85 86 ENDM 87 88; /**********************************************************************/ 89 90portRESTORE_CONTEXT MACRO 91 92 /* Set the SP to point to the stack of the task being restored. */ 93 LDR R0, =pxCurrentTCB 94 LDR R1, [R0] 95 LDR SP, [R1] 96 97 /* Is there a floating point context to restore? If the restored 98 ulPortTaskHasFPUContext is zero then no. */ 99 LDR R0, =ulPortTaskHasFPUContext 100 POP {R1} 101 STR R1, [R0] 102 CMP R1, #0 103 104 /* Restore the floating point context, if any. */ 105 POPNE {R0} 106#if configFPU_D32 == 1 107 VPOPNE {D16-D31} 108#endif /* configFPU_D32 */ 109 VPOPNE {D0-D15} 110 VMSRNE FPSCR, R0 111 112 /* Restore the critical section nesting depth. */ 113 LDR R0, =ulCriticalNesting 114 POP {R1} 115 STR R1, [R0] 116 117 /* Restore all system mode registers other than the SP (which is already 118 being used). */ 119 POP {R0-R12, R14} 120 121 /* Return to the task code, loading CPSR on the way. */ 122 RFEIA sp! 123 124 ENDM 125 126 127 128 129/****************************************************************************** 130 * SVC handler is used to yield. 131 *****************************************************************************/ 132FreeRTOS_SVC_Handler: 133 /* Save the context of the current task and select a new task to run. */ 134 portSAVE_CONTEXT 135 LDR R0, =vTaskSwitchContext 136 BLX R0 137 portRESTORE_CONTEXT 138 139 140/****************************************************************************** 141 * vPortRestoreTaskContext is used to start the scheduler. 142 *****************************************************************************/ 143vPortRestoreTaskContext: 144 /* Switch to system mode. */ 145 CPS #SYS_MODE 146 portRESTORE_CONTEXT 147 148FreeRTOS_IRQ_Handler: 149 /* Return to the interrupted instruction. */ 150 SUB lr, lr, #4 151 152 /* Push the return address and SPSR. */ 153 PUSH {lr} 154 MRS lr, SPSR 155 PUSH {lr} 156 157 /* Change to supervisor mode to allow reentry. */ 158 CPS #SVC_MODE 159 160 /* Push used registers. */ 161 PUSH {r0-r3, r12} 162 163 /* Increment nesting count. r3 holds the address of ulPortInterruptNesting 164 for future use. r1 holds the original ulPortInterruptNesting value for 165 future use. */ 166 LDR r3, =ulPortInterruptNesting 167 LDR r1, [r3] 168 ADD r0, r1, #1 169 STR r0, [r3] 170 171 /* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for 172 future use. */ 173 MOV r0, sp 174 AND r2, r0, #4 175 SUB sp, sp, r2 176 177 /* Call the interrupt handler. */ 178 PUSH {r0-r3, lr} 179 LDR r1, =vApplicationIRQHandler 180 BLX r1 181 POP {r0-r3, lr} 182 ADD sp, sp, r2 183 184 CPSID i 185 DSB 186 ISB 187 188 /* Write to the EOI register. */ 189 LDR r2, =configEOI_ADDRESS 190 STR r0, [r2] 191 192 /* Restore the old nesting count. */ 193 STR r1, [r3] 194 195 /* A context switch is never performed if the nesting count is not 0. */ 196 CMP r1, #0 197 BNE exit_without_switch 198 199 /* Did the interrupt request a context switch? r1 holds the address of 200 ulPortYieldRequired and r0 the value of ulPortYieldRequired for future 201 use. */ 202 LDR r1, =ulPortYieldRequired 203 LDR r0, [r1] 204 CMP r0, #0 205 BNE switch_before_exit 206 207exit_without_switch: 208 /* No context switch. Restore used registers, LR_irq and SPSR before 209 returning. */ 210 POP {r0-r3, r12} 211 CPS #IRQ_MODE 212 POP {LR} 213 MSR SPSR_cxsf, LR 214 POP {LR} 215 MOVS PC, LR 216 217switch_before_exit: 218 /* A context swtich is to be performed. Clear the context switch pending 219 flag. */ 220 MOV r0, #0 221 STR r0, [r1] 222 223 /* Restore used registers, LR-irq and SPSR before saving the context 224 to the task stack. */ 225 POP {r0-r3, r12} 226 CPS #IRQ_MODE 227 POP {LR} 228 MSR SPSR_cxsf, LR 229 POP {LR} 230 portSAVE_CONTEXT 231 232 /* Call the function that selects the new task to execute. 233 vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD 234 instructions, or 8 byte aligned stack allocated data. LR does not need 235 saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */ 236 LDR R0, =vTaskSwitchContext 237 BLX R0 238 239 /* Restore the context of, and branch to, the task selected to execute 240 next. */ 241 portRESTORE_CONTEXT 242 243 END 244