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