rt-thread/libcpu/ti-dsp/c28x/context.s

289 lines
6.5 KiB
ArmAsm

;
; Copyright (c) 2006-2022, RT-Thread Development Team
;
; SPDX-License-Identifier: Apache-2.0
;
; Change Logs:
; Date Author Notes
; 2018-09-01 xuzhuoyi the first version.
; 2019-06-17 zhaoxiaowei fix bugs of old c28x interrupt api.
; 2019-07-03 zhaoxiaowei add _rt_hw_calc_csb function to support __rt_ffs.
; 2019-12-05 xiaolifan add support for hardware fpu32
; 2022-06-21 guyunjie trim pendsv (RTOSINT_Handler)
; 2022-08-24 guyunjie fix bugs in context switching
.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_calc_csb
.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
;workaround for importing fpu settings from the compiler
.cdecls C,NOLIST
%{
#ifdef __TMS320C28XX_FPU32__
#define __FPU32__ 1
#else
#define __FPU32__ 0
#endif
%}
RT_CTX_SAVE .macro
PUSH AR1H:AR0H
PUSH XAR2
PUSH XAR3
PUSH XAR4
PUSH XAR5
PUSH XAR6
PUSH XAR7
PUSH XT
PUSH RPC
.if __FPU32__
PUSH RB
MOV32 *SP++, STF
MOV32 *SP++, R0H
MOV32 *SP++, R1H
MOV32 *SP++, R2H
MOV32 *SP++, R3H
MOV32 *SP++, R4H
MOV32 *SP++, R5H
MOV32 *SP++, R6H
MOV32 *SP++, R7H
.endif
.endm
RT_CTX_RESTORE .macro
.if __FPU32__
MOV32 R7H, *--SP, UNCF
MOV32 R6H, *--SP, UNCF
MOV32 R5H, *--SP, UNCF
MOV32 R4H, *--SP, UNCF
MOV32 R3H, *--SP, UNCF
MOV32 R2H, *--SP, UNCF
MOV32 R1H, *--SP, UNCF
MOV32 R0H, *--SP, UNCF
MOV32 STF, *--SP
POP RB
.endif
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:
PUSH ST1
SETC INTM,DBGM
MOV AL, *--SP
LRETR
.endasmfunc
;
; void rt_hw_interrupt_enable(rt_base_t level);
;
.asmfunc
_rt_hw_interrupt_enable:
MOV *SP++, AL
POP ST1
LRETR
.endasmfunc
;
; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; ACC --> from
; SP[4] --> to
;
.asmfunc
_rt_hw_context_switch_interrupt:
MOVL XAR0, ACC
MOVL XAR4, *-SP[4]
; set rt_thread_switch_interrupt_flag to 1
MOVL XAR5, #_rt_thread_switch_interrupt_flag
MOVL ACC, *XAR5
BF _reswitch, NEQ ; ACC!=0
MOVB ACC, #1
MOVL *XAR5, ACC
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
LRETR
.endasmfunc
;
; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; ACC --> from
; SP[4] --> to
;
.asmfunc
_rt_hw_context_switch:
MOVL XAR0, ACC
MOVL XAR4, *-SP[4]
; set rt_thread_switch_interrupt_flag to 1
MOVL XAR5, #_rt_thread_switch_interrupt_flag
MOVL ACC, *XAR5
BF _reswitch2, NEQ ; ACC!=0
MOVB ACC, #1
MOVL *XAR5, ACC
MOVL XAR5, #_rt_interrupt_from_thread ; set rt_interrupt_from_thread
MOVL *XAR5, XAR0
_reswitch2:
MOVL XAR5, #_rt_interrupt_to_thread ; set rt_interrupt_to_thread
MOVL *XAR5, XAR4
TRAP #16
LRETR
.endasmfunc
;
; * void rt_hw_context_switch_to(rt_uint32 to);
; * ACC --> to
;
.asmfunc
_rt_hw_context_switch_to:
; get to thread
MOVL XAR1, #_rt_interrupt_to_thread
MOVL *XAR1, ACC
; set from thread to 0
MOVL XAR1, #_rt_interrupt_from_thread
MOVL XAR0, #0
MOVL *XAR1, XAR0
; set interrupt flag to 1
MOVL XAR1, #_rt_thread_switch_interrupt_flag
MOVL XAR0, #1
MOVL *XAR1, XAR0
TRAP #16
; never reach here!
.endasmfunc
.asmfunc
_RTOSINT_Handler:
; disable interrupt to protect context switch
; DINT ;this is done by hardware so not needed
; get rt_thread_switch_interrupt_flag
MOVL XAR0, #_rt_thread_switch_interrupt_flag
MOVL ACC, *XAR0
BF rtosint_exit, EQ ; pendsv already handled
; clear rt_thread_switch_interrupt_flag to 0
MOVL XAR1, #0
MOVL *XAR0, XAR1
MOVL XAR0, #_rt_interrupt_from_thread
MOVL ACC, *XAR0
BF switch_to_thread, EQ ; skip register save at the first time
RT_CTX_SAVE ; push cpu registers
MOVL ACC, *XAR0
MOVL XAR0, ACC
MOVZ AR1, @SP ; get from thread stack pointer
MOVL *XAR0, XAR1 ; update from thread stack pointer
switch_to_thread:
MOVL XAR1, #_rt_interrupt_to_thread
MOVL ACC, *XAR1
MOVL XAR1, ACC
MOVL ACC, *XAR1
MOV @SP, AL ; load thread stack pointer
RT_CTX_RESTORE ; pop cpu registers
rtosint_exit:
; do not restore interrupt here: to be restored according to the
; switched-to context during IRET (automaticlly by hardware)
IRET
.endasmfunc
.asmfunc
_rt_hw_get_st0:
PUSH ST0
POP AL
LRETR
.endasmfunc
.asmfunc
_rt_hw_get_st1:
PUSH ST1
POP AL
LRETR
.endasmfunc
; C28x do not have a build-in "__ffs" func in its C compiler.
; We can use the "Count Sign Bits" (CSB) instruction to make one.
; CSB will return the number of 0's minus 1 above the highest set bit.
; The count is placed in T. For example:
; ACC T maxbit
; 0x00000001 30 0
; 0x00000010 26 4
; 0x000001FF 22 8
; 0x000001F0 22 8
.asmfunc
_rt_hw_calc_csb:
MOV AH, #0
CSB ACC ; T = no. of sign bits - 1
MOVU ACC, T ; ACC = no. of sign bits - 1
SUBB ACC, #30 ; ACC = ACC - 30
ABS ACC ; ACC = |ACC|
lretr
.endasmfunc
; compatible with old version
.asmfunc
_rt_hw_interrupt_thread_switch:
LRETR
NOP
.endasmfunc
.end