From 3639963a9783dc3f06804bd7dff9283010edb372 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Tue, 16 Nov 2021 18:32:11 +0800 Subject: 添加TMS320C6678处理器,keystone架构底层代码 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/ti-dsp/c6x/SConscript | 14 ++ libcpu/ti-dsp/c6x/c66xx.h | 106 ++++++++++++ libcpu/ti-dsp/c6x/context.asm | 312 +++++++++++++++++++++++++++++++++++ libcpu/ti-dsp/c6x/cpuport.c | 225 +++++++++++++++++++++++++ libcpu/ti-dsp/c6x/inct.asm | 374 ++++++++++++++++++++++++++++++++++++++++++ libcpu/ti-dsp/c6x/interrupt.c | 90 ++++++++++ libcpu/ti-dsp/c6x/interrupt.h | 24 +++ libcpu/ti-dsp/c6x/stack.asm | 103 ++++++++++++ libcpu/ti-dsp/c6x/trap.c | 352 +++++++++++++++++++++++++++++++++++++++ libcpu/ti-dsp/c6x/trap.h | 76 +++++++++ libcpu/ti-dsp/c6x/vector.asm | 95 +++++++++++ 11 files changed, 1771 insertions(+) create mode 100644 libcpu/ti-dsp/c6x/SConscript create mode 100644 libcpu/ti-dsp/c6x/c66xx.h create mode 100644 libcpu/ti-dsp/c6x/context.asm create mode 100644 libcpu/ti-dsp/c6x/cpuport.c create mode 100644 libcpu/ti-dsp/c6x/inct.asm create mode 100644 libcpu/ti-dsp/c6x/interrupt.c create mode 100644 libcpu/ti-dsp/c6x/interrupt.h create mode 100644 libcpu/ti-dsp/c6x/stack.asm create mode 100644 libcpu/ti-dsp/c6x/trap.c create mode 100644 libcpu/ti-dsp/c6x/trap.h create mode 100644 libcpu/ti-dsp/c6x/vector.asm (limited to 'libcpu') diff --git a/libcpu/ti-dsp/c6x/SConscript b/libcpu/ti-dsp/c6x/SConscript new file mode 100644 index 0000000000..0fe94fd9a6 --- /dev/null +++ b/libcpu/ti-dsp/c6x/SConscript @@ -0,0 +1,14 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*.asm') +CPPPATH = [cwd] +ASFLAGS = '' + +group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS) + +Return('group') diff --git a/libcpu/ti-dsp/c6x/c66xx.h b/libcpu/ti-dsp/c6x/c66xx.h new file mode 100644 index 0000000000..9f3a20399f --- /dev/null +++ b/libcpu/ti-dsp/c6x/c66xx.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#ifndef __C66XX_H__ +#define __C66XX_H__ + +#include + +#ifdef _BIG_ENDIAN +#define REG_PAIR(odd, even) unsigned long odd; unsigned long even +#else +#define REG_PAIR(odd, even) unsigned long even; unsigned long odd +#endif + +/* + * this struct defines the way the registers are stored on the + * stack during a system call. fields defined with REG_PAIR + * are saved and restored using double-word memory operations + * which means the word ordering of the pair depends on endianess. + */ + +struct rt_hw_register +{ + REG_PAIR(b17, b16); + REG_PAIR(b19, b18); + REG_PAIR(b21, b20); + REG_PAIR(b23, b22); + REG_PAIR(b25, b24); + REG_PAIR(b27, b26); + REG_PAIR(b29, b28); + REG_PAIR(b31, b30); + + REG_PAIR(b1, b0); + REG_PAIR(b3, b2); + REG_PAIR(b5, b4); + REG_PAIR(b7, b6); + REG_PAIR(b9, b8); + REG_PAIR(b11, b10); + REG_PAIR(b13, b12); + + REG_PAIR(a17, a16); + REG_PAIR(a19, a18); + REG_PAIR(a21, a20); + REG_PAIR(a23, a22); + REG_PAIR(a25, a24); + REG_PAIR(a27, a26); + REG_PAIR(a29, a28); + REG_PAIR(a31, a30); + + REG_PAIR(a1, a0); + REG_PAIR(a3, a2); + REG_PAIR(a5, a4); + REG_PAIR(a7, a6); + REG_PAIR(a9, a8); + REG_PAIR(a11, a10); + REG_PAIR(a13, a12); + + REG_PAIR(a15, a14); + REG_PAIR(sp, dp); +}; + +struct rt_hw_exp_stack_register +{ + REG_PAIR(tsr, orig_a4); + REG_PAIR(rilc, ilc); + REG_PAIR(pc, csr); + struct rt_hw_register hw_register; +}; + +extern cregister volatile unsigned int IERR; /* Internal Exception Report Register */ +extern cregister volatile unsigned int ECR; /* Exception Clear Register */ +extern cregister volatile unsigned int EFR; /* Exception Flag Register */ +extern cregister volatile unsigned int TSR; /* Task State Register */ +extern cregister volatile unsigned int ITSR; /* Interrupt Task State Register */ +extern cregister volatile unsigned int NTSR; /* NMI/exception Task State Register */ +extern cregister volatile unsigned int TSCL; /* Time Stamp Counter Register - Low Half */ +extern cregister volatile unsigned int TSCH; /* Time Stamp Counter Register - High Half */ +extern cregister volatile unsigned int DNUM; /* Core number */ + +#define get_creg(reg) reg +#define set_creg(reg, v) reg = (v) +#define or_creg(reg, n) reg |= (n) +#define and_creg(reg, n) reg &= (n) + +#define __dint() asm(" DINT") +#define __rint() asm(" RINT") + +#define __system_call() asm(" SWE") +#define __enter_idle() asm(" IDLE") +#define __nop() asm(" NOP") +#define __mfence() asm(" MFENCE") + +#define __SYSREG(ADDR, TYPE) (*(volatile TYPE*)(ADDR)) +#define __SYSREGA(ADDR, TYPE) ((volatile TYPE*)(ADDR)) + +extern void rt_hw_enable_exception(void); + +#endif /* __C66XX_H__ */ + diff --git a/libcpu/ti-dsp/c6x/context.asm b/libcpu/ti-dsp/c6x/context.asm new file mode 100644 index 0000000000..07affb6a1a --- /dev/null +++ b/libcpu/ti-dsp/c6x/context.asm @@ -0,0 +1,312 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; context switch for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +DP .set B14 +SP .set B15 + +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; global variable +;----------------------------------------------------------- + .global rt_interrupt_from_thread + .global rt_interrupt_to_thread + .global rt_thread_switch_interrupt_flag + +; +;----------------------------------------------------------- +; + .sect ".text" +;----------------------------------------------------------- +; void rt_hw_enable_exception(void) +;----------------------------------------------------------- + .global rt_hw_enable_exception +rt_hw_enable_exception: + DINT + MVC .S2 TSR,B0 + MVC .S2 B3,NRP + MVK .L2 0xc,B1 + OR .D2 B0,B1,B0 + MVC .S2 B0,TSR ; Set GEE and XEN in TSR + B .S2 NRP + NOP 5 + +;----------------------------------------------------------- +; rt_base_t rt_hw_interrupt_enable(void) +;----------------------------------------------------------- + .global rt_hw_interrupt_disable +rt_hw_interrupt_disable: +;{ + MVC CSR,B4 + MV B4,A4 + AND 1,B4,B0 + [!B0] CLR B4,1,1,B4 + [B0] SET B4,1,1,B4 + CLR B4,0,0,B4 + MVC B4,CSR + B B3 + NOP 5 +;} + +;----------------------------------------------------------- +; void rt_hw_interrupt_enable(rt_base_t scr) +;----------------------------------------------------------- + .global rt_hw_interrupt_enable +rt_hw_interrupt_enable: +;{ + MVC A4,CSR + B B3 + NOP 5 +;} + +; +;----------------------------------------------------------- +; + +; +; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); +; A4 --> from +; B4 --> to +; + .global rt_hw_context_switch +rt_hw_context_switch: +; { + SUBAW .D2 SP,2,SP + ADD .D1X SP,-8,A15 + || STDW .D2T1 A15:A14,*SP--[3] ; Store A15:A14 + + STDW .D2T2 B13:B12,*SP--[1] ; Store B13:B12 + || STDW .D1T1 A13:A12,*A15--[1] ; Store A13:A12 + || MV B3,B13 + STDW .D2T2 B11:B10,*SP--[1] ; Store B11:B10 + || STDW .D1T1 A11:A10,*A15--[1] ; Store A11:A10 + || MVC .S2 CSR,B12 + STDW .D2T2 B13:B12,*SP--[1] ; Store PC:CSR + || MVC .S2 TSR,B5 + + MVC ILC,B11 ; + MVC RILC,B10 ; + STDW .D2T2 B11:B10,*SP--[1] ; Store RILC:ILC + || MV .S1X B5,A3 + + ZERO A2 ; + STDW .D2T1 A3:A2,*SP--[1] ; Store TSR:stack type + STW SP,*A4 ; Save thread's stack pointer + + MV B4,A4 ; + B rt_hw_context_switch_to + NOP 5 +;} + +; +; void rt_hw_context_switch_to(rt_uint32 to); +; A4 --> to +; + .global rt_hw_context_switch_to +rt_hw_context_switch_to: +;{ + LDW *A4,SP + NOP 4 + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) and stack frame type (B8) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + NOP 2 + MV B8,B0 + [B0] B _rt_thread_interrupt_stack ; + NOP 5 +; +; this maybe do better +; + MVC .S2 B11,RILC ; Restore RILC + MVC .S2 B10,ILC ; Restore ILC + MV B13,B3 ; Restore PC + MVC .S2 B12,CSR ; Restore CSR + + LDDW *++SP[1],B11:B10 + LDDW *++SP[1],B13:B12 + LDDW *++SP[1],A11:A10 + LDDW *++SP[1],A13:A12 + LDDW *++SP[1],A15:A14 + B B3 ; Return to caller + ADDAW SP,2,SP + NOP 4 ; Delay slots +_rt_thread_interrupt_stack: + ADDAW .D1X SP,30,A15 + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,ITSR ; Restore ITSR + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC ; Restore RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC ; Restore ILC + + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,IRP ; Restore IPR + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR ; Restore CSR + + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + LDDW .D2T1 *++SP[1],A15:A14 + B IRP ; Return to point of interrupt + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 ; Delay slots +;} + +; +;----------------------------------------------------------- +; + +; +; void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to) +; A4 --> from +; B4 --> to + .global rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + SUB B15,0x8,B15 + STW B4,*B15[2] + STW A4,*B15[1] + LDW *+B14(rt_thread_switch_interrupt_flag),B4 + NOP 4 + CMPEQ 1,B4,B0 + [ B0] BNOP _reswitch,5 + MVK 1,B4 + STW B4,*+B14(rt_thread_switch_interrupt_flag) + MV A4,B4 + STW B4,*+B14(rt_interrupt_from_thread) +_reswitch: + LDW *B15[2],B4 + NOP 4 + STW B4,*+B14(rt_interrupt_to_thread) + ADD 8,B15,B15 + BNOP B3,5 +;} + +;----------------------------------------------------------- +; +;void rt_interrupt_context_restore(void) +; + .global rt_interrupt_context_restore +rt_interrupt_context_restore: +;{ +; if rt_switch_interrupt_flag set, jump to rt_hw_context_switch_interrupt and don't return + MVKL rt_thread_switch_interrupt_flag,A3 + MVKH rt_thread_switch_interrupt_flag,A3 + LDW *A3,A1 + NOP 4 + CMPEQ 1,A1,A2 + [A2] BNOP rt_preempt_context_restore,5 + NOP 5 + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + + ADDAW .D1X SP,30,A15 + + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,ITSR + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,IRP + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + LDDW .D2T1 *++SP[1],A15:A14 + B .S2 IRP ; return from interruption + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 + +rt_preempt_context_restore: + ZERO A12 + STW A12,*A3 ; clear rt_thread_switch_interrupt_flag + + MVKL rt_interrupt_from_thread,A11 + MVKH rt_interrupt_from_thread,A11 + LDW *A11,A10 + NOP + MVKL rt_interrupt_to_thread,B10 + MVKH rt_interrupt_to_thread,B10 + LDW *B10,B11 + NOP 3 + STW SP,*A10 ; store sp in preempted tasks's TCB + MV B11,A4 ; + B rt_hw_context_switch_to + NOP 5 +;} + + .end + diff --git a/libcpu/ti-dsp/c6x/cpuport.c b/libcpu/ti-dsp/c6x/cpuport.c new file mode 100644 index 0000000000..a00a2e9046 --- /dev/null +++ b/libcpu/ti-dsp/c6x/cpuport.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include +#include + +#include "trap.h" + +/*------------ rt_hw_cpu_shutdown() function ---------------------------------- + * DESCRIPTION: Shutdown CPU + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +RT_WEAK void rt_hw_cpu_shutdown(void) +{ + rt_kprintf("shutdown...\n"); + + rt_hw_interrupt_disable(); + + RT_ASSERT(0); +} +//----------------------------------------------------------------------------- + +/*------------ nested_exception_handler() function --------------------------- + * DESCRIPTION: Function handles Nested Exception + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ + +void nested_exception_handler(void) +{ + for ( ; ; ); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_nmi_handler() function -------------------------------------- + * DESCRIPTION: Function handles NMI interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_nmi_handler(struct rt_hw_exp_stack_register *regs) +{ + for ( ; ; ); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_bad_handler() function -------------------------------------- + * DESCRIPTION: Function handles Bad interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_bad_handler(void) +{ + for ( ; ; ); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int4_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT4 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int4_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int5_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT5 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int5_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int6_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT6 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int6_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int7_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT7 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int7_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int8_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT8 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int8_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int9_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT9 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int9_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int10_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT10 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int10_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int11_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT11 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int11_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int12_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT12 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int12_handler(void) +{ +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int13_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT13 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int13_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------------ hw_int14_handler() function ------------------------------ + * DESCRIPTION: Function handles INT14 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: +-----------------------------------------------------------------------------*/ +void hw_int14_handler(void) +{ +extern void rt_hw_systick_isr(); + rt_hw_systick_isr(); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int15_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT15 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int15_handler(void) +{ + +} + diff --git a/libcpu/ti-dsp/c6x/inct.asm b/libcpu/ti-dsp/c6x/inct.asm new file mode 100644 index 0000000000..4f866e4800 --- /dev/null +++ b/libcpu/ti-dsp/c6x/inct.asm @@ -0,0 +1,374 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; interrupt handler for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +DP .set B14 +SP .set B15 +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; global function +;----------------------------------------------------------- + .global _nmi_handler + .global _bad_handler + .global _int4_handler + .global _int5_handler + .global _int6_handler + .global _int7_handler + .global _int8_handler + .global _int9_handler + .global _int10_handler + .global _int11_handler + .global _int12_handler + .global _int13_handler + .global _int14_handler + .global _int15_handler +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; extern function +;----------------------------------------------------------- + .ref hw_nmi_handler + .ref hw_bad_handler + .ref hw_int4_handler + .ref hw_int5_handler + .ref hw_int6_handler + .ref hw_int7_handler + .ref hw_int8_handler + .ref hw_int9_handler + .ref hw_int10_handler + .ref hw_int11_handler + .ref hw_int12_handler + .ref hw_int13_handler + .ref hw_int14_handler + .ref hw_int15_handler + .ref rt_hw_process_exception + .ref rt_interrupt_context_restore +; +;----------------------------------------------------------- +; + +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +SAVE_ALL .macro __rp, __tsr + STDW .D2T2 SP:DP,*--SP[1] + SUBAW .D2 SP,2,SP + ADD .D1X SP,-8,A15 + || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 + + STDW .D2T2 B13:B12,*SP--[1] + || STDW .D1T1 A13:A12,*A15--[1] + || MVC .S2 __rp,B13 + + STDW .D2T2 B11:B10,*SP--[1] + || STDW .D1T1 A11:A10,*A15--[1] + || MVC .S2 CSR,B12 + + STDW .D2T2 B9:B8,*SP--[1] + || STDW .D1T1 A9:A8,*A15--[1] + || MVC .S2 RILC,B11 + STDW .D2T2 B7:B6,*SP--[1] + || STDW .D1T1 A7:A6,*A15--[1] + || MVC .S2 ILC,B10 + + STDW .D2T2 B5:B4,*SP--[1] + || STDW .D1T1 A5:A4,*A15--[1] + + STDW .D2T2 B3:B2,*SP--[1] + || STDW .D1T1 A3:A2,*A15--[1] + || MVC .S2 __tsr,B5 + + STDW .D2T2 B1:B0,*SP--[1] + || STDW .D1T1 A1:A0,*A15--[1] + || MV .S1X B5,A5 + + STDW .D2T2 B31:B30,*SP--[1] + || STDW .D1T1 A31:A30,*A15--[1] + || MVKL 1,A4 + + STDW .D2T2 B29:B28,*SP--[1] + || STDW .D1T1 A29:A28,*A15--[1] + STDW .D2T2 B27:B26,*SP--[1] + || STDW .D1T1 A27:A26,*A15--[1] + STDW .D2T2 B25:B24,*SP--[1] + || STDW .D1T1 A25:A24,*A15--[1] + STDW .D2T2 B23:B22,*SP--[1] + || STDW .D1T1 A23:A22,*A15--[1] + STDW .D2T2 B21:B20,*SP--[1] + || STDW .D1T1 A21:A20,*A15--[1] + STDW .D2T2 B19:B18,*SP--[1] + || STDW .D1T1 A19:A18,*A15--[1] + STDW .D2T2 B17:B16,*SP--[1] + || STDW .D1T1 A17:A16,*A15--[1] + + STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR + + STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 + .endm + +RESTORE_ALL .macro __rp, __tsr + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + + ADDAW .D1X SP,30,A15 + + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,__tsr + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,__rp + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + LDDW .D2T1 *++SP[1],A15:A14 + B .S2 __rp ; return from interruption + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 + .endm +;----------------------------------------------------------- +; interrupt macro definition +;----------------------------------------------------------- +RT_INTERRUPT_ENTRY .macro + SAVE_ALL IRP,ITSR + .endm + +RT_CALL_INT .macro __isr + CALLP __isr,B3 + B .S1 rt_interrupt_context_restore + NOP 5 + .endm +;----------------------------------------------------------- +; execption macro definition +;----------------------------------------------------------- +RT_EXECPTION_ENTRY .macro + SAVE_ALL NRP,NTSR + .endm + +RT_EXECPTION_EXIT .macro + RESTORE_ALL NRP,NTSR + .endm + +; +;----------------------------------------------------------- +; + + .sect ".text" +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; handler NMI interrupt +;----------------------------------------------------------- +_nmi_handler: +;{ + RT_EXECPTION_ENTRY + MVC .S2 EFR,B2 + CMPEQ .L2 1,B2,B2 + || MVC .S2 TSR,B1 + MV .D1X B2,A2 + || CLR .S2 B1,10,10,B1 + MVC .S2 B1,TSR + [!A2] MVKL .S1 rt_hw_process_exception,A0 + ||[B2] MVKL .S2 rt_hw_software_exception,B1 + [!A2] MVKH .S1 rt_hw_process_exception,A0 + ||[B2] MVKH .S2 rt_hw_software_exception,B1 + [!B2] B .S2X A0 + [B2] B .S2 B1 + [!B2] ADDAW .D2 SP,2,B1 + [!B2] MV .D1X B1,A4 + ADDKPC .S2 ret_from_trap,B3,2 +; +; return from trap +; +ret_from_trap: + MV .D2X A4,B0 + [!B0] MVKL .S2 ret_from_exception,B3 + [!B0] MVKH .S2 ret_from_exception,B3 + [!B0] BNOP .S2 B3,5 +; +; return from trap£¬restore exception context +; +ret_from_exception: + RT_EXECPTION_EXIT +; +rt_hw_software_exception: + MVKL .S1 rt_hw_process_exception,A0 + MVKH .S1 rt_hw_process_exception,A0 + B .S2X A0 + ADDAW .D2 SP,2,B1 + MV .D1X B1,A4 + ADDKPC .S2 ret_from_trap,B3,2 + NOP 2 +;} + +;----------------------------------------------------------- +; handler bad interrupt +;----------------------------------------------------------- +_bad_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_bad_handler +;} + +;----------------------------------------------------------- +; handler INT4 interrupt +;----------------------------------------------------------- +_int4_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int4_handler +;} + +;----------------------------------------------------------- +; handler INT5 interrupt +;----------------------------------------------------------- +_int5_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int5_handler +;} + +;----------------------------------------------------------- +; handler INT6 interrupt +;----------------------------------------------------------- +_int6_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int6_handler +;} + +;----------------------------------------------------------- +; handler INT7 interrupt +;----------------------------------------------------------- +_int7_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int7_handler +;} +;----------------------------------------------------------- +; handler INT8 interrupt +;----------------------------------------------------------- +_int8_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int8_handler +;} + +;----------------------------------------------------------- +; handler INT9 interrupt +;----------------------------------------------------------- +_int9_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int9_handler +;} + +;----------------------------------------------------------- +; handler INT10 interrupt +;----------------------------------------------------------- +_int10_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int10_handler +;} + +;----------------------------------------------------------- +; handler INT11 interrupt +;----------------------------------------------------------- +_int11_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int11_handler +;} + +;----------------------------------------------------------- +; handler INT12 interrupt +;----------------------------------------------------------- +_int12_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int12_handler +;} + +;----------------------------------------------------------- +; handler INT13 interrupt +;----------------------------------------------------------- +_int13_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int13_handler +;} + +;----------------------------------------------------------- +; handler INT14 interrupt +;----------------------------------------------------------- +_int14_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int14_handler +;} +;----------------------------------------------------------- +; handler INT15 interrupt +;----------------------------------------------------------- +_int15_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int15_handler +;} + .end diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c new file mode 100644 index 0000000000..69205e0d38 --- /dev/null +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + + +#include "c66xx.h" +#include "interrupt.h" + +#define MAX_HANDLERS 128 + +extern volatile rt_uint8_t rt_interrupt_nest; +struct rt_irq_desc isr_table[MAX_HANDLERS]; +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + /* init exceptions table */ + rt_memset(isr_table, 0x00, sizeof(isr_table)); + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + if (vector < 0 || vector >= MAX_HANDLERS) + return; +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + if (vector < 0 || vector >= MAX_HANDLERS) + return; +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS || vector >= 0) + { + old_handler = isr_table[vector].handler; + + if (handler != RT_NULL) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + } + + return old_handler; +} + +void rt_hw_interrupt_clear(int vector) +{ + if (vector < 0 || vector >= MAX_HANDLERS) + return; +} diff --git a/libcpu/ti-dsp/c6x/interrupt.h b/libcpu/ti-dsp/c6x/interrupt.h new file mode 100644 index 0000000000..de7935b38a --- /dev/null +++ b/libcpu/ti-dsp/c6x/interrupt.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include +#include + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); +void rt_hw_interrupt_clear(int vector); +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); + +#endif /* __INTERRUPT_H__ */ diff --git a/libcpu/ti-dsp/c6x/stack.asm b/libcpu/ti-dsp/c6x/stack.asm new file mode 100644 index 0000000000..4415a9767c --- /dev/null +++ b/libcpu/ti-dsp/c6x/stack.asm @@ -0,0 +1,103 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; build system stack for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +ADDRESS_MSK .set 0xFFFFFFF0 + +; +;----------------------------------------------------------- +; + + .sect ".text" +; +; rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) +; tentry --> A4 +; parameter --> B4 +; stack_addr --> A6 +; texit --> B6 +;{ + .global rt_hw_stack_init +rt_hw_stack_init: + SUB A6,1,B1 ; + MVKL ADDRESS_MSK,A1 ; + MVKH ADDRESS_MSK,A1 ; Build address mask + MVC CSR,B0 ; + AND -2,B0,B0 ; Clear GIE bit + OR 2,B0,B0 ; Set PGIE bit for interrupt return + AND A1,B1,B1 ; Ensure alignment +; +; Actually build the stack frame. +; + MV B1,A3 + MV B14,A2 + STDW A3:A2,*--B1[1] ; Initial B15:B14 + SUBAW .D2 B1,2,B1 + ZERO A2 + ZERO A3 ; Clear value + STDW A3:A2,*B1--[1] ; Initial A15:A14 + STDW A3:A2,*B1--[1] ; Initial A13:A12 + STDW A3:A2,*B1--[1] ; Initial A11:A10 + STDW A3:A2,*B1--[1] ; Initial A9:A8 + STDW A3:A2,*B1--[1] ; Initial A7:A6 + MV B4,A2 + STDW A3:A2,*B1--[1] ; Initial A5:A4 + ZERO A2 + STDW A3:A2,*B1--[1] ; Initial A3:A2 + STDW A3:A2,*B1--[1] ; Initial A1:A0 + + STDW A3:A2,*B1--[1] ; Initial A31:A30 + STDW A3:A2,*B1--[1] ; Initial A29:A28 + STDW A3:A2,*B1--[1] ; Initial A27:A26 + STDW A3:A2,*B1--[1] ; Initial A25:A24 + STDW A3:A2,*B1--[1] ; Initial A23:A22 + STDW A3:A2,*B1--[1] ; Initial A21:A20 + STDW A3:A2,*B1--[1] ; Initial A19:A18 + STDW A3:A2,*B1--[1] ; Initial A17:A16 + + STDW A3:A2,*B1--[1] ; Initial B13:B12 + STDW A3:A2,*B1--[1] ; Initial B11:B10 + STDW A3:A2,*B1--[1] ; Initial B9:B8 + STDW A3:A2,*B1--[1] ; Initial B7:B6 + STDW A3:A2,*B1--[1] ; Initial B5:B4 + MV B6,A3 + STDW A3:A2,*B1--[1] ; Initial B3:B2 + ZERO A3 + STDW A3:A2,*B1--[1] ; Initial B1:B0 + + STDW A3:A2,*B1--[1] ; Initial B31:B30 + STDW A3:A2,*B1--[1] ; Initial B29:B28 + STDW A3:A2,*B1--[1] ; Initial B27:B26 + STDW A3:A2,*B1--[1] ; Initial B25:B24 + STDW A3:A2,*B1--[1] ; Initial B23:B22 + STDW A3:A2,*B1--[1] ; Initial B21:B20 + STDW A3:A2,*B1--[1] ; Initial B19:B18 + STDW A3:A2,*B1--[1] ; Initial B17:B16 + + MV A4,A3 + MV B0,A2 + STDW A3:A2,*B1--[1] ; Initial PC:CSR + + ZERO A2 + ZERO A3 + STDW A3:A2,*B1--[1] ; Initial ILC:RILC + B B3 + MVKL 0x3,B0 + MV B0,A3 + MVKL 1,A2 + STDW A3:A2,*B1--[1] ; Initial TSR:stack type + MV B1,A4 ; Save to TCB +;} + .end diff --git a/libcpu/ti-dsp/c6x/trap.c b/libcpu/ti-dsp/c6x/trap.c new file mode 100644 index 0000000000..eb1863fa9c --- /dev/null +++ b/libcpu/ti-dsp/c6x/trap.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include "trap.h" +#include "c66xx.h" + +#include +#include + +void rt_trap_init(void) +{ + ack_exception(EXCEPT_TYPE_NXF); + ack_exception(EXCEPT_TYPE_EXC); + ack_exception(EXCEPT_TYPE_IXF); + ack_exception(EXCEPT_TYPE_SXF); + rt_hw_enable_exception(); +} + +void show_regs(struct rt_hw_exp_stack_register *regs) +{ + rt_kprintf("\n"); + rt_kprintf("PC: %08lx SP: %08lx\n", + regs->pc, regs->hw_register.sp); + rt_kprintf("Status: %08lx ORIG_A4: %08lx\n", + regs->csr, regs->orig_a4); + rt_kprintf("A0: %08lx B0: %08lx\n", + regs->hw_register.a0, regs->hw_register.b0); + rt_kprintf("A1: %08lx B1: %08lx\n", + regs->hw_register.a1, regs->hw_register.b1); + rt_kprintf("A2: %08lx B2: %08lx\n", + regs->hw_register.a2, regs->hw_register.b2); + rt_kprintf("A3: %08lx B3: %08lx\n", + regs->hw_register.a3, regs->hw_register.b3); + rt_kprintf("A4: %08lx B4: %08lx\n", + regs->hw_register.a4, regs->hw_register.b4); + rt_kprintf("A5: %08lx B5: %08lx\n", + regs->hw_register.a5, regs->hw_register.b5); + rt_kprintf("A6: %08lx B6: %08lx\n", + regs->hw_register.a6, regs->hw_register.b6); + rt_kprintf("A7: %08lx B7: %08lx\n", + regs->hw_register.a7, regs->hw_register.b7); + rt_kprintf("A8: %08lx B8: %08lx\n", + regs->hw_register.a8, regs->hw_register.b8); + rt_kprintf("A9: %08lx B9: %08lx\n", + regs->hw_register.a9, regs->hw_register.b9); + rt_kprintf("A10: %08lx B10: %08lx\n", + regs->hw_register.a10, regs->hw_register.b10); + rt_kprintf("A11: %08lx B11: %08lx\n", + regs->hw_register.a11, regs->hw_register.b11); + rt_kprintf("A12: %08lx B12: %08lx\n", + regs->hw_register.a12, regs->hw_register.b12); + rt_kprintf("A13: %08lx B13: %08lx\n", + regs->hw_register.a13, regs->hw_register.b13); + rt_kprintf("A14: %08lx B14: %08lx\n", + regs->hw_register.a14, regs->hw_register.dp); + rt_kprintf("A15: %08lx B15: %08lx\n", + regs->hw_register.a15, regs->hw_register.sp); + rt_kprintf("A16: %08lx B16: %08lx\n", + regs->hw_register.a16, regs->hw_register.b16); + rt_kprintf("A17: %08lx B17: %08lx\n", + regs->hw_register.a17, regs->hw_register.b17); + rt_kprintf("A18: %08lx B18: %08lx\n", + regs->hw_register.a18, regs->hw_register.b18); + rt_kprintf("A19: %08lx B19: %08lx\n", + regs->hw_register.a19, regs->hw_register.b19); + rt_kprintf("A20: %08lx B20: %08lx\n", + regs->hw_register.a20, regs->hw_register.b20); + rt_kprintf("A21: %08lx B21: %08lx\n", + regs->hw_register.a21, regs->hw_register.b21); + rt_kprintf("A22: %08lx B22: %08lx\n", + regs->hw_register.a22, regs->hw_register.b22); + rt_kprintf("A23: %08lx B23: %08lx\n", + regs->hw_register.a23, regs->hw_register.b23); + rt_kprintf("A24: %08lx B24: %08lx\n", + regs->hw_register.a24, regs->hw_register.b24); + rt_kprintf("A25: %08lx B25: %08lx\n", + regs->hw_register.a25, regs->hw_register.b25); + rt_kprintf("A26: %08lx B26: %08lx\n", + regs->hw_register.a26, regs->hw_register.b26); + rt_kprintf("A27: %08lx B27: %08lx\n", + regs->hw_register.a27, regs->hw_register.b27); + rt_kprintf("A28: %08lx B28: %08lx\n", + regs->hw_register.a28, regs->hw_register.b28); + rt_kprintf("A29: %08lx B29: %08lx\n", + regs->hw_register.a29, regs->hw_register.b29); + rt_kprintf("A30: %08lx B30: %08lx\n", + regs->hw_register.a30, regs->hw_register.b30); + rt_kprintf("A31: %08lx B31: %08lx\n", + regs->hw_register.a31, regs->hw_register.b31); +} + + +void do_trap(struct rt_exception_info *except_info, struct rt_hw_exp_stack_register *regs) +{ + rt_kprintf("Enter exception: %s\n", except_info->kernel_str); + + show_regs(regs); + + for( ; ; ); +} + + +static struct rt_exception_info iexcept_table[10] = { + { " - instruction fetch", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - fetch packet", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - execute packet", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - resource conflict", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - resource access", ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL }, + { " - privilege", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - loops buffer", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - software exception", ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL }, + { " - unknown exception", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL } +}; + +/* + * Process an internal exception (non maskable) + */ +static int process_iexcept(struct rt_hw_exp_stack_register *regs) +{ + unsigned int iexcept_report = get_iexcept(); + unsigned int iexcept_num; + + ack_exception(EXCEPT_TYPE_IXF); + + while(iexcept_report) { + iexcept_num = __ffs(iexcept_report); + iexcept_report &= ~(1 << iexcept_num); + set_iexcept(iexcept_report); + + if (*(unsigned int *)regs->pc == BKPT_OPCODE) { + /* This is a breakpoint */ + struct rt_exception_info bkpt_exception = { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; + do_trap(&bkpt_exception, regs); + iexcept_report &= ~(0xFF); + set_iexcept(iexcept_report); + continue; + } + + do_trap(&iexcept_table[iexcept_num], regs); + } + return 0; +} + +static struct rt_exception_info except_table[128] = { + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - EMC CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - EMC bus error", ABORT_TYPE_MAP, ABORT_BUS_ADDRERR } +}; + +/* + * Process an external exception (maskable) + */ +static void process_except(struct rt_hw_exp_stack_register *regs) +{ + int except_num; + int bank = 0; + int i; + + for (i = 0; i <= 3; i++) { + while (INTC_MEXPMASK[i]) { + __dint(); + except_num = __ffs(INTC_MEXPMASK[i]); + INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */ + __rint(); + do_trap(&except_table[except_num + (bank << 5)], regs); + } + bank++; + } + + ack_exception(EXCEPT_TYPE_EXC); +} + +extern void hw_nmi_handler(struct rt_hw_exp_stack_register *regs); + +/* + * Main exception processing + */ +int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) +{ + int type; + int type_num; + int ie_num = 9; /* default is unknown exception */ + + while ((type = get_except_type()) != 0) { + type_num = fls(type) - 1; + + switch(type_num) { + case EXCEPT_TYPE_NXF: /* NMI exception */ + ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ + if (hw_nmi_handler != RT_NULL) + hw_nmi_handler(regs); + break; + + case EXCEPT_TYPE_IXF: /* internal exception */ + if (process_iexcept(regs)) + return 1; + break; + + case EXCEPT_TYPE_EXC: /* external exception */ + process_except(regs); + break; + + case EXCEPT_TYPE_SXF: /* software exception */ + ie_num = 8; + ack_exception(type_num); + break; + default: /* clear exception */ + ack_exception(type_num); + do_trap(&iexcept_table[ie_num], regs); + break; + } + } + return 0; +} + diff --git a/libcpu/ti-dsp/c6x/trap.h b/libcpu/ti-dsp/c6x/trap.h new file mode 100644 index 0000000000..5494fa900b --- /dev/null +++ b/libcpu/ti-dsp/c6x/trap.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#ifndef __TRAP_H__ +#define __TRAP_H__ + +#include "c66xx.h" + +/* + * exception operation macro + */ +#define disable_exception() +#define get_except_type() EFR +#define ack_exception(type) ECR = 1ul << (type) +#define get_iexcept() IERR +#define set_iexcept(mask) IERR = (mask) + +/* + * exception types + */ +#define EXCEPT_TYPE_NXF 31 /* NMI */ +#define EXCEPT_TYPE_EXC 30 /* external exception */ +#define EXCEPT_TYPE_IXF 1 /* internal exception */ +#define EXCEPT_TYPE_SXF 0 /* software exception */ + +#define EXCEPT_CAUSE_LBX (1 << 7) /* loop buffer exception */ +#define EXCEPT_CAUSE_PRX (1 << 6) /* privilege exception */ +#define EXCEPT_CAUSE_RAX (1 << 5) /* resource access exception */ +#define EXCEPT_CAUSE_RCX (1 << 4) /* resource conflict exception */ +#define EXCEPT_CAUSE_OPX (1 << 3) /* opcode exception */ +#define EXCEPT_CAUSE_EPX (1 << 2) /* execute packet exception */ +#define EXCEPT_CAUSE_FPX (1 << 1) /* fetch packet exception */ +#define EXCEPT_CAUSE_IFX (1 << 0) /* instruction fetch exception */ + +enum SYSTEM_TRAP_CODE +{ + ABORT_BUS_ADDRERR = 0, // bus address error + ABORT_BUS_ACCERR, // bus access permission error + ABORT_OPCODE_ILL, // illegal opcode + ABORT_PRVREG_ILL, // privilege register + ABORT_PRVOPC_ILL, // privileged opcode + ABORT_ILLTRP_ILL, // illegal trap + ABORT_BRKPT_ILL, // handling breakpoints +}; + +/* + * abort types + */ +#define ABORT_TYPE_BUS 0 // bus access abnormal +#define ABORT_TYPE_MAP 1 // page table mapping error +#define ABORT_TYPE_UNDDEF 0xff // undefined exception +#define ABORT_TYPE_FATAL 0xffffffff // fatal error + +struct rt_exception_info { + char *kernel_str; + int type; + int code; +}; + +#define BKPT_OPCODE 0x56454314 /* illegal opcode */ +#define INTC_MEXPMASK __SYSREGA(0x018000e0, unsigned int) + +#define __ffs(a) (_lmbd(1, _bitr(a))) +#define fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) + +void rt_trap_init(void); + +#endif /* __TRAP_H__ */ + diff --git a/libcpu/ti-dsp/c6x/vector.asm b/libcpu/ti-dsp/c6x/vector.asm new file mode 100644 index 0000000000..47eb8781f5 --- /dev/null +++ b/libcpu/ti-dsp/c6x/vector.asm @@ -0,0 +1,95 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; interrupt vector table for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; extern function +;----------------------------------------------------------- + .ref _c_int00 ; entry point + .ref _nmi_handler + .ref _bad_handler + .ref _int4_handler + .ref _int5_handler + .ref _int6_handler + .ref _int7_handler + .ref _int8_handler + .ref _int9_handler + .ref _int10_handler + .ref _int11_handler + .ref _int12_handler + .ref _int13_handler + .ref _int14_handler + .ref _int15_handler + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- + +; +; create interrupt vector for reset (interrupt 0) +; +VEC_RESET .macro addr + MVKL addr,B0 + MVKH addr,B0 + B B0 + MVC PCE1,B0 + NOP 4 + .align 32 + .endm + +; +; create interrupt vector for other used interrupts +; +IRQVEC .macro __name, __isr + .align 32 + .hidden __name + .global __name +__name: + B .S2 __isr + NOP + NOP + NOP + NOP + NOP + NOP + NOP + .endm +; +;----------------------------------------------------------- +; + +; +; vector table +; + .sect ".vecs" + .align 32 + .global vector +vector: + VEC_RESET _c_int00 + IRQVEC NMI, _nmi_handler + IRQVEC AINT, _bad_handler + IRQVEC MSGINT,_bad_handler + IRQVEC INT4, _int4_handler + IRQVEC INT5, _int5_handler + IRQVEC INT6, _int6_handler + IRQVEC INT7, _int7_handler + IRQVEC INT8, _int8_handler + IRQVEC INT9, _int9_handler + IRQVEC INT10, _int10_handler + IRQVEC INT11, _int11_handler + IRQVEC INT12, _int12_handler + IRQVEC INT13, _int13_handler + IRQVEC INT14, _int14_handler + IRQVEC INT15, _int15_handler + + .end -- cgit v1.3.1