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 * 2019-03-31 xuzhuoyi port to Cortex-M23. 15 */ 16 17 .cpu cortex-m23 18 .fpu softvfp 19 .syntax unified 20 .thumb 21 .text 22 23 .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ 24 .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ 25 .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ 26 .equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ 27 .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ 28 29/* 30 * rt_base_t rt_hw_interrupt_disable(); 31 */ 32 .global rt_hw_interrupt_disable 33 .type rt_hw_interrupt_disable, %function 34rt_hw_interrupt_disable: 35 MRS R0, PRIMASK 36 CPSID I 37 BX LR 38 39/* 40 * void rt_hw_interrupt_enable(rt_base_t level); 41 */ 42 .global rt_hw_interrupt_enable 43 .type rt_hw_interrupt_enable, %function 44rt_hw_interrupt_enable: 45 MSR PRIMASK, R0 46 BX LR 47 48/* 49 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 50 * R0 --> from 51 * R1 --> to 52 */ 53 .global rt_hw_context_switch_interrupt 54 .type rt_hw_context_switch_interrupt, %function 55 .global rt_hw_context_switch 56 .type rt_hw_context_switch, %function 57rt_hw_context_switch_interrupt: 58rt_hw_context_switch: 59 /* set rt_thread_switch_interrupt_flag to 1 */ 60 LDR R2, =rt_thread_switch_interrupt_flag 61 LDR R3, [R2] 62 CMP R3, #1 63 BEQ _reswitch 64 MOVS R3, #1 65 STR R3, [R2] 66 67 LDR R2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */ 68 STR R0, [R2] 69 70_reswitch: 71 LDR R2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */ 72 STR R1, [R2] 73 74 LDR R0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ 75 LDR R1, =NVIC_PENDSVSET 76 STR R1, [R0] 77 BX LR 78 79/* R0 --> switch from thread stack 80 * R1 --> switch to thread stack 81 * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack 82 */ 83 .global PendSV_Handler 84 .type PendSV_Handler, %function 85PendSV_Handler: 86 /* disable interrupt to protect context switch */ 87 MRS R2, PRIMASK 88 CPSID I 89 90 /* get rt_thread_switch_interrupt_flag */ 91 LDR R0, =rt_thread_switch_interrupt_flag 92 LDR R1, [R0] 93 CMP R1, #0x00 94 BEQ pendsv_exit /* pendsv already handled */ 95 96 /* clear rt_thread_switch_interrupt_flag to 0 */ 97 MOVS R1, #0 98 STR R1, [R0] 99 100 LDR R0, =rt_interrupt_from_thread 101 LDR R1, [R0] 102 CMP R1, #0x00 103 BEQ switch_to_thread /* skip register save at the first time */ 104 105 MRS R1, PSP /* get from thread stack pointer */ 106 107 SUBS R1, R1, #0x20 /* space for {R4 - R7} and {R8 - R11} */ 108 LDR R0, [R0] 109 STR R1, [R0] /* update from thread stack pointer */ 110 111 STMIA R1!, {R4 - R7} /* push thread {R4 - R7} register to thread stack */ 112 113 MOV R4, R8 /* mov thread {R8 - R11} to {R4 - R7} */ 114 MOV R5, R9 115 MOV R6, R10 116 MOV R7, R11 117 STMIA R1!, {R4 - R7} /* push thread {R8 - R11} high register to thread stack */ 118switch_to_thread: 119 LDR R1, =rt_interrupt_to_thread 120 LDR R1, [R1] 121 LDR R1, [R1] /* load thread stack pointer */ 122 123 LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ 124 PUSH {R4 - R7} /* push {R4 - R7} to MSP for copy {R8 - R11} */ 125 126 LDMIA R1!, {R4 - R7} /* pop thread {R8 - R11} high register from thread stack to {R4 - R7} */ 127 MOV R8, R4 /* mov {R4 - R7} to {R8 - R11} */ 128 MOV R9, R5 129 MOV R10, R6 130 MOV R11, R7 131 132 POP {R4 - R7} /* pop {R4 - R7} from MSP */ 133 134 MSR PSP, R1 /* update stack pointer */ 135 136pendsv_exit: 137 /* restore interrupt */ 138 MSR PRIMASK, R2 139 140 MOVS R0, #0x03 141 RSBS R0, R0, #0x00 142 BX R0 143/* 144 * void rt_hw_context_switch_to(rt_uint32 to); 145 * R0 --> to 146 */ 147 .global rt_hw_context_switch_to 148 .type rt_hw_context_switch_to, %function 149rt_hw_context_switch_to: 150 LDR R1, =rt_interrupt_to_thread 151 STR R0, [R1] 152 153 /* set from thread to 0 */ 154 LDR R1, =rt_interrupt_from_thread 155 MOVS R0, #0 156 STR R0, [R1] 157 158 /* set interrupt flag to 1 */ 159 LDR R1, =rt_thread_switch_interrupt_flag 160 MOVS R0, #1 161 STR R0, [R1] 162 163 /* set the PendSV and SysTick exception priority */ 164 LDR R0, =NVIC_SHPR3 165 LDR R1, =NVIC_PENDSV_PRI 166 LDR R2, [R0,#0x00] /* read */ 167 ORRS R1, R1, R2 /* modify */ 168 STR R1, [R0] /* write-back */ 169 170 LDR R0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ 171 LDR R1, =NVIC_PENDSVSET 172 STR R1, [R0] 173 NOP 174 /* restore MSP */ 175 LDR R0, =SCB_VTOR 176 LDR R0, [R0] 177 LDR R0, [R0] 178 NOP 179 MSR MSP, R0 180 181 /* enable interrupts at processor level */ 182 CPSIE I 183 184 /* ensure PendSV exception taken place before subsequent operation */ 185 DSB 186 ISB 187 188 /* never reach here! */ 189 190/* compatible with old version */ 191 .global rt_hw_interrupt_thread_switch 192 .type rt_hw_interrupt_thread_switch, %function 193rt_hw_interrupt_thread_switch: 194 BX LR 195 NOP 196 197 .global HardFault_Handler 198 .type HardFault_Handler, %function 199HardFault_Handler: 200 /* get current context */ 201 MRS R0, PSP /* get fault thread stack pointer */ 202 PUSH {LR} 203 BL rt_hw_hard_fault_exception 204 POP {PC} 205 206 207/* 208 * rt_uint32_t rt_hw_interrupt_check(void); 209 * R0 --> state 210 */ 211 .global rt_hw_interrupt_check 212 .type rt_hw_interrupt_check, %function 213rt_hw_interrupt_check: 214 MRS R0, IPSR 215 BX LR 216