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