|
| 1 | +;/* |
| 2 | +; * Copyright (c) 2016-2017 ARM Limited. All rights reserved. |
| 3 | +; * |
| 4 | +; * SPDX-License-Identifier: Apache-2.0 |
| 5 | +; * |
| 6 | +; * Licensed under the Apache License, Version 2.0 (the License); you may |
| 7 | +; * not use this file except in compliance with the License. |
| 8 | +; * You may obtain a copy of the License at |
| 9 | +; * |
| 10 | +; * www.apache.org/licenses/LICENSE-2.0 |
| 11 | +; * |
| 12 | +; * Unless required by applicable law or agreed to in writing, software |
| 13 | +; * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
| 14 | +; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | +; * See the License for the specific language governing permissions and |
| 16 | +; * limitations under the License. |
| 17 | +; * |
| 18 | +; * ----------------------------------------------------------------------------- |
| 19 | +; * |
| 20 | +; * Project: CMSIS-RTOS RTX |
| 21 | +; * Title: ARMv8M Baseline Exception handlers |
| 22 | +; * |
| 23 | +; * ----------------------------------------------------------------------------- |
| 24 | +; */ |
| 25 | + |
| 26 | + |
| 27 | + .file "irq_armv8mbl.S" |
| 28 | + .syntax unified |
| 29 | + |
| 30 | + .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset |
| 31 | + .equ TCB_SM_OFS, 48 // TCB.stack_mem offset |
| 32 | + .equ TCB_SP_OFS, 56 // TCB.SP offset |
| 33 | + .equ TCB_SF_OFS, 34 // TCB.stack_frame offset |
| 34 | + .equ TCB_TZM_OFS, 64 // TCB.tz_memory offset |
| 35 | + |
| 36 | + .section ".rodata" |
| 37 | + .global irqRtxLib // Non weak library reference |
| 38 | +irqRtxLib: |
| 39 | + .byte 0 |
| 40 | + |
| 41 | + |
| 42 | + .thumb |
| 43 | + .section ".text" |
| 44 | + .align 2 |
| 45 | + |
| 46 | + |
| 47 | + .thumb_func |
| 48 | + .type SVC_Handler, %function |
| 49 | + .global SVC_Handler |
| 50 | + .fnstart |
| 51 | + .cantunwind |
| 52 | +SVC_Handler: |
| 53 | + MRS R0,PSP // Get PSP |
| 54 | + LDR R1,[R0,#24] // Load saved PC from stack |
| 55 | + SUBS R1,R1,#2 // Point to SVC instruction |
| 56 | + LDRB R1,[R1] // Load SVC number |
| 57 | + CMP R1,#0 |
| 58 | + BNE SVC_User // Branch if not SVC 0 |
| 59 | + |
| 60 | + PUSH {R0,LR} // Save PSP and EXC_RETURN |
| 61 | + LDM R0,{R0-R3} // Load function parameters from stack |
| 62 | + BLX R7 // Call service function |
| 63 | + POP {R2,R3} // Restore PSP and EXC_RETURN |
| 64 | + STMIA R2!,{R0-R1} // Store function return values |
| 65 | + MOV LR,R3 // Set EXC_RETURN |
| 66 | + |
| 67 | +SVC_Context: |
| 68 | + LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run |
| 69 | + LDMIA R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next |
| 70 | + CMP R1,R2 // Check if thread switch is required |
| 71 | + BEQ SVC_Exit // Branch when threads are the same |
| 72 | + |
| 73 | + CBZ R1,SVC_ContextSwitch // Branch if running thread is deleted |
| 74 | + |
| 75 | +SVC_ContextSave: |
| 76 | +#ifdef __DOMAIN_NS |
| 77 | + LDR R0,[R1,#TCB_TZM_OFS] // Load TrustZone memory identifier |
| 78 | + CBZ R0,SVC_ContextSave1 // Branch if there is no secure context |
| 79 | + PUSH {R1,R2,R3,R7} // Save registers |
| 80 | + MOV R7,LR // Get EXC_RETURN |
| 81 | + BL TZ_StoreContext_S // Store secure context |
| 82 | + MOV LR,R7 // Set EXC_RETURN |
| 83 | + POP {R1,R2,R3,R7} // Restore registers |
| 84 | +#endif |
| 85 | + |
| 86 | +SVC_ContextSave1: |
| 87 | + MRS R0,PSP // Get PSP |
| 88 | + SUBS R0,R0,#32 // Adjust PSP |
| 89 | + STR R0,[R1,#TCB_SP_OFS] // Store SP |
| 90 | + STMIA R0!,{R4-R7} // Save R4..R7 |
| 91 | + MOV R4,R8 |
| 92 | + MOV R5,R9 |
| 93 | + MOV R6,R10 |
| 94 | + MOV R7,R11 |
| 95 | + STMIA R0!,{R4-R7} // Save R8..R11 |
| 96 | + |
| 97 | +SVC_ContextSave2: |
| 98 | + MOV R0,LR // Get EXC_RETURN |
| 99 | + ADDS R1,R1,#TCB_SF_OFS // Adjust address |
| 100 | + STRB R0,[R1] // Store stack frame information |
| 101 | + |
| 102 | +SVC_ContextSwitch: |
| 103 | + SUBS R3,R3,#8 // Adjust address |
| 104 | + STR R2,[R3] // osRtxInfo.thread.run: curr = next |
| 105 | + |
| 106 | +SVC_ContextRestore: |
| 107 | +#ifdef __DOMAIN_NS |
| 108 | + LDR R0,[R2,#TCB_TZM_OFS] // Load TrustZone memory identifier |
| 109 | + CBZ R0,SVC_ContextRestore1 // Branch if there is no secure context |
| 110 | + PUSH {R2,R3} // Save registers |
| 111 | + BL TZ_LoadContext_S // Load secure context |
| 112 | + POP {R2,R3} // Restore registers |
| 113 | +#endif |
| 114 | + |
| 115 | +SVC_ContextRestore1: |
| 116 | + MOV R1,R2 |
| 117 | + ADDS R1,R1,#TCB_SF_OFS // Adjust address |
| 118 | + LDRB R0,[R1] // Load stack frame information |
| 119 | + MOVS R1,#0xFF |
| 120 | + MVNS R1,R1 // R1=0xFFFFFF00 |
| 121 | + ORRS R0,R1 |
| 122 | + MOV LR,R0 // Set EXC_RETURN |
| 123 | + |
| 124 | +#ifdef __DOMAIN_NS |
| 125 | + LSLS R0,R0,#25 // Check domain of interrupted thread |
| 126 | + BPL SVC_ContextRestore2 // Branch if non-secure |
| 127 | + LDR R0,[R2,#TCB_SP_OFS] // Load SP |
| 128 | + MSR PSP,R0 // Set PSP |
| 129 | + BX LR // Exit from handler |
| 130 | +#else |
| 131 | + LDR R0,[R2,#TCB_SM_OFS] // Load stack memory base |
| 132 | + MSR PSPLIM,R0 // Set PSPLIM |
| 133 | +#endif |
| 134 | + |
| 135 | +SVC_ContextRestore2: |
| 136 | + LDR R0,[R2,#TCB_SP_OFS] // Load SP |
| 137 | + ADDS R0,R0,#16 // Adjust address |
| 138 | + LDMIA R0!,{R4-R7} // Restore R8..R11 |
| 139 | + MOV R8,R4 |
| 140 | + MOV R9,R5 |
| 141 | + MOV R10,R6 |
| 142 | + MOV R11,R7 |
| 143 | + MSR PSP,R0 // Set PSP |
| 144 | + SUBS R0,R0,#32 // Adjust address |
| 145 | + LDMIA R0!,{R4-R7} // Restore R4..R7 |
| 146 | + |
| 147 | +SVC_Exit: |
| 148 | + BX LR // Exit from handler |
| 149 | + |
| 150 | +SVC_User: |
| 151 | + PUSH {R4,LR} // Save registers |
| 152 | + LDR R2,=osRtxUserSVC // Load address of SVC table |
| 153 | + LDR R3,[R2] // Load SVC maximum number |
| 154 | + CMP R1,R3 // Check SVC number range |
| 155 | + BHI SVC_Done // Branch if out of range |
| 156 | + |
| 157 | + LSLS R1,R1,#2 |
| 158 | + LDR R4,[R2,R1] // Load address of SVC function |
| 159 | + |
| 160 | + LDM R0,{R0-R3} // Load function parameters from stack |
| 161 | + BLX R4 // Call service function |
| 162 | + MRS R4,PSP // Get PSP |
| 163 | + STR R0,[R4] // Store function return value |
| 164 | + |
| 165 | +SVC_Done: |
| 166 | + POP {R4,PC} // Return from handler |
| 167 | + |
| 168 | + .fnend |
| 169 | + .size SVC_Handler, .-SVC_Handler |
| 170 | + |
| 171 | + |
| 172 | + .thumb_func |
| 173 | + .type PendSV_Handler, %function |
| 174 | + .global PendSV_Handler |
| 175 | + .fnstart |
| 176 | + .cantunwind |
| 177 | +PendSV_Handler: |
| 178 | + |
| 179 | + PUSH {R0,LR} // Save EXC_RETURN |
| 180 | + BL osRtxPendSV_Handler // Call osRtxPendSV_Handler |
| 181 | + POP {R0,R1} // Restore EXC_RETURN |
| 182 | + MOV LR,R1 // Set EXC_RETURN |
| 183 | + B Sys_Context |
| 184 | + |
| 185 | + .fnend |
| 186 | + .size PendSV_Handler, .-PendSV_Handler |
| 187 | + |
| 188 | + |
| 189 | + .thumb_func |
| 190 | + .type SysTick_Handler, %function |
| 191 | + .global SysTick_Handler |
| 192 | + .fnstart |
| 193 | + .cantunwind |
| 194 | +SysTick_Handler: |
| 195 | + |
| 196 | + PUSH {R0,LR} // Save EXC_RETURN |
| 197 | + BL osRtxTick_Handler // Call osRtxTick_Handler |
| 198 | + POP {R0,R1} // Restore EXC_RETURN |
| 199 | + MOV LR,R1 // Set EXC_RETURN |
| 200 | + B Sys_Context |
| 201 | + |
| 202 | + .fnend |
| 203 | + .size SysTick_Handler, .-SysTick_Handler |
| 204 | + |
| 205 | + |
| 206 | + .thumb_func |
| 207 | + .type Sys_Context, %function |
| 208 | + .global Sys_Context |
| 209 | + .fnstart |
| 210 | + .cantunwind |
| 211 | +Sys_Context: |
| 212 | + |
| 213 | + LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run |
| 214 | + LDM R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next |
| 215 | + CMP R1,R2 // Check if thread switch is required |
| 216 | + BEQ Sys_ContextExit // Branch when threads are the same |
| 217 | + |
| 218 | +Sys_ContextSave: |
| 219 | +#ifdef __DOMAIN_NS |
| 220 | + LDR R0,[R1,#TCB_TZM_OFS] // Load TrustZone memory identifier |
| 221 | + CBZ R0,Sys_ContextSave1 // Branch if there is no secure context |
| 222 | + PUSH {R1,R2,R3,R7} // Save registers |
| 223 | + MOV R7,LR // Get EXC_RETURN |
| 224 | + BL TZ_StoreContext_S // Store secure context |
| 225 | + MOV LR,R7 // Set EXC_RETURN |
| 226 | + POP {R1,R2,R3,R7} // Restore registers |
| 227 | + LSLS R7,R7,#25 // Check domain of interrupted thread |
| 228 | + BMI Sys_ContextSave1 // Branch if secure |
| 229 | + MRS R0,PSP // Get PSP |
| 230 | + STR R0,[R1,#TCB_SP_OFS] // Store SP |
| 231 | + B Sys_ContextSave2 |
| 232 | +#endif |
| 233 | + |
| 234 | +Sys_ContextSave1: |
| 235 | + MRS R0,PSP // Get PSP |
| 236 | + SUBS R0,R0,#32 // Adjust address |
| 237 | + STR R0,[R1,#TCB_SP_OFS] // Store SP |
| 238 | + STMIA R0!,{R4-R7} // Save R4..R7 |
| 239 | + MOV R4,R8 |
| 240 | + MOV R5,R9 |
| 241 | + MOV R6,R10 |
| 242 | + MOV R7,R11 |
| 243 | + STMIA R0!,{R4-R7} // Save R8..R11 |
| 244 | + |
| 245 | +Sys_ContextSave2: |
| 246 | + MOV R0,LR // Get EXC_RETURN |
| 247 | + ADDS R1,R1,#TCB_SF_OFS // Adjust address |
| 248 | + STRB R0,[R1] // Store stack frame information |
| 249 | + |
| 250 | +Sys_ContextSwitch: |
| 251 | + SUBS R3,R3,#8 // Adjust address |
| 252 | + STR R2,[R3] // osRtxInfo.run: curr = next |
| 253 | + |
| 254 | +Sys_ContextRestore: |
| 255 | +#ifdef __DOMAIN_NS |
| 256 | + LDR R0,[R2,#TCB_TZM_OFS] // Load TrustZone memory identifier |
| 257 | + CBZ R0,Sys_ContextRestore1 // Branch if there is no secure context |
| 258 | + PUSH {R2,R3} // Save registers |
| 259 | + BL TZ_LoadContext_S // Load secure context |
| 260 | + POP {R2,R3} // Restore registers |
| 261 | +#endif |
| 262 | + |
| 263 | +Sys_ContextRestore1: |
| 264 | + MOV R1,R2 |
| 265 | + ADDS R1,R1,#TCB_SF_OFS // Adjust offset |
| 266 | + LDRB R0,[R1] // Load stack frame information |
| 267 | + MOVS R1,#0xFF |
| 268 | + MVNS R1,R1 // R1=0xFFFFFF00 |
| 269 | + ORRS R0,R1 |
| 270 | + MOV LR,R0 // Set EXC_RETURN |
| 271 | + |
| 272 | +#ifdef __DOMAIN_NS |
| 273 | + LSLS R0,R0,#25 // Check domain of interrupted thread |
| 274 | + BPL Sys_ContextRestore2 // Branch if non-secure |
| 275 | + LDR R0,[R2,#TCB_SP_OFS] // Load SP |
| 276 | + MSR PSP,R0 // Set PSP |
| 277 | + BX LR // Exit from handler |
| 278 | +#else |
| 279 | + LDR R0,[R2,#TCB_SM_OFS] // Load stack memory base |
| 280 | + MSR PSPLIM,R0 // Set PSPLIM |
| 281 | +#endif |
| 282 | + |
| 283 | +Sys_ContextRestore2: |
| 284 | + LDR R0,[R2,#TCB_SP_OFS] // Load SP |
| 285 | + ADDS R0,R0,#16 // Adjust address |
| 286 | + LDMIA R0!,{R4-R7} // Restore R8..R11 |
| 287 | + MOV R8,R4 |
| 288 | + MOV R9,R5 |
| 289 | + MOV R10,R6 |
| 290 | + MOV R11,R7 |
| 291 | + MSR PSP,R0 // Set PSP |
| 292 | + SUBS R0,R0,#32 // Adjust address |
| 293 | + LDMIA R0!,{R4-R7} // Restore R4..R7 |
| 294 | + |
| 295 | +Sys_ContextExit: |
| 296 | + BX LR // Exit from handler |
| 297 | + |
| 298 | + .fnend |
| 299 | + .size Sys_Context, .-Sys_Context |
| 300 | + |
| 301 | + |
| 302 | + .end |
0 commit comments