summaryrefslogtreecommitdiff
path: root/libcpu/arc
diff options
context:
space:
mode:
authoryangjie11 <[email protected]>2020-11-18 09:56:35 +0800
committerGitHub <[email protected]>2020-11-18 09:56:35 +0800
commitd4a682e8d97fa131e5a8d795f8c5451d55cdd5b0 (patch)
tree4773b40cb012475c5daf74bfd55707e141477669 /libcpu/arc
parent2b98f4720c827ae1850df78299f6b273d568c8c7 (diff)
parent2ef3c9d861f55253620996a94831a4be31ca6620 (diff)
Merge pull request #3 from RT-Thread/master
sync
Diffstat (limited to 'libcpu/arc')
-rw-r--r--libcpu/arc/SConscript17
-rw-r--r--libcpu/arc/common/SConscript10
-rw-r--r--libcpu/arc/em/SConscript15
-rw-r--r--libcpu/arc/em/contex_gcc_mw.S364
-rw-r--r--libcpu/arc/em/cpuport.c87
5 files changed, 493 insertions, 0 deletions
diff --git a/libcpu/arc/SConscript b/libcpu/arc/SConscript
new file mode 100644
index 0000000000..3c69b578fa
--- /dev/null
+++ b/libcpu/arc/SConscript
@@ -0,0 +1,17 @@
+# RT-Thread building script for bridge
+
+import os
+from building import *
+
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+group = []
+
+# add common code files
+group = group + SConscript(os.path.join('common', 'SConscript'))
+
+# cpu porting code files
+group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript'))
+
+Return('group')
diff --git a/libcpu/arc/common/SConscript b/libcpu/arc/common/SConscript
new file mode 100644
index 0000000000..1c77347e61
--- /dev/null
+++ b/libcpu/arc/common/SConscript
@@ -0,0 +1,10 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd]
+
+
+group = DefineGroup('cpu', src, depend = [], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/libcpu/arc/em/SConscript b/libcpu/arc/em/SConscript
new file mode 100644
index 0000000000..ff1d8c134d
--- /dev/null
+++ b/libcpu/arc/em/SConscript
@@ -0,0 +1,15 @@
+# RT-Thread building script for component
+
+from building import *
+
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd]
+
+src += Glob('*.S')
+
+group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/libcpu/arc/em/contex_gcc_mw.S b/libcpu/arc/em/contex_gcc_mw.S
new file mode 100644
index 0000000000..81b291c1c8
--- /dev/null
+++ b/libcpu/arc/em/contex_gcc_mw.S
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2018, Synopsys, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#define __ASSEMBLY__
+#include "include/arc/arc.h"
+#include "include/arc/arc_asm_common.h"
+
+.global rt_interrupt_enter;
+.global rt_interrupt_leave;
+.global context_switch_reqflg;
+.global rt_interrupt_from_thread;
+.global rt_interrupt_to_thread;
+.global exc_nest_count;
+.global set_hw_stack_check;
+
+ .text
+ .align 4
+dispatcher:
+ st sp, [r0]
+ ld sp, [r1]
+#if ARC_FEATURE_STACK_CHECK
+#if ARC_FEATURE_SEC_PRESENT
+ lr r0, [AUX_SEC_STAT]
+ bclr r0, r0, AUX_SEC_STAT_BIT_SSC
+ sflag r0
+#else
+ lr r0, [AUX_STATUS32]
+ bclr r0, r0, AUX_STATUS_BIT_SC
+ kflag r0
+#endif
+ jl set_hw_stack_check
+#if ARC_FEATURE_SEC_PRESENT
+ lr r0, [AUX_SEC_STAT]
+ bset r0, r0, AUX_SEC_STAT_BIT_SSC
+ sflag r0
+#else
+ lr r0, [AUX_STATUS32]
+ bset r0, r0, AUX_STATUS_BIT_SC
+ kflag r0
+#endif
+#endif
+ pop r0
+ j [r0]
+
+/* return routine when task dispatch happened in task context */
+dispatch_r:
+ RESTORE_NONSCRATCH_REGS
+ j [blink]
+
+/*
+ * rt_base_t rt_hw_interrupt_disable();
+ */
+ .global rt_hw_interrupt_disable
+ .align 4
+rt_hw_interrupt_disable:
+ clri r0
+ j [blink]
+
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ */
+ .global rt_hw_interrupt_enable
+ .align 4
+rt_hw_interrupt_enable:
+ seti r0
+ j [blink]
+
+
+ .global rt_hw_context_switch_interrupt
+ .align 4
+rt_hw_context_switch_interrupt:
+ st r0, [rt_interrupt_from_thread]
+ st r1, [rt_interrupt_to_thread]
+ mov r0, 1
+ st r0, [context_switch_reqflg]
+ j [blink]
+
+
+/*
+ * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+ * r0 --> from
+ * r1 --> to
+ */
+ .global rt_hw_context_switch
+ .align 4
+rt_hw_context_switch:
+ SAVE_NONSCRATCH_REGS
+ mov r2, dispatch_r
+ push r2
+ b dispatcher
+
+
+/*
+ * void rt_hw_context_switch_to(rt_uint32 to);
+ * r0 --> to
+ */
+ .global rt_hw_context_switch_to
+ .align 4
+rt_hw_context_switch_to:
+ ld sp, [r0]
+#if ARC_FEATURE_STACK_CHECK
+ mov r1, r0
+#if ARC_FEATURE_SEC_PRESENT
+ lr r0, [AUX_SEC_STAT]
+ bclr r0, r0, AUX_SEC_STAT_BIT_SSC
+ sflag r0
+#else
+ lr r0, [AUX_STATUS32]
+ bclr r0, r0, AUX_STATUS_BIT_SC
+ kflag r0
+#endif
+ jl set_hw_stack_check
+#if ARC_FEATURE_SEC_PRESENT
+ lr r0, [AUX_SEC_STAT]
+ bset r0, r0, AUX_SEC_STAT_BIT_SSC
+ sflag r0
+#else
+ lr r0, [AUX_STATUS32]
+ bset r0, r0, AUX_STATUS_BIT_SC
+ kflag r0
+#endif
+#endif
+ pop r0
+ j [r0]
+
+ .global start_r
+ .align 4
+start_r:
+ pop blink;
+ pop r1
+ pop r2
+ pop r0
+
+ j_s.d [r1]
+ kflag r2
+
+/*
+ * int __rt_ffs(int value);
+ * r0 --> value
+ */
+ .global __rt_ffs
+ .align 4
+__rt_ffs:
+ breq r0, 0, __rt_ffs_return
+ ffs r1, r0
+ add r0, r1, 1
+__rt_ffs_return:
+ j [blink]
+
+/****** exceptions and interrupts handing ******/
+/****** entry for exception handling ******/
+ .global exc_entry_cpu
+ .align 4
+exc_entry_cpu:
+
+ EXCEPTION_PROLOGUE
+
+ mov blink, sp
+ mov r3, sp /* as exception handler's para(p_excinfo) */
+
+ ld r0, [exc_nest_count]
+ add r1, r0, 1
+ st r1, [exc_nest_count]
+ brne r0, 0, exc_handler_1
+/* change to exception stack if interrupt happened in task context */
+ mov sp, _e_stack
+exc_handler_1:
+ PUSH blink
+
+ lr r0, [AUX_ECR]
+ lsr r0, r0, 16
+ mov r1, exc_int_handler_table
+ ld.as r2, [r1, r0]
+
+ mov r0, r3
+ jl [r2]
+
+/* interrupts are not allowed */
+ret_exc:
+ POP sp
+ mov r1, exc_nest_count
+ ld r0, [r1]
+ sub r0, r0, 1
+ st r0, [r1]
+ brne r0, 0, ret_exc_1 /* nest exception case */
+ lr r1, [AUX_IRQ_ACT] /* nest interrupt case */
+ brne r1, 0, ret_exc_1
+
+ ld r0, [context_switch_reqflg]
+ brne r0, 0, ret_exc_2
+ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */
+ EXCEPTION_EPILOGUE
+ rtie
+
+/* there is a dispatch request */
+ret_exc_2:
+ /* clear dispatch request */
+ mov r0, 0
+ st r0, [context_switch_reqflg]
+
+ SAVE_CALLEE_REGS /* save callee save registers */
+
+ /* clear exception bit to do exception exit by SW */
+ lr r0, [AUX_STATUS32]
+ bclr r0, r0, AUX_STATUS_BIT_AE
+ kflag r0
+
+ mov r1, ret_exc_r /* save return address */
+ PUSH r1
+
+ ld r0, [rt_interrupt_from_thread]
+ ld r1, [rt_interrupt_to_thread]
+ b dispatcher
+
+ret_exc_r:
+ /* recover exception status */
+ lr r0, [AUX_STATUS32]
+ bset r0, r0, AUX_STATUS_BIT_AE
+ kflag r0
+
+ RESTORE_CALLEE_REGS
+ EXCEPTION_EPILOGUE
+ rtie
+
+/****** entry for normal interrupt exception handling ******/
+ .global exc_entry_int /* entry for interrupt handling */
+ .align 4
+exc_entry_int:
+#if ARC_FEATURE_FIRQ == 1
+/* check whether it is P0 interrupt */
+#if ARC_FEATURE_RGF_NUM_BANKS > 1
+ lr r0, [AUX_IRQ_ACT]
+ btst r0, 0
+ jnz exc_entry_firq
+#else
+ PUSH r10
+ lr r10, [AUX_IRQ_ACT]
+ btst r10, 0
+ POP r10
+ jnz exc_entry_firq
+#endif
+#endif
+ INTERRUPT_PROLOGUE
+
+ mov blink, sp
+
+ clri /* disable interrupt */
+ ld r3, [exc_nest_count]
+ add r2, r3, 1
+ st r2, [exc_nest_count]
+ seti /* enable higher priority interrupt */
+
+ brne r3, 0, irq_handler_1
+/* change to exception stack if interrupt happened in task context */
+ mov sp, _e_stack
+#if ARC_FEATURE_STACK_CHECK
+#if ARC_FEATURE_SEC_PRESENT
+ lr r0, [AUX_SEC_STAT]
+ bclr r0, r0, AUX_SEC_STAT_BIT_SSC
+ sflag r0
+#else
+ lr r0, [AUX_STATUS32]
+ bclr r0, r0, AUX_STATUS_BIT_SC
+ kflag r0
+#endif
+#endif
+irq_handler_1:
+ PUSH blink
+
+ jl rt_interrupt_enter
+
+ lr r0, [AUX_IRQ_CAUSE]
+ sr r0, [AUX_IRQ_SELECT]
+ mov r1, exc_int_handler_table
+ ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */
+/* handle software triggered interrupt */
+ lr r3, [AUX_IRQ_HINT]
+ cmp r3, r0
+ bne.d irq_hint_handled
+ xor r3, r3, r3
+ sr r3, [AUX_IRQ_HINT]
+irq_hint_handled:
+ lr r3, [AUX_IRQ_PRIORITY]
+ PUSH r3 /* save irq priority */
+
+ jl [r2] /* jump to interrupt handler */
+ jl rt_interrupt_leave
+ret_int:
+ clri /* disable interrupt */
+ POP r3 /* irq priority */
+ POP sp
+ mov r1, exc_nest_count
+ ld r0, [r1]
+ sub r0, r0, 1
+ st r0, [r1]
+/* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
+ lr r0, [AUX_IRQ_CAUSE]
+ sr r0, [AUX_IRQ_SELECT]
+ lr r3, [AUX_IRQ_PRIORITY]
+ lr r1, [AUX_IRQ_ACT]
+ bclr r2, r1, r3
+ brne r2, 0, ret_int_1
+
+ ld r0, [context_switch_reqflg]
+ brne r0, 0, ret_int_2
+ret_int_1: /* return from non-task context */
+ INTERRUPT_EPILOGUE
+ rtie
+/* there is a dispatch request */
+ret_int_2:
+ /* clear dispatch request */
+ mov r0, 0
+ st r0, [context_switch_reqflg]
+
+ /* interrupt return by SW */
+ lr r10, [AUX_IRQ_ACT]
+ PUSH r10
+ bclr r10, r10, r3 /* clear related bits in IRQ_ACT */
+ sr r10, [AUX_IRQ_ACT]
+
+ SAVE_CALLEE_REGS /* save callee save registers */
+ mov r1, ret_int_r /* save return address */
+ PUSH r1
+
+ ld r0, [rt_interrupt_from_thread]
+ ld r1, [rt_interrupt_to_thread]
+ b dispatcher
+
+ret_int_r:
+ RESTORE_CALLEE_REGS
+ /* recover AUX_IRQ_ACT to restore the interrup status */
+ POPAX AUX_IRQ_ACT
+ INTERRUPT_EPILOGUE
+ rtie
+
+/****** entry for fast irq exception handling ******/
+ .global exc_entry_firq
+ .weak exc_entry_firq
+ .align 4
+exc_entry_firq:
+ SAVE_FIQ_EXC_REGS
+
+ lr r0, [AUX_IRQ_CAUSE]
+ mov r1, exc_int_handler_table
+/* r2 = _kernel_exc_tbl + irqno *4 */
+ ld.as r2, [r1, r0]
+
+/* for the case of software triggered interrupt */
+ lr r3, [AUX_IRQ_HINT]
+ cmp r3, r0
+ bne.d firq_hint_handled
+ xor r3, r3, r3
+ sr r3, [AUX_IRQ_HINT]
+firq_hint_handled:
+/* jump to interrupt handler */
+ mov r0, sp
+ jl [r2]
+
+firq_return:
+ RESTORE_FIQ_EXC_REGS
+ rtie
diff --git a/libcpu/arc/em/cpuport.c b/libcpu/arc/em/cpuport.c
new file mode 100644
index 0000000000..34f538881f
--- /dev/null
+++ b/libcpu/arc/em/cpuport.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, Synopsys, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <rtthread.h>
+
+#include "arc/arc_exception.h"
+
+#if ARC_FEATURE_STACK_CHECK
+#define ARC_INIT_STATUS ((1 << AUX_STATUS_BIT_SC) | AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE)
+#else
+#define ARC_INIT_STATUS (AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE)
+#endif
+
+extern void start_r(void);
+
+
+rt_uint32_t context_switch_reqflg;
+rt_uint32_t rt_interrupt_from_thread;
+rt_uint32_t rt_interrupt_to_thread;
+rt_uint32_t exc_nest_count;
+
+struct init_stack_frame {
+ rt_uint32_t pc;
+ rt_uint32_t blink;
+ rt_uint32_t task;
+ rt_uint32_t status32;
+ rt_uint32_t r0;
+};
+
+/**
+ * shutdown CPU
+ */
+void rt_hw_cpu_shutdown(void)
+{
+
+}
+
+rt_uint8_t *rt_hw_stack_init(void *tentry,
+ void *parameter,
+ rt_uint8_t *stack_addr,
+ void *texit)
+{
+ struct init_stack_frame *stack_frame;
+ rt_uint8_t *stk;
+
+ stk = stack_addr + sizeof(rt_uint32_t);
+ stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
+ stk -= sizeof(struct init_stack_frame);
+
+ stack_frame = (struct init_stack_frame *)stk;
+
+ stack_frame->pc = (rt_uint32_t)start_r;
+ stack_frame->blink = (rt_uint32_t)texit;
+ stack_frame->task = (rt_uint32_t)tentry;
+ stack_frame->status32 = ARC_INIT_STATUS;
+ stack_frame->r0 = (rt_uint32_t)parameter;
+
+ return stk;
+}
+
+
+/**
+ * This function set the hook, which is invoked on fault exception handling.
+ *
+ * @param exception_handle the exception handling hook function.
+ */
+void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context))
+{
+ exception_handle = exception_handle;
+}
+
+void set_hw_stack_check(rt_uint32_t *from, rt_uint32_t *to)
+{
+ struct rt_thread *rt_thread_to;
+ if (to != NULL) {
+ rt_thread_to = rt_container_of(to, struct rt_thread, sp);
+#if ARC_FEATURE_SEC_PRESENT
+ arc_aux_write(AUX_S_KSTACK_TOP, (uint32_t)(rt_thread_to->stack_addr));
+ arc_aux_write(AUX_S_KSTACK_BASE, (uint32_t)(rt_thread_to->stack_addr)+rt_thread_to->stack_size);
+#else
+ arc_aux_write(AUX_KSTACK_TOP, (uint32_t)(rt_thread_to->stack_addr));
+ arc_aux_write(AUX_KSTACK_BASE, (uint32_t)(rt_thread_to->stack_addr)+rt_thread_to->stack_size);
+#endif
+ }
+}