diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/risc-v/k210/interrupt.c | 203 | ||||
| -rw-r--r-- | libcpu/risc-v/k210/interrupt_gcc.S | 137 | ||||
| -rw-r--r-- | libcpu/risc-v/k210/startup_gcc.S | 128 | ||||
| -rw-r--r-- | libcpu/risc-v/k210/tick.c | 48 | ||||
| -rw-r--r-- | libcpu/risc-v/k210/tick.h | 17 |
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 |
