; ; Copyright (c) 2006-2018, RT-Thread Development Team ; ; SPDX-License-Identifier: Apache-2.0 ; ; Change Logs: ; Date Author Notes ; 2018-09-01 xuzhuoyi the first version. ; .ref _rt_interrupt_to_thread .ref _rt_interrupt_from_thread .ref _rt_thread_switch_interrupt_flag .def _RTOSINT_Handler .def _rt_hw_get_st0 .def _rt_hw_get_st1 .def _rt_hw_context_switch_interrupt .def _rt_hw_context_switch .def _rt_hw_context_switch_to .def _rt_hw_interrupt_thread_switch .def _rt_hw_interrupt_disable .def _rt_hw_interrupt_enable RT_CTX_SAVE .macro PUSH AR1H:AR0H PUSH XAR2 PUSH XAR3 PUSH XAR4 PUSH XAR5 PUSH XAR6 PUSH XAR7 PUSH XT PUSH RPC .endm RT_CTX_RESTORE .macro POP RPC POP XT POP XAR7 POP XAR6 POP XAR5 POP XAR4 POP XAR3 POP XAR2 MOVZ AR0 , @SP SUBB XAR0, #6 MOVL ACC , *XAR0 AND ACC, #0xFFFF << 16 MOV AL, IER MOVL *XAR0, ACC POP AR1H:AR0H .endm .text .newblock ; ; rt_base_t rt_hw_interrupt_disable(); ; .asmfunc _rt_hw_interrupt_disable: DINT LRETR .endasmfunc ; ; void rt_hw_interrupt_enable(rt_base_t level); ; .asmfunc _rt_hw_interrupt_enable: EINT LRETR .endasmfunc ; ; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; r0 --> from ; r4 --> to .asmfunc _rt_hw_context_switch_interrupt: _rt_hw_context_switch: MOVL XAR0, #0 MOV AR0, AL MOVL XAR4, *-SP[4] ; set rt_thread_switch_interrupt_flag to 1 MOVL XAR5, #_rt_thread_switch_interrupt_flag MOVL XAR6, *XAR5 MOVL ACC, XAR6 CMPB AL, #1 B _reswitch, EQ MOVL XAR6, #1 MOVL *XAR5, XAR6 MOVL XAR5, #_rt_interrupt_from_thread ; set rt_interrupt_from_thread MOVL *XAR5, XAR0 _reswitch: MOVL XAR5, #_rt_interrupt_to_thread ; set rt_interrupt_to_thread MOVL *XAR5, XAR4 TRAP #16 LRETR .endasmfunc .asmfunc _RTOSINT_Handler: ; disable interrupt to protect context switch DINT ; get rt_thread_switch_interrupt_flag MOV AR0, #_rt_thread_switch_interrupt_flag MOV AL, *AR0 MOV AR1, AL CMP AR1, #0 B rtosint_exit, EQ ; pendsv already handled ; clear rt_thread_switch_interrupt_flag to 0 MOV AR1, #0x00 MOV *AR0, AR1 MOV AR0, #_rt_interrupt_from_thread MOV AL, *AR0 MOV AR1, AL CMP AR1, #0 B switch_to_thread, EQ ; skip register save at the first time ;MOVZ AR1, @SP ; get from thread stack pointer ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) ; TST lr, #0x10 ; if(!EXC_RETURN[4]) ; VSTMDBEQ r1!, {d8 - d15} ; push FPU register s16~s31 ;#endif RT_CTX_SAVE ; push r4 - r11 register ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) ; MOV r4, #0x00 ; flag = 0 ; TST lr, #0x10 ; if(!EXC_RETURN[4]) ; MOVEQ r4, #0x01 ; flag = 1 ; STMFD r1!, {r4} ; push flag ;#endif MOV AL, *AR0 MOV AR1, AL MOVZ AR1, @SP ; get from thread stack pointer MOV *AR0, AR1 ; update from thread stack pointer switch_to_thread: MOV AR1, #_rt_interrupt_to_thread MOV AL, *AR1 MOV AR1, AL MOV AL, *AR1 MOV AR1, AL ; load thread stack pointer ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) ; LDMFD r1!, {r3} ; pop flag ;#endif MOV @SP, AR1 INC SP RT_CTX_RESTORE ; pop r4 - r11 register rtosint_exit: ; restore interrupt EINT IRET .endasmfunc .asmfunc _rt_hw_get_st0: PUSH ST0 POP AL LRETR .endasmfunc .asmfunc _rt_hw_get_st1: PUSH ST1 POP AL LRETR .endasmfunc ; ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to .asmfunc _rt_hw_context_switch_to: MOV AR1, #_rt_interrupt_to_thread MOV *AR1, AL ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) ; CLEAR CONTROL.FPCA ; MRS r2, CONTROL ; read ; BIC r2, #0x04 ; modify ; MSR CONTROL, r2 ; write-back ;#endif ; set from thread to 0 MOV AR1, #_rt_interrupt_from_thread MOV AR0, #0x0 MOV *AR1, AR0 ; set interrupt flag to 1 MOV AR1, #_rt_thread_switch_interrupt_flag MOV AR0, #1 MOV *AR1, AR0 TRAP #16 ; never reach here! .endasmfunc ; compatible with old version .asmfunc _rt_hw_interrupt_thread_switch: LRETR NOP .endasmfunc .end