summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2018-12-18 23:10:04 +0800
committerGitHub <[email protected]>2018-12-18 23:10:04 +0800
commitbf62a7ffb7c90bbfd358b8b42c698b77d27e6bb0 (patch)
tree5b94cf68f3f0a9cde67f0d71c9dc7b7758d2d88d /libcpu
parent12b8a0cc3866a3d204fecb09095cd8d3d04242ba (diff)
parent5e0f8cb3aa0d9459985bf0345eef0192857d1b41 (diff)
Merge pull request #2088 from RT-Thread/bsp_k210
[libcpu] Add k210 BSP.
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/risc-v/k210/interrupt.c203
-rw-r--r--libcpu/risc-v/k210/interrupt_gcc.S137
-rw-r--r--libcpu/risc-v/k210/startup_gcc.S128
-rw-r--r--libcpu/risc-v/k210/tick.c48
-rw-r--r--libcpu/risc-v/k210/tick.h17
5 files changed, 533 insertions, 0 deletions
diff --git a/libcpu/risc-v/k210/interrupt.c b/libcpu/risc-v/k210/interrupt.c
new file mode 100644
index 0000000000..6d8866c3f0
--- /dev/null
+++ b/libcpu/risc-v/k210/interrupt.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/01 Bernard The first version
+ */
+
+#include <rthw.h>
+
+#include "tick.h"
+
+#include <plic.h>
+#include <clint.h>
+#include <interrupt.h>
+
+#define CPU_NUM 2
+#define MAX_HANDLERS IRQN_MAX
+
+static struct rt_irq_desc irq_desc[CPU_NUM][MAX_HANDLERS];
+
+static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
+{
+ rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
+ return RT_NULL;
+}
+
+/**
+ * This function will initialize hardware interrupt
+ */
+void rt_hw_interrupt_init(void)
+{
+ int idx;
+ int cpuid;
+
+ cpuid = current_coreid();
+
+ /* Disable all interrupts for the current core. */
+ for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
+ plic->target_enables.target[cpuid].enable[idx] = 0;
+
+ /* Set priorities to zero. */
+ for (idx = 0; idx < PLIC_NUM_SOURCES; idx++)
+ plic->source_priorities.priority[idx] = 0;
+
+ /* Set the threshold to zero. */
+ plic->targets.target[cpuid].priority_threshold = 0;
+
+ /* init exceptions table */
+ for (idx = 0; idx < MAX_HANDLERS; idx++)
+ {
+ rt_hw_interrupt_mask(idx);
+ irq_desc[cpuid][idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
+ irq_desc[cpuid][idx].param = RT_NULL;
+#ifdef RT_USING_INTERRUPT_INFO
+ rt_snprintf(irq_desc[cpuid][idx].name, RT_NAME_MAX - 1, "default");
+ irq_desc[idx][cpuid].counter = 0;
+#endif
+ }
+
+ /* Enable machine external interrupts. */
+ set_csr(mie, MIP_MEIP);
+}
+
+/**
+ * This function will mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_mask(int vector)
+{
+ plic_irq_disable(vector);
+}
+
+/**
+ * This function will un-mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_umask(int vector)
+{
+ plic_set_priority(vector, 1);
+ plic_irq_enable(vector);
+}
+
+/**
+ * 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)
+{
+ int cpuid;
+ rt_isr_handler_t old_handler = RT_NULL;
+
+ cpuid = current_coreid();
+
+ if(vector < MAX_HANDLERS)
+ {
+ old_handler = irq_desc[cpuid][vector].handler;
+ if (handler != RT_NULL)
+ {
+ irq_desc[cpuid][vector].handler = (rt_isr_handler_t)handler;
+ irq_desc[cpuid][vector].param = param;
+#ifdef RT_USING_INTERRUPT_INFO
+ rt_snprintf(irq_desc[cpuid][vector].name, RT_NAME_MAX - 1, "%s", name);
+ irq_desc[cpuid][vector].counter = 0;
+#endif
+ }
+ }
+
+ return old_handler;
+}
+
+uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
+{
+ /*
+ * After the highest-priority pending interrupt is claimed by a target
+ * and the corresponding IP bit is cleared, other lower-priority
+ * pending interrupts might then become visible to the target, and so
+ * the PLIC EIP bit might not be cleared after a claim. The interrupt
+ * handler can check the local meip/heip/seip/ueip bits before exiting
+ * the handler, to allow more efficient service of other interrupts
+ * without first restoring the interrupted context and taking another
+ * interrupt trap.
+ */
+ if (read_csr(mip) & MIP_MEIP)
+ {
+ /* Get current core id */
+ uint64_t core_id = current_coreid();
+ /* Get primitive interrupt enable flag */
+ uint64_t ie_flag = read_csr(mie);
+ /* Get current IRQ num */
+ uint32_t int_num = plic->targets.target[core_id].claim_complete;
+ /* Get primitive IRQ threshold */
+ uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
+ /* Set new IRQ threshold = current IRQ threshold */
+ plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
+
+ /* Disable software interrupt and timer interrupt */
+ clear_csr(mie, MIP_MTIP | MIP_MSIP);
+
+ if (irq_desc[core_id][int_num].handler)
+ {
+ irq_desc[core_id][int_num].handler(int_num, irq_desc[core_id][int_num].param);
+ }
+
+ /* Perform IRQ complete */
+ plic->targets.target[core_id].claim_complete = int_num;
+ /* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
+ set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
+ /* Restore primitive interrupt enable flag */
+ write_csr(mie, ie_flag);
+ /* Restore primitive IRQ threshold */
+ plic->targets.target[core_id].priority_threshold = int_threshold;
+ }
+ else
+ {
+ rt_kprintf("unhandled trap!\n");
+ }
+
+ return epc;
+}
+
+uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
+{
+ int cause = mcause & CAUSE_MACHINE_IRQ_REASON_MASK;
+
+ if (mcause & (1UL << 63))
+ {
+ switch (cause)
+ {
+ case IRQ_M_SOFT:
+ break;
+ case IRQ_M_EXT:
+ handle_irq_m_ext(mcause, epc);
+ break;
+ case IRQ_M_TIMER:
+ tick_isr();
+ break;
+ }
+ }
+ else
+ {
+ rt_thread_t tid;
+ extern long list_thread();
+
+ rt_hw_interrupt_disable();
+
+ tid = rt_thread_self();
+ rt_kprintf("\n");
+ rt_kprintf("unhandled trap, epc => 0x%08x, INT[%d]\n", epc, rt_interrupt_get_nest());
+ rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
+#ifdef RT_USING_FINSH
+ list_thread();
+#endif
+ while(1);
+ }
+
+ return epc;
+}
diff --git a/libcpu/risc-v/k210/interrupt_gcc.S b/libcpu/risc-v/k210/interrupt_gcc.S
new file mode 100644
index 0000000000..5783322237
--- /dev/null
+++ b/libcpu/risc-v/k210/interrupt_gcc.S
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/02 Bernard The first version
+ */
+
+#include "cpuport.h"
+
+ .section .text.entry
+ .align 2
+ .global trap_entry
+trap_entry:
+
+ /* save thread context to thread stack */
+ addi sp, sp, -32 * REGBYTES
+
+ STORE x1, 1 * REGBYTES(sp)
+ li t0, 0x80
+ STORE t0, 2 * REGBYTES(sp)
+
+ STORE x4, 4 * REGBYTES(sp)
+ STORE x5, 5 * REGBYTES(sp)
+ STORE x6, 6 * REGBYTES(sp)
+ STORE x7, 7 * REGBYTES(sp)
+ STORE x8, 8 * REGBYTES(sp)
+ STORE x9, 9 * REGBYTES(sp)
+ STORE x10, 10 * REGBYTES(sp)
+ STORE x11, 11 * REGBYTES(sp)
+ STORE x12, 12 * REGBYTES(sp)
+ STORE x13, 13 * REGBYTES(sp)
+ STORE x14, 14 * REGBYTES(sp)
+ STORE x15, 15 * REGBYTES(sp)
+ STORE x16, 16 * REGBYTES(sp)
+ STORE x17, 17 * REGBYTES(sp)
+ STORE x18, 18 * REGBYTES(sp)
+ STORE x19, 19 * REGBYTES(sp)
+ STORE x20, 20 * REGBYTES(sp)
+ STORE x21, 21 * REGBYTES(sp)
+ STORE x22, 22 * REGBYTES(sp)
+ STORE x23, 23 * REGBYTES(sp)
+ STORE x24, 24 * REGBYTES(sp)
+ STORE x25, 25 * REGBYTES(sp)
+ STORE x26, 26 * REGBYTES(sp)
+ STORE x27, 27 * REGBYTES(sp)
+ STORE x28, 28 * REGBYTES(sp)
+ STORE x29, 29 * REGBYTES(sp)
+ STORE x30, 30 * REGBYTES(sp)
+ STORE x31, 31 * REGBYTES(sp)
+
+ /* switch to interrupt stack */
+ move s0, sp
+
+ /* get cpu id */
+ csrr t0, mhartid
+
+ /* switch interrupt stack of current cpu */
+ la sp, __stack_start__
+ addi t1, t0, 1
+ li t2, __STACKSIZE__
+ mul t1, t1, t2
+ add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
+
+ /* handle interrupt */
+ call rt_interrupt_enter
+ csrr a0, mcause
+ csrr a1, mepc
+ mv a2, sp
+ call handle_trap
+ call rt_interrupt_leave
+
+ /* switch to from_thread stack */
+ move sp, s0
+
+ /* need to switch new thread */
+ la s0, rt_thread_switch_interrupt_flag
+ lw s2, 0(s0)
+ beqz s2, spurious_interrupt
+ sw zero, 0(s0)
+
+ csrr a0, mepc
+ STORE a0, 0 * REGBYTES(sp)
+
+ la s0, rt_interrupt_from_thread
+ LOAD s1, 0(s0)
+ STORE sp, 0(s1)
+
+ la s0, rt_interrupt_to_thread
+ LOAD s1, 0(s0)
+ LOAD sp, 0(s1)
+
+ LOAD a0, 0 * REGBYTES(sp)
+ csrw mepc, a0
+
+spurious_interrupt:
+ LOAD x1, 1 * REGBYTES(sp)
+
+ /* Remain in M-mode after mret */
+ li t0, 0x00001800
+ csrs mstatus, t0
+ LOAD t0, 2 * REGBYTES(sp)
+ csrs mstatus, t0
+
+ LOAD x4, 4 * REGBYTES(sp)
+ LOAD x5, 5 * REGBYTES(sp)
+ LOAD x6, 6 * REGBYTES(sp)
+ LOAD x7, 7 * REGBYTES(sp)
+ LOAD x8, 8 * REGBYTES(sp)
+ LOAD x9, 9 * REGBYTES(sp)
+ LOAD x10, 10 * REGBYTES(sp)
+ LOAD x11, 11 * REGBYTES(sp)
+ LOAD x12, 12 * REGBYTES(sp)
+ LOAD x13, 13 * REGBYTES(sp)
+ LOAD x14, 14 * REGBYTES(sp)
+ LOAD x15, 15 * REGBYTES(sp)
+ LOAD x16, 16 * REGBYTES(sp)
+ LOAD x17, 17 * REGBYTES(sp)
+ LOAD x18, 18 * REGBYTES(sp)
+ LOAD x19, 19 * REGBYTES(sp)
+ LOAD x20, 20 * REGBYTES(sp)
+ LOAD x21, 21 * REGBYTES(sp)
+ LOAD x22, 22 * REGBYTES(sp)
+ LOAD x23, 23 * REGBYTES(sp)
+ LOAD x24, 24 * REGBYTES(sp)
+ LOAD x25, 25 * REGBYTES(sp)
+ LOAD x26, 26 * REGBYTES(sp)
+ LOAD x27, 27 * REGBYTES(sp)
+ LOAD x28, 28 * REGBYTES(sp)
+ LOAD x29, 29 * REGBYTES(sp)
+ LOAD x30, 30 * REGBYTES(sp)
+ LOAD x31, 31 * REGBYTES(sp)
+
+ addi sp, sp, 32 * REGBYTES
+ mret
diff --git a/libcpu/risc-v/k210/startup_gcc.S b/libcpu/risc-v/k210/startup_gcc.S
new file mode 100644
index 0000000000..bc73f51e03
--- /dev/null
+++ b/libcpu/risc-v/k210/startup_gcc.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/01 Bernard The first version
+ */
+
+#define MSTATUS_FS 0x00006000U /* initial state of FPU */
+#include <cpuport.h>
+
+ .global _start
+ .section ".start", "ax"
+_start:
+ j 1f
+ .word 0xdeadbeef
+1:
+ csrw mideleg, 0
+ csrw medeleg, 0
+ csrw mie, 0
+ csrw mip, 0
+ la t0, trap_entry
+ csrw mtvec, t0
+
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10,0
+ li x11,0
+ li x12,0
+ li x13,0
+ li x14,0
+ li x15,0
+ li x16,0
+ li x17,0
+ li x18,0
+ li x19,0
+ li x20,0
+ li x21,0
+ li x22,0
+ li x23,0
+ li x24,0
+ li x25,0
+ li x26,0
+ li x27,0
+ li x28,0
+ li x29,0
+ li x30,0
+ li x31,0
+
+ /* set to initial state of FPU and disable interrupt */
+ li t0, MSTATUS_FS
+ csrs mstatus, t0
+
+ fssr x0
+ fmv.d.x f0, x0
+ fmv.d.x f1, x0
+ fmv.d.x f2, x0
+ fmv.d.x f3, x0
+ fmv.d.x f4, x0
+ fmv.d.x f5, x0
+ fmv.d.x f6, x0
+ fmv.d.x f7, x0
+ fmv.d.x f8, x0
+ fmv.d.x f9, x0
+ fmv.d.x f10,x0
+ fmv.d.x f11,x0
+ fmv.d.x f12,x0
+ fmv.d.x f13,x0
+ fmv.d.x f14,x0
+ fmv.d.x f15,x0
+ fmv.d.x f16,x0
+ fmv.d.x f17,x0
+ fmv.d.x f18,x0
+ fmv.d.x f19,x0
+ fmv.d.x f20,x0
+ fmv.d.x f21,x0
+ fmv.d.x f22,x0
+ fmv.d.x f23,x0
+ fmv.d.x f24,x0
+ fmv.d.x f25,x0
+ fmv.d.x f26,x0
+ fmv.d.x f27,x0
+ fmv.d.x f28,x0
+ fmv.d.x f29,x0
+ fmv.d.x f30,x0
+ fmv.d.x f31,x0
+
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+
+ /* get cpu id */
+ csrr a0, mhartid
+
+ la sp, __stack_start__
+ addi t1, a0, 1
+ li t2, __STACKSIZE__
+ mul t1, t1, t2
+ add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
+
+ /* other cpu core, jump to cpu entry directly */
+ bnez a0, _cpu_entry
+
+#if 0
+ /* clear bss section */
+ la a0, __bss_start
+ la a1, __bss_end
+ bgeu a0, a1, 2f
+1:
+ sw zero, (a0)
+ addi a0, a0, REGBYTES
+ bltu a0, a1, 1b
+2:
+#endif
+
+_cpu_entry:
+ csrr a0, mhartid
+ j cpu_entry
diff --git a/libcpu/risc-v/k210/tick.c b/libcpu/risc-v/k210/tick.c
new file mode 100644
index 0000000000..144f7f1fff
--- /dev/null
+++ b/libcpu/risc-v/k210/tick.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/28 Bernard The unify RISC-V porting code.
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include <encoding.h>
+#include <clint.h>
+#include <sysctl.h>
+
+static volatile unsigned long tick_cycles = 0;
+int tick_isr(void)
+{
+ uint64_t core_id = current_coreid();
+
+ clint->mtimecmp[core_id] += tick_cycles;
+ rt_tick_increase();
+
+ return 0;
+}
+
+/* Sets and enable the timer interrupt */
+int rt_hw_tick_init(void)
+{
+ /* Read core id */
+ unsigned long core_id = current_coreid();
+ unsigned long interval = 1000/RT_TICK_PER_SECOND;
+
+ /* Clear the Machine-Timer bit in MIE */
+ clear_csr(mie, MIP_MTIP);
+
+ /* calculate the tick cycles */
+ tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
+ /* Set mtimecmp by core id */
+ clint->mtimecmp[core_id] = clint->mtime + tick_cycles;
+
+ /* Enable the Machine-Timer bit in MIE */
+ set_csr(mie, MIP_MTIP);
+
+ return 0;
+}
diff --git a/libcpu/risc-v/k210/tick.h b/libcpu/risc-v/k210/tick.h
new file mode 100644
index 0000000000..0821004263
--- /dev/null
+++ b/libcpu/risc-v/k210/tick.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/28 Bernard The unify RISC-V porting code.
+ */
+
+#ifndef TICK_H__
+#define TICK_H__
+
+int tick_isr(void);
+int rt_hw_tick_init(void);
+
+#endif