1/* 2 * Copyright (c) 2006-2022, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2010-01-25 Bernard first version 9 * 2012-06-01 aozima set pendsv priority to 0xFF. 10 * 2012-08-17 aozima fixed bug: store r8 - r11. 11 * 2013-02-20 aozima port to gcc. 12 * 2013-06-18 aozima add restore MSP feature. 13 * 2013-11-04 bright fixed hardfault bug for gcc. 14 */ 15 16 .cpu cortex-m0 17 .fpu softvfp 18 .syntax unified 19 .thumb 20 .text 21 22 .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ 23 .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ 24 .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ 25 .equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ 26 .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ 27 28#include "../rtconfig.h" 29 30#ifdef RT_USING_SMP 31 .equ SIO_CPUID, 0xd0000000 /* CPUID */ 32 #define rt_hw_interrupt_disable rt_hw_local_irq_disable 33 #define rt_hw_interrupt_enable rt_hw_local_irq_enable 34#endif 35 36/* 37 * rt_base_t rt_hw_interrupt_disable(); 38 */ 39 .global rt_hw_interrupt_disable 40 .type rt_hw_interrupt_disable, %function 41rt_hw_interrupt_disable: 42 MRS R0, PRIMASK 43 CPSID I 44 BX LR 45 46/* 47 * void rt_hw_interrupt_enable(rt_base_t level); 48 */ 49 .global rt_hw_interrupt_enable 50 .type rt_hw_interrupt_enable, %function 51rt_hw_interrupt_enable: 52 MSR PRIMASK, R0 53 BX LR 54 55/* 56 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 57 * R0 --> from 58 * R1 --> to 59 */ 60 .global rt_hw_context_switch_interrupt 61 .type rt_hw_context_switch_interrupt, %function 62 .global rt_hw_context_switch 63 .type rt_hw_context_switch, %function 64rt_hw_context_switch_interrupt: 65rt_hw_context_switch: 66#ifndef RT_USING_SMP 67 /* set rt_thread_switch_interrupt_flag to 1 */ 68 LDR R2, =rt_thread_switch_interrupt_flag 69 LDR R3, [R2] 70 CMP R3, #1 71 BEQ _reswitch 72 MOVS R3, #1 73 STR R3, [R2] 74 75 LDR R2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */ 76 STR R0, [R2] 77 78_reswitch: 79 LDR R2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */ 80 STR R1, [R2] 81#else 82 /* context_switch_to smp */ 83 PUSH {LR} 84 BL __rt_cpu_switch 85 POP {R2} 86#endif 87 88 LDR R0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ 89 LDR R1, =NVIC_PENDSVSET 90 STR R1, [R0] 91#ifndef RT_USING_SMP 92 BX LR 93#else 94 BX R2 95#endif 96 97/* R0 --> switch from thread stack 98 * R1 --> switch to thread stack 99 * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack 100 */ 101 .global PendSV_Handler 102 .type PendSV_Handler, %function 103PendSV_Handler: 104 /* disable interrupt to protect context switch */ 105 MRS R2, PRIMASK 106 CPSID I 107 108#ifndef RT_USING_SMP 109 /* get rt_thread_switch_interrupt_flag */ 110 LDR R0, =rt_thread_switch_interrupt_flag 111#else 112 LDR R0, =SIO_CPUID 113 LDR R1, [R0] 114 LDR R3, =rt_thread_switch_array 115 CMP R1, #0 116 BEQ cpu0_info 117 ADDS R3, #12 118cpu0_info: 119 MOV R0, R3 120#endif 121 LDR R1, [R0] 122 123 CMP R1, #0x00 124 BEQ pendsv_exit /* pendsv already handled */ 125 126 /* clear rt_thread_switch_interrupt_flag to 0 */ 127 MOVS R1, #0 128 STR R1, [R0] 129 130#ifndef RT_USING_SMP 131 LDR R0, =rt_interrupt_from_thread 132#else 133 ADDS R0, #4 134#endif 135 LDR R1, [R0] 136 137 CMP R1, #0x00 138 BEQ switch_to_thread /* skip register save at the first time */ 139 140 MRS R1, PSP /* get from thread stack pointer */ 141 142 SUBS R1, R1, #0x20 /* space for {R4 - R7} and {R8 - R11} */ 143 LDR R0, [R0] 144 STR R1, [R0] /* update from thread stack pointer */ 145 146 STMIA R1!, {R4 - R7} /* push thread {R4 - R7} register to thread stack */ 147 148 MOV R4, R8 /* mov thread {R8 - R11} to {R4 - R7} */ 149 MOV R5, R9 150 MOV R6, R10 151 MOV R7, R11 152 STMIA R1!, {R4 - R7} /* push thread {R8 - R11} high register to thread stack */ 153switch_to_thread: 154 155#ifndef RT_USING_SMP 156 LDR R1, =rt_interrupt_to_thread 157#else 158 MOV R1, R3 159 ADDS R1, #8 160#endif 161 LDR R1, [R1] 162 163 LDR R1, [R1] /* load thread stack pointer */ 164 165 LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ 166 PUSH {R4 - R7} /* push {R4 - R7} to MSP for copy {R8 - R11} */ 167 168 LDMIA R1!, {R4 - R7} /* pop thread {R8 - R11} high register from thread stack to {R4 - R7} */ 169 MOV R8, R4 /* mov {R4 - R7} to {R8 - R11} */ 170 MOV R9, R5 171 MOV R10, R6 172 MOV R11, R7 173 174 POP {R4 - R7} /* pop {R4 - R7} from MSP */ 175 176 MSR PSP, R1 /* update stack pointer */ 177 178pendsv_exit: 179 /* restore interrupt */ 180 MSR PRIMASK, R2 181 182 MOVS R0, #0x03 183 RSBS R0, R0, #0x00 184 BX R0 185/* 186 * void rt_hw_context_switch_to(rt_uint32 to); 187 * R0 --> to 188 */ 189 .global rt_hw_context_switch_to 190 .type rt_hw_context_switch_to, %function 191rt_hw_context_switch_to: 192#ifndef RT_USING_SMP 193 LDR R1, =rt_interrupt_to_thread 194 STR R0, [R1] 195 196 /* set from thread to 0 */ 197 LDR R1, =rt_interrupt_from_thread 198 MOVS R0, #0 199 STR R0, [R1] 200 201 /* set interrupt flag to 1 */ 202 LDR R1, =rt_thread_switch_interrupt_flag 203 MOVS R0, #1 204 STR R0, [R1] 205#else 206 /* context_switch_to smp */ 207 MOV R2,R1 208 MOV R1,R0 209 MOVS R0,#0 210 BL __rt_cpu_switch 211#endif 212 213 /* set the PendSV and SysTick exception priority */ 214 LDR R0, =NVIC_SHPR3 215 LDR R1, =NVIC_PENDSV_PRI 216 LDR R2, [R0,#0x00] /* read */ 217 ORRS R1, R1, R2 /* modify */ 218 STR R1, [R0] /* write-back */ 219 220 LDR R0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ 221 LDR R1, =NVIC_PENDSVSET 222 STR R1, [R0] 223 NOP 224 /* restore MSP */ 225 LDR R0, =SCB_VTOR 226 LDR R0, [R0] 227 LDR R0, [R0] 228 NOP 229 MSR MSP, R0 230 231 /* enable interrupts at processor level */ 232 CPSIE I 233 234 /* ensure PendSV exception taken place before subsequent operation */ 235 DSB 236 ISB 237 238 /* never reach here! */ 239 240/* compatible with old version */ 241 .global rt_hw_interrupt_thread_switch 242 .type rt_hw_interrupt_thread_switch, %function 243rt_hw_interrupt_thread_switch: 244 BX LR 245 NOP 246 247 .global HardFault_Handler 248 .type HardFault_Handler, %function 249HardFault_Handler: 250 /* get current context */ 251 MRS R0, PSP /* get fault thread stack pointer */ 252 PUSH {LR} 253 BL rt_hw_hard_fault_exception 254 POP {PC} 255 256 257/* 258 * rt_uint32_t rt_hw_interrupt_check(void); 259 * R0 --> state 260 */ 261 .global rt_hw_interrupt_check 262 .type rt_hw_interrupt_check, %function 263rt_hw_interrupt_check: 264 MRS R0, IPSR 265 BX LR 266