123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- ;
- ; 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
- ; 2022-10-15 guyunjie add zero-latency interrupt
- .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
- ;importing settings from compiler and config
- .cdecls C,NOLIST
- %{
- #include <rtconfig.h>
- #ifdef __TMS320C28XX_FPU32__
- #define __FPU32__ 1
- #else
- #define __FPU32__ 0
- #endif
- #ifdef __TMS320C28XX_FPU64__
- #define __FPU64__ 1
- #else
- #define __FPU64__ 0
- #endif
- #ifdef __TMS320C28XX_VCRC__
- #define __VCRC__ 1
- #else
- #define __VCRC__ 0
- #endif
- #ifdef RT_USING_ZERO_LATENCY
- #define ZERO_LATENCY 1
- #ifndef ZERO_LATENCY_INT_MASK
- #error ZERO_LATENCY_INT_MASK must be defined for zero latency interrupt
- #elif ZERO_LATENCY_INT_MASK & 0x8000
- #error RTOS bit (0x8000) must not be set in ZERO_LATENCY_INT_MASK
- #endif
- #else
- #define ZERO_LATENCY 0
- #endif
- %}
- .text
- .newblock
- ;
- ; rt_base_t rt_hw_interrupt_disable();
- ;
- .asmfunc
- rt_hw_interrupt_disable:
- .if ZERO_LATENCY
- MOV AL, IER
- AND IER, #ZERO_LATENCY_INT_MASK
- .else
- PUSH ST1
- SETC INTM
- POP AL
- .endif
- MOV AH, #0
- LRETR
- .endasmfunc
- ;
- ; void rt_hw_interrupt_enable(rt_base_t level);
- ;
- .asmfunc
- rt_hw_interrupt_enable:
- .if ZERO_LATENCY
- MOV IER, AL
- .else
- PUSH AL
- POP ST1
- .endif
- LRETR
- .endasmfunc
- ;
- ; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
- ; ACC --> from
- ; SP[4] --> to
- ;
- .asmfunc
- rt_hw_context_switch_interrupt:
- ; ACC, XAR4-7 are "save on call" following TI C28x C/C++ compiler convention
- ; and therefore can be used in a function without being saved on stack first
- ; (the compiler has already saved it before the call).
- ; Reference: TMS320C28x Optimizing CC++ Compiler
- ; note this convention is only applicable to normal functions not to isrs
- MOVL XAR6, 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, XAR6
- reswitch2:
- 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 XAR6, ACC
- MOVL XAR4, *-SP[4]
- ; set rt_thread_switch_interrupt_flag to 1
- MOVL XAR5, #rt_thread_switch_interrupt_flag
- MOVL ACC, *XAR5
- BF reswitch1, NEQ ; ACC!=0
- MOVB ACC, #1
- MOVL *XAR5, ACC
- MOVL XAR5, #rt_interrupt_from_thread ; set rt_interrupt_from_thread
- MOVL *XAR5, XAR6
- reswitch1:
- MOVL XAR5, #rt_interrupt_to_thread ; set rt_interrupt_to_thread
- MOVL *XAR5, XAR4
- OR IFR, #0x8000
- LRETR
- .endasmfunc
- ;
- ; * void rt_hw_context_switch_to(rt_uint32 to);
- ; * ACC --> to
- ;
- .asmfunc
- rt_hw_context_switch_to:
- ; get to thread
- MOVL XAR5, #rt_interrupt_to_thread
- MOVL *XAR5, ACC
- ; set from thread to 0
- MOVL XAR5, #rt_interrupt_from_thread
- MOVL XAR4, #0
- MOVL *XAR5, XAR4
- ; set interrupt flag to 1
- MOVL XAR5, #rt_thread_switch_interrupt_flag
- MOVL XAR4, #1
- MOVL *XAR5, XAR4
- ; trigger rtos interrupt
- OR IFR, #0x8000
- OR IER, #0x8000
- CLRC INTM
- ; never reach here!
- .endasmfunc
- .asmfunc
- rtosint_handler:
- .if ZERO_LATENCY
- ; mask out non-critical interrupts and enable global interrupt
- ; so rtosint_handler won't block critical interrupts
- AND IER, #ZERO_LATENCY_INT_MASK
- CLRC INTM
- .endif
- MOVL ACC, *-SP[4]
- MOV AR0, AL ; save original IER
- PUSH AR1H:AR0H
- PUSH XAR2
- ; get rt_thread_switch_interrupt_flag
- MOVL XAR1, #rt_thread_switch_interrupt_flag
- MOVL ACC, *XAR1
- BF rtosint_exit, EQ ; rtos_int already handled
- ; clear rt_thread_switch_interrupt_flag to 0
- MOVL XAR2, #0
- MOVL *XAR1, XAR2
- MOVL XAR1, #rt_interrupt_from_thread
- MOVL ACC, *XAR1
- BF switch_to_thread, EQ ; skip register save at the first time
- 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
- .if __FPU64__
- MOV32 *SP++, R0L
- MOV32 *SP++, R1L
- MOV32 *SP++, R2L
- MOV32 *SP++, R3L
- MOV32 *SP++, R4L
- MOV32 *SP++, R5L
- MOV32 *SP++, R6L
- MOV32 *SP++, R7L
- .endif
- .if __VCRC__
- VMOV32 *SP++, VCRC
- VMOV32 *SP++, VSTATUS
- VMOV32 *SP++, VCRCPOLY
- VMOV32 *SP++, VCRCSIZE
- .endif
- MOVL ACC, *XAR1
- MOVL XAR1, ACC
- MOVZ AR2, @SP ; get from thread stack pointer
- MOVL *XAR1, XAR2 ; 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
- .if __VCRC__
- VMOV32 VCRCSIZE, *--SP
- VMOV32 VCRCPOLY, *--SP
- VMOV32 VSTATUS, *--SP
- VMOV32 VCRC, *--SP
- .endif
- .if __FPU64__
- MOV32 R7L, *--SP
- MOV32 R6L, *--SP
- MOV32 R5L, *--SP
- MOV32 R4L, *--SP
- MOV32 R3L, *--SP
- MOV32 R2L, *--SP
- MOV32 R1L, *--SP
- MOV32 R0L, *--SP
- .endif
- .if __FPU32__
- MOV32 R7H, *--SP
- MOV32 R6H, *--SP
- MOV32 R5H, *--SP
- MOV32 R4H, *--SP
- MOV32 R3H, *--SP
- MOV32 R2H, *--SP
- MOV32 R1H, *--SP
- MOV32 R0H, *--SP
- MOV32 STF, *--SP
- POP RB
- .endif
- POP RPC
- POP XT
- POP XAR7
- POP XAR6
- POP XAR5
- POP XAR4
- POP XAR3
- rtosint_exit:
- ; do not restore interrupt here: to be restored according to the
- ; switched-to context during IRET (automaticlly by hardware)
- POP XAR2
- POP AR1H:AR0H
- MOVL ACC , *-SP[4]
- MOV AL, AR0
- MOVL *-SP[4], ACC
- 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
|