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; * 2010-01-25 Bernard first version 9*10465441SEvalZero; * 2012-06-01 aozima set pendsv priority to 0xFF. 10*10465441SEvalZero; * 2012-08-17 aozima fixed bug: store r8 - r11. 11*10465441SEvalZero; * 2013-06-18 aozima add restore MSP feature. 12*10465441SEvalZero; */ 13*10465441SEvalZero 14*10465441SEvalZero;/** 15*10465441SEvalZero; * @addtogroup CORTEX-M0 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_SHPR3 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 MOVS r3, #0x1 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 CMP r1, #0x00 94*10465441SEvalZero BEQ pendsv_exit ; pendsv already handled 95*10465441SEvalZero 96*10465441SEvalZero ; clear rt_thread_switch_interrupt_flag to 0 97*10465441SEvalZero MOVS r1, #0x00 98*10465441SEvalZero STR r1, [r0] 99*10465441SEvalZero 100*10465441SEvalZero LDR r0, =rt_interrupt_from_thread 101*10465441SEvalZero LDR r1, [r0] 102*10465441SEvalZero CMP r1, #0x00 103*10465441SEvalZero BEQ switch_to_thread ; skip register save at the first time 104*10465441SEvalZero 105*10465441SEvalZero MRS r1, psp ; get from thread stack pointer 106*10465441SEvalZero 107*10465441SEvalZero SUBS r1, r1, #0x20 ; space for {r4 - r7} and {r8 - r11} 108*10465441SEvalZero LDR r0, [r0] 109*10465441SEvalZero STR r1, [r0] ; update from thread stack pointer 110*10465441SEvalZero 111*10465441SEvalZero STMIA r1!, {r4 - r7} ; push thread {r4 - r7} register to thread stack 112*10465441SEvalZero 113*10465441SEvalZero MOV r4, r8 ; mov thread {r8 - r11} to {r4 - r7} 114*10465441SEvalZero MOV r5, r9 115*10465441SEvalZero MOV r6, r10 116*10465441SEvalZero MOV r7, r11 117*10465441SEvalZero STMIA r1!, {r4 - r7} ; push thread {r8 - r11} high register to thread stack 118*10465441SEvalZero 119*10465441SEvalZeroswitch_to_thread 120*10465441SEvalZero LDR r1, =rt_interrupt_to_thread 121*10465441SEvalZero LDR r1, [r1] 122*10465441SEvalZero LDR r1, [r1] ; load thread stack pointer 123*10465441SEvalZero 124*10465441SEvalZero LDMIA r1!, {r4 - r7} ; pop thread {r4 - r7} register from thread stack 125*10465441SEvalZero PUSH {r4 - r7} ; push {r4 - r7} to MSP for copy {r8 - r11} 126*10465441SEvalZero 127*10465441SEvalZero LDMIA r1!, {r4 - r7} ; pop thread {r8 - r11} high register from thread stack to {r4 - r7} 128*10465441SEvalZero MOV r8, r4 ; mov {r4 - r7} to {r8 - r11} 129*10465441SEvalZero MOV r9, r5 130*10465441SEvalZero MOV r10, r6 131*10465441SEvalZero MOV r11, r7 132*10465441SEvalZero 133*10465441SEvalZero POP {r4 - r7} ; pop {r4 - r7} from MSP 134*10465441SEvalZero 135*10465441SEvalZero MSR psp, r1 ; update stack pointer 136*10465441SEvalZero 137*10465441SEvalZeropendsv_exit 138*10465441SEvalZero ; restore interrupt 139*10465441SEvalZero MSR PRIMASK, r2 140*10465441SEvalZero 141*10465441SEvalZero MOVS r0, #0x04 142*10465441SEvalZero RSBS r0, r0, #0x00 143*10465441SEvalZero BX r0 144*10465441SEvalZero 145*10465441SEvalZero;/* 146*10465441SEvalZero; * void rt_hw_context_switch_to(rt_uint32 to); 147*10465441SEvalZero; * r0 --> to 148*10465441SEvalZero; * this fucntion is used to perform the first thread switch 149*10465441SEvalZero; */ 150*10465441SEvalZero EXPORT rt_hw_context_switch_to 151*10465441SEvalZerort_hw_context_switch_to: 152*10465441SEvalZero ; set to thread 153*10465441SEvalZero LDR r1, =rt_interrupt_to_thread 154*10465441SEvalZero STR r0, [r1] 155*10465441SEvalZero 156*10465441SEvalZero ; set from thread to 0 157*10465441SEvalZero LDR r1, =rt_interrupt_from_thread 158*10465441SEvalZero MOVS r0, #0x0 159*10465441SEvalZero STR r0, [r1] 160*10465441SEvalZero 161*10465441SEvalZero ; set interrupt flag to 1 162*10465441SEvalZero LDR r1, =rt_thread_switch_interrupt_flag 163*10465441SEvalZero MOVS r0, #1 164*10465441SEvalZero STR r0, [r1] 165*10465441SEvalZero 166*10465441SEvalZero ; set the PendSV exception priority 167*10465441SEvalZero LDR r0, =NVIC_SHPR3 168*10465441SEvalZero LDR r1, =NVIC_PENDSV_PRI 169*10465441SEvalZero LDR r2, [r0,#0x00] ; read 170*10465441SEvalZero ORRS r1,r1,r2 ; modify 171*10465441SEvalZero STR r1, [r0] ; write-back 172*10465441SEvalZero 173*10465441SEvalZero ; trigger the PendSV exception (causes context switch) 174*10465441SEvalZero LDR r0, =NVIC_INT_CTRL 175*10465441SEvalZero LDR r1, =NVIC_PENDSVSET 176*10465441SEvalZero STR r1, [r0] 177*10465441SEvalZero NOP 178*10465441SEvalZero 179*10465441SEvalZero ; restore MSP 180*10465441SEvalZero LDR r0, =SCB_VTOR 181*10465441SEvalZero LDR r0, [r0] 182*10465441SEvalZero LDR r0, [r0] 183*10465441SEvalZero NOP 184*10465441SEvalZero MSR msp, r0 185*10465441SEvalZero 186*10465441SEvalZero ; enable interrupts at processor level 187*10465441SEvalZero CPSIE I 188*10465441SEvalZero 189*10465441SEvalZero ; never reach here! 190*10465441SEvalZero 191*10465441SEvalZero; compatible with old version 192*10465441SEvalZero EXPORT rt_hw_interrupt_thread_switch 193*10465441SEvalZerort_hw_interrupt_thread_switch: 194*10465441SEvalZero BX lr 195*10465441SEvalZero 196*10465441SEvalZero IMPORT rt_hw_hard_fault_exception 197*10465441SEvalZero EXPORT HardFault_Handler 198*10465441SEvalZeroHardFault_Handler: 199*10465441SEvalZero 200*10465441SEvalZero ; get current context 201*10465441SEvalZero MRS r0, psp ; get fault thread stack pointer 202*10465441SEvalZero PUSH {lr} 203*10465441SEvalZero BL rt_hw_hard_fault_exception 204*10465441SEvalZero POP {pc} 205*10465441SEvalZero 206*10465441SEvalZero END 207