summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/ti-dsp/c28x/context.s338
-rw-r--r--libcpu/ti-dsp/c28x/cpuport.c69
2 files changed, 263 insertions, 144 deletions
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
+; 2022-10-15 guyunjie add zero-latency interrupt
- .ref _rt_interrupt_to_thread
- .ref _rt_interrupt_from_thread
- .ref _rt_thread_switch_interrupt_flag
+ .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
+ .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
+ ;importing settings from compiler and config
.cdecls C,NOLIST
%{
+ #include <rtconfig.h>
+
#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 <rtthread.h>
+#include <rthw.h>
+
+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 */
+}