From 8fa9fde43a2e9cb978b52c0eb536fe2bafcc6e73 Mon Sep 17 00:00:00 2001 From: Yunjie Gu Date: Thu, 20 Oct 2022 04:41:13 +0100 Subject: [bsp][c28x] add support to not disable global interrupt in context-switch to enable zero-latency isr for critical interrupts. --- libcpu/ti-dsp/c28x/context.s | 344 ++++++++++++++++++++++++++----------------- libcpu/ti-dsp/c28x/cpuport.c | 69 +++++++-- 2 files changed, 266 insertions(+), 147 deletions(-) (limited to 'libcpu') diff --git a/libcpu/ti-dsp/c28x/context.s b/libcpu/ti-dsp/c28x/context.s index 297b3b2119..82207bce1b 100644 --- a/libcpu/ti-dsp/c28x/context.s +++ b/libcpu/ti-dsp/c28x/context.s @@ -11,95 +11,57 @@ ; 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 +; 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 + #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 + #ifdef __TMS320C28XX_FPU64__ + #define __FPU64__ 1 + #else + #define __FPU64__ 0 + #endif - POP AR1H:AR0H + #ifdef __TMS320C28XX_VCRC__ + #define __VCRC__ 1 + #else + #define __VCRC__ 0 + #endif - .endm + #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 @@ -109,10 +71,16 @@ RT_CTX_RESTORE .macro ; rt_base_t rt_hw_interrupt_disable(); ; .asmfunc -_rt_hw_interrupt_disable: +rt_hw_interrupt_disable: + .if ZERO_LATENCY + MOV AL, IER + AND IER, #ZERO_LATENCY_INT_MASK + .else PUSH ST1 - SETC INTM,DBGM - MOV AL, *--SP + SETC INTM + POP AL + .endif + MOV AH, #0 LRETR .endasmfunc @@ -120,9 +88,13 @@ _rt_hw_interrupt_disable: ; void rt_hw_interrupt_enable(rt_base_t level); ; .asmfunc -_rt_hw_interrupt_enable: - MOV *SP++, AL +rt_hw_interrupt_enable: + .if ZERO_LATENCY + MOV IER, AL + .else + PUSH AL POP ST1 + .endif LRETR .endasmfunc @@ -132,23 +104,29 @@ _rt_hw_interrupt_enable: ; SP[4] --> to ; .asmfunc -_rt_hw_context_switch_interrupt: - MOVL XAR0, ACC +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 XAR5, #rt_thread_switch_interrupt_flag MOVL ACC, *XAR5 - BF _reswitch, NEQ ; ACC!=0 + 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 + MOVL XAR5, #rt_interrupt_from_thread ; set rt_interrupt_from_thread + MOVL *XAR5, XAR6 -_reswitch: - MOVL XAR5, #_rt_interrupt_to_thread ; set rt_interrupt_to_thread +reswitch2: + MOVL XAR5, #rt_interrupt_to_thread ; set rt_interrupt_to_thread MOVL *XAR5, XAR4 - LRETR .endasmfunc @@ -158,102 +136,196 @@ _reswitch: ; SP[4] --> to ; .asmfunc -_rt_hw_context_switch: - MOVL XAR0, ACC +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 XAR5, #rt_thread_switch_interrupt_flag MOVL ACC, *XAR5 - BF _reswitch2, NEQ ; ACC!=0 + BF reswitch1, NEQ ; ACC!=0 MOVB ACC, #1 MOVL *XAR5, ACC - MOVL XAR5, #_rt_interrupt_from_thread ; set rt_interrupt_from_thread - MOVL *XAR5, XAR0 + 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 +reswitch1: + MOVL XAR5, #rt_interrupt_to_thread ; set rt_interrupt_to_thread MOVL *XAR5, XAR4 - - TRAP #16 + OR IFR, #0x8000 LRETR .endasmfunc - ; ; * void rt_hw_context_switch_to(rt_uint32 to); ; * ACC --> to ; .asmfunc -_rt_hw_context_switch_to: +rt_hw_context_switch_to: ; get to thread - MOVL XAR1, #_rt_interrupt_to_thread - MOVL *XAR1, ACC + MOVL XAR5, #rt_interrupt_to_thread + MOVL *XAR5, ACC ; set from thread to 0 - MOVL XAR1, #_rt_interrupt_from_thread - MOVL XAR0, #0 - MOVL *XAR1, XAR0 + MOVL XAR5, #rt_interrupt_from_thread + MOVL XAR4, #0 + MOVL *XAR5, XAR4 ; set interrupt flag to 1 - MOVL XAR1, #_rt_thread_switch_interrupt_flag - MOVL XAR0, #1 - MOVL *XAR1, XAR0 + MOVL XAR5, #rt_thread_switch_interrupt_flag + MOVL XAR4, #1 + MOVL *XAR5, XAR4 - TRAP #16 + ; trigger rtos interrupt + OR IFR, #0x8000 + OR IER, #0x8000 + CLRC INTM ; never reach here! .endasmfunc .asmfunc -_RTOSINT_Handler: - ; disable interrupt to protect context switch - ; DINT ;this is done by hardware so not needed +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 XAR0, #_rt_thread_switch_interrupt_flag - MOVL ACC, *XAR0 - BF rtosint_exit, EQ ; pendsv already handled + 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 XAR1, #0 - MOVL *XAR0, XAR1 + MOVL XAR2, #0 + MOVL *XAR1, XAR2 - MOVL XAR0, #_rt_interrupt_from_thread - MOVL ACC, *XAR0 + MOVL XAR1, #rt_interrupt_from_thread + MOVL ACC, *XAR1 BF switch_to_thread, EQ ; skip register save at the first time - RT_CTX_SAVE ; push cpu registers + PUSH XAR3 + PUSH XAR4 + PUSH XAR5 + PUSH XAR6 + PUSH XAR7 + PUSH XT + PUSH RPC - MOVL ACC, *XAR0 - MOVL XAR0, ACC - MOVZ AR1, @SP ; get from thread stack pointer - MOVL *XAR0, XAR1 ; update from thread stack pointer + .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 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 + .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: +rt_hw_get_st0: PUSH ST0 POP AL LRETR .endasmfunc .asmfunc -_rt_hw_get_st1: +rt_hw_get_st1: PUSH ST1 POP AL LRETR @@ -269,18 +341,18 @@ _rt_hw_get_st1: ; 0x000001FF 22 8 ; 0x000001F0 22 8 .asmfunc -_rt_hw_calc_csb: +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 + LRETR .endasmfunc ; compatible with old version .asmfunc -_rt_hw_interrupt_thread_switch: +rt_hw_interrupt_thread_switch: LRETR NOP .endasmfunc diff --git a/libcpu/ti-dsp/c28x/cpuport.c b/libcpu/ti-dsp/c28x/cpuport.c index 9ffd96d4f7..e5ffbd3cc3 100644 --- a/libcpu/ti-dsp/c28x/cpuport.c +++ b/libcpu/ti-dsp/c28x/cpuport.c @@ -8,9 +8,12 @@ * 2018-09-01 xuzhuoyi the first version. * 2019-07-03 zhaoxiaowei add support for __rt_ffs. * 2019-12-05 xiaolifan add support for hardware fpu32 + * 2022-10-17 guyunjie add support for hardware fpu64 and vcrc */ -#include +#include + +extern volatile rt_uint8_t rt_interrupt_nest; /* exception and interrupt handler table */ rt_uint32_t rt_interrupt_from_thread; @@ -64,6 +67,24 @@ struct stack_frame rt_uint32_t r7h; #endif +#ifdef __TMS320C28XX_FPU64__ + rt_uint32_t r0l; + rt_uint32_t r1l; + rt_uint32_t r2l; + rt_uint32_t r3l; + rt_uint32_t r4l; + rt_uint32_t r5l; + rt_uint32_t r6l; + rt_uint32_t r7l; +#endif + +#ifdef __TMS320C28XX_VCRC__ + rt_uint32_t vcrc; + rt_uint32_t vstatus; + rt_uint32_t vcrcpoly; + rt_uint32_t vcrcsize; +#endif + }; rt_uint8_t *rt_hw_stack_init(void *tentry, @@ -81,20 +102,17 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, stack_frame = (struct stack_frame *)stk; - /* init all register */ + /* zero all registers */ for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++) { - ((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef; + ((rt_uint32_t *)stack_frame)[i] = 0; } - stack_frame->exception_stack_frame.t_st0 = 0x11110000 | rt_hw_get_st0(); - stack_frame->exception_stack_frame.acc = 0x33332222; - stack_frame->exception_stack_frame.ar1_ar0 = 0x00001111 & (unsigned long)parameter; /* ar0 : argument */ - stack_frame->exception_stack_frame.p = 0x55554444; /* p */ - stack_frame->exception_stack_frame.dp_st1 = (0x00000000) | rt_hw_get_st1() & 0xFFFFFFFE; /* dp_st1 */ - stack_frame->exception_stack_frame.dbgstat_ier = 0; /* dbgstat_ier */ - stack_frame->exception_stack_frame.return_address = (unsigned long)tentry; /* return_address */ - stack_frame->rpc = (unsigned long)texit; + /* configure special registers*/ + stack_frame->exception_stack_frame.dp_st1 = 0x00000A08; + stack_frame->xar4 = (rt_uint32_t)parameter; + stack_frame->exception_stack_frame.return_address = (rt_uint32_t)tentry; + stack_frame->rpc = (rt_uint32_t)texit; #ifdef __TMS320C28XX_FPU32__ stack_frame->stf = 0x00000200; @@ -145,3 +163,32 @@ RT_WEAK void rt_hw_cpu_shutdown(void) RT_ASSERT(0); } + +void rt_interrupt_enter(void) +{ + rt_base_t level; + + __asm(" EINT"); + level = rt_hw_interrupt_disable(); + rt_interrupt_nest ++; + RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,()); + rt_hw_interrupt_enable(level); + + RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq has come..., irq current nest:%d\n", + (rt_int32_t)rt_interrupt_nest)); +} + +void rt_interrupt_leave(void) +{ + RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq is going to leave, irq current nest:%d\n", + (rt_int32_t)rt_interrupt_nest)); + + rt_hw_interrupt_disable(); + RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,()); + rt_interrupt_nest --; + if(rt_thread_switch_interrupt_flag && !rt_interrupt_nest) + { + __asm(" OR IFR, #0x8000"); /* trigger rtos int */ + } + /* rt_hw_interrupt_enable auto done by hardware on IRET */ +} -- cgit v1.3.1