1;/* 2; * Copyright (c) 2006-2018, RT-Thread Development Team 3; * 4; * SPDX-License-Identifier: Apache-2.0 5; * 6; * Change Logs: 7; * Date Author Notes 8; * 2009-01-17 Bernard first version 9; * 2009-09-27 Bernard add protect when contex switch occurs 10; * 2013-06-18 aozima add restore MSP feature. 11; * 2013-07-09 aozima enhancement hard fault exception handler. 12; */ 13 14;/** 15; * @addtogroup cortex-m3 16; */ 17;/*@{*/ 18 19SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register 20NVIC_INT_CTRL EQU 0xE000ED04 ; interrupt control state register 21NVIC_SYSPRI2 EQU 0xE000ED20 ; system priority register (2) 22NVIC_PENDSV_PRI EQU 0x00FF0000 ; PendSV priority value (lowest) 23NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV exception 24 25 SECTION .text:CODE(2) 26 THUMB 27 REQUIRE8 28 PRESERVE8 29 30 IMPORT rt_thread_switch_interrupt_flag 31 IMPORT rt_interrupt_from_thread 32 IMPORT rt_interrupt_to_thread 33 34;/* 35; * rt_base_t rt_hw_interrupt_disable(); 36; */ 37 EXPORT rt_hw_interrupt_disable 38rt_hw_interrupt_disable: 39 MRS r0, PRIMASK 40 CPSID I 41 BX LR 42 43;/* 44; * void rt_hw_interrupt_enable(rt_base_t level); 45; */ 46 EXPORT rt_hw_interrupt_enable 47rt_hw_interrupt_enable: 48 MSR PRIMASK, r0 49 BX LR 50 51;/* 52; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 53; * r0 --> from 54; * r1 --> to 55; */ 56 EXPORT rt_hw_context_switch_interrupt 57 EXPORT rt_hw_context_switch 58rt_hw_context_switch_interrupt: 59rt_hw_context_switch: 60 ; set rt_thread_switch_interrupt_flag to 1 61 LDR r2, =rt_thread_switch_interrupt_flag 62 LDR r3, [r2] 63 CMP r3, #1 64 BEQ _reswitch 65 MOV r3, #1 66 STR r3, [r2] 67 68 LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread 69 STR r0, [r2] 70 71_reswitch 72 LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread 73 STR r1, [r2] 74 75 LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch) 76 LDR r1, =NVIC_PENDSVSET 77 STR r1, [r0] 78 BX LR 79 80; r0 --> switch from thread stack 81; r1 --> switch to thread stack 82; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack 83 EXPORT PendSV_Handler 84PendSV_Handler: 85 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 CBZ r1, pendsv_exit ; pendsv already handled 94 95 ; clear rt_thread_switch_interrupt_flag to 0 96 MOV r1, #0x00 97 STR r1, [r0] 98 99 LDR r0, =rt_interrupt_from_thread 100 LDR r1, [r0] 101 CBZ r1, switch_to_thread ; skip register save at the first time 102 103 MRS r1, psp ; get from thread stack pointer 104 STMFD r1!, {r4 - r11} ; push r4 - r11 register 105 LDR r0, [r0] 106 STR r1, [r0] ; update from thread stack pointer 107 108switch_to_thread 109 LDR r1, =rt_interrupt_to_thread 110 LDR r1, [r1] 111 LDR r1, [r1] ; load thread stack pointer 112 113 LDMFD r1!, {r4 - r11} ; pop r4 - r11 register 114 MSR psp, r1 ; update stack pointer 115 116pendsv_exit 117 ; restore interrupt 118 MSR PRIMASK, r2 119 120 ORR lr, lr, #0x04 121 BX lr 122 123;/* 124; * void rt_hw_context_switch_to(rt_uint32 to); 125; * r0 --> to 126; */ 127 EXPORT rt_hw_context_switch_to 128rt_hw_context_switch_to: 129 LDR r1, =rt_interrupt_to_thread 130 STR r0, [r1] 131 132 ; set from thread to 0 133 LDR r1, =rt_interrupt_from_thread 134 MOV r0, #0x0 135 STR r0, [r1] 136 137 ; set interrupt flag to 1 138 LDR r1, =rt_thread_switch_interrupt_flag 139 MOV r0, #1 140 STR r0, [r1] 141 142 ; set the PendSV exception priority 143 LDR r0, =NVIC_SYSPRI2 144 LDR r1, =NVIC_PENDSV_PRI 145 LDR.W r2, [r0,#0x00] ; read 146 ORR r1,r1,r2 ; modify 147 STR r1, [r0] ; write-back 148 149 LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch) 150 LDR r1, =NVIC_PENDSVSET 151 STR r1, [r0] 152 153 ; restore MSP 154 LDR r0, =SCB_VTOR 155 LDR r0, [r0] 156 LDR r0, [r0] 157 NOP 158 MSR msp, r0 159 160 ; enable interrupts at processor level 161 CPSIE F 162 CPSIE I 163 164 ; never reach here! 165 166; compatible with old version 167 EXPORT rt_hw_interrupt_thread_switch 168rt_hw_interrupt_thread_switch: 169 BX lr 170 171 IMPORT rt_hw_hard_fault_exception 172 EXPORT HardFault_Handler 173HardFault_Handler: 174 175 ; get current context 176 MRS r0, msp ; get fault context from handler. 177 TST lr, #0x04 ; if(!EXC_RETURN[2]) 178 BEQ _get_sp_done 179 MRS r0, psp ; get fault context from thread. 180_get_sp_done 181 182 STMFD r0!, {r4 - r11} ; push r4 - r11 register 183 ;STMFD r0!, {lr} ; push exec_return register 184 SUB r0, r0, #0x04 185 STR lr, [r0] 186 187 TST lr, #0x04 ; if(!EXC_RETURN[2]) 188 BEQ _update_msp 189 MSR psp, r0 ; update stack pointer to PSP. 190 B _update_done 191_update_msp 192 MSR msp, r0 ; update stack pointer to MSP. 193_update_done 194 195 PUSH {lr} 196 BL rt_hw_hard_fault_exception 197 POP {lr} 198 199 ORR lr, lr, #0x04 200 BX lr 201 202 END 203