mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-23 12:15:32 +08:00
[libcpu] Add k210 BSP.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user