添加rtthread相关代码
This commit is contained in:
204
riscv/rtthread/libcpu/risc-v/common/atomic_riscv.c
Executable file
204
riscv/rtthread/libcpu/risc-v/common/atomic_riscv.c
Executable file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-14 WangShun first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
rt_atomic_t rt_hw_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoswap.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
result = *ptr;
|
||||
*ptr = val;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoswap.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoadd.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) += val;
|
||||
result = *ptr;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoadd.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
val = -val;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoadd.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) += val;
|
||||
result = *ptr;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoadd.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoxor.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) ^= val;
|
||||
result = *ptr;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoxor.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoand.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) &= val;
|
||||
result = *ptr;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoand.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoor.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) |= val;
|
||||
result = *ptr;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoor.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoxor.w %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
result = *ptr;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoxor.d %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoswap.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) = val;
|
||||
result = *ptr;
|
||||
(void)result;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoswap.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_flag_test_and_set(volatile rt_atomic_t *ptr)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
rt_atomic_t temp = 1;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoor.w %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) |= 1;
|
||||
result = *ptr;
|
||||
(void)temp;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoor.d %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void rt_hw_atomic_flag_clear(volatile rt_atomic_t *ptr)
|
||||
{
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile ("amoand.w %0, x0, (%1)" : "=r"(result) :"r"(ptr) : "memory");
|
||||
rt_base_t irq = rt_hw_local_irq_disable();
|
||||
(*ptr) = 0;
|
||||
result = *ptr;
|
||||
(void)result;
|
||||
rt_hw_local_irq_enable(irq);
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile ("amoand.d %0, x0, (%1)" : "=r"(result) :"r"(ptr) : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_atomic_t *old, rt_atomic_t desired)
|
||||
{
|
||||
rt_atomic_t tmp = *old;
|
||||
rt_atomic_t result = 0;
|
||||
#if __riscv_xlen == 32
|
||||
// asm volatile(
|
||||
// " fence iorw, ow\n"
|
||||
// "1: lr.w.aq %[result], (%[ptr])\n"
|
||||
// " bne %[result], %[tmp], 2f\n"
|
||||
// " sc.w.rl %[tmp], %[desired], (%[ptr])\n"
|
||||
// " bnez %[tmp], 1b\n"
|
||||
// " li %[result], 1\n"
|
||||
// " j 3f\n"
|
||||
// " 2:sw %[result], (%[old])\n"
|
||||
// " li %[result], 0\n"
|
||||
// " 3:\n"
|
||||
// : [result]"+r" (result), [tmp]"+r" (tmp), [ptr]"+r" (ptr)
|
||||
// : [desired]"r" (desired), [old]"r"(old)
|
||||
// : "memory");
|
||||
(void)tmp;
|
||||
(void)ptr;
|
||||
(void)desired;
|
||||
#elif __riscv_xlen == 64
|
||||
asm volatile(
|
||||
" fence iorw, ow\n"
|
||||
"1: lr.d.aq %[result], (%[ptr])\n"
|
||||
" bne %[result], %[tmp], 2f\n"
|
||||
" sc.d.rl %[tmp], %[desired], (%[ptr])\n"
|
||||
" bnez %[tmp], 1b\n"
|
||||
" li %[result], 1\n"
|
||||
" j 3f\n"
|
||||
" 2:sd %[result], (%[old])\n"
|
||||
" li %[result], 0\n"
|
||||
" 3:\n"
|
||||
: [result]"+r" (result), [tmp]"+r" (tmp), [ptr]"+r" (ptr)
|
||||
: [desired]"r" (desired), [old]"r"(old)
|
||||
: "memory");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
307
riscv/rtthread/libcpu/risc-v/common/context_gcc.S
Executable file
307
riscv/rtthread/libcpu/risc-v/common/context_gcc.S
Executable file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* 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 implementation
|
||||
* 2018/12/27 Jesven Add SMP support
|
||||
* 2020/11/20 BalanceTWK Add FPU support
|
||||
* 2022/12/28 WangShun Add macro to distinguish whether FPU is supported
|
||||
* 2023/03/19 Flyingcys Add riscv_32e support
|
||||
*/
|
||||
|
||||
#define __ASSEMBLY__
|
||||
#include "cpuport.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable(void);
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
rt_hw_interrupt_disable:
|
||||
csrrci a0, mstatus, 8
|
||||
ret
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
csrw mstatus, a0
|
||||
ret
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to);
|
||||
* #endif
|
||||
* a0 --> to
|
||||
* a1 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
la t0, __rt_rvstack
|
||||
csrw mscratch,t0
|
||||
|
||||
LOAD sp, (a0)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mv a0, a1
|
||||
call rt_cpus_lock_status_restore
|
||||
#endif
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrw mstatus, a0
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*
|
||||
* a0 --> from
|
||||
* a1 --> to
|
||||
* a2 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
/* saved from thread context
|
||||
* x1/ra -> sp(0)
|
||||
* x1/ra -> sp(1)
|
||||
* mstatus.mie -> sp(2)
|
||||
* x(i) -> sp(i-4)
|
||||
*/
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
#ifndef __riscv_32e
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
#else
|
||||
addi sp, sp, -16 * REGBYTES
|
||||
#endif
|
||||
|
||||
STORE sp, (a0)
|
||||
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mstatus
|
||||
andi a0, a0, 8
|
||||
beqz a0, save_mpie
|
||||
li a0, 0x80
|
||||
save_mpie:
|
||||
STORE a0, 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)
|
||||
#ifndef __riscv_32e
|
||||
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)
|
||||
#endif
|
||||
/* restore to thread context
|
||||
* sp(0) -> epc;
|
||||
* sp(1) -> ra;
|
||||
* sp(i) -> x(i+2)
|
||||
*/
|
||||
LOAD sp, (a1)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mv a0, a2
|
||||
call rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
*
|
||||
* a0 --> context
|
||||
* a1 --> from
|
||||
* a2 --> to
|
||||
* a3 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
|
||||
STORE a0, 0(a1)
|
||||
|
||||
LOAD sp, 0(a2)
|
||||
move a0, a3
|
||||
call rt_cpus_lock_status_restore
|
||||
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
#endif
|
||||
|
||||
.global rt_hw_context_switch_exit
|
||||
rt_hw_context_switch_exit:
|
||||
#ifdef RT_USING_SMP
|
||||
#ifdef RT_USING_SIGNALS
|
||||
mv a0, sp
|
||||
|
||||
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__ */
|
||||
|
||||
call rt_signal_check
|
||||
mv sp, a0
|
||||
#endif
|
||||
#endif
|
||||
/* resw ra to mepc */
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
li t0, 0x7800
|
||||
#else
|
||||
li t0, 0x1800
|
||||
#endif
|
||||
csrw mstatus, t0
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, a0
|
||||
|
||||
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)
|
||||
#ifndef __riscv_32e
|
||||
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
|
||||
#else
|
||||
addi sp, sp, 16 * REGBYTES
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
FLOAD f0, 0 * FREGBYTES(sp)
|
||||
FLOAD f1, 1 * FREGBYTES(sp)
|
||||
FLOAD f2, 2 * FREGBYTES(sp)
|
||||
FLOAD f3, 3 * FREGBYTES(sp)
|
||||
FLOAD f4, 4 * FREGBYTES(sp)
|
||||
FLOAD f5, 5 * FREGBYTES(sp)
|
||||
FLOAD f6, 6 * FREGBYTES(sp)
|
||||
FLOAD f7, 7 * FREGBYTES(sp)
|
||||
FLOAD f8, 8 * FREGBYTES(sp)
|
||||
FLOAD f9, 9 * FREGBYTES(sp)
|
||||
FLOAD f10, 10 * FREGBYTES(sp)
|
||||
FLOAD f11, 11 * FREGBYTES(sp)
|
||||
FLOAD f12, 12 * FREGBYTES(sp)
|
||||
FLOAD f13, 13 * FREGBYTES(sp)
|
||||
FLOAD f14, 14 * FREGBYTES(sp)
|
||||
FLOAD f15, 15 * FREGBYTES(sp)
|
||||
FLOAD f16, 16 * FREGBYTES(sp)
|
||||
FLOAD f17, 17 * FREGBYTES(sp)
|
||||
FLOAD f18, 18 * FREGBYTES(sp)
|
||||
FLOAD f19, 19 * FREGBYTES(sp)
|
||||
FLOAD f20, 20 * FREGBYTES(sp)
|
||||
FLOAD f21, 21 * FREGBYTES(sp)
|
||||
FLOAD f22, 22 * FREGBYTES(sp)
|
||||
FLOAD f23, 23 * FREGBYTES(sp)
|
||||
FLOAD f24, 24 * FREGBYTES(sp)
|
||||
FLOAD f25, 25 * FREGBYTES(sp)
|
||||
FLOAD f26, 26 * FREGBYTES(sp)
|
||||
FLOAD f27, 27 * FREGBYTES(sp)
|
||||
FLOAD f28, 28 * FREGBYTES(sp)
|
||||
FLOAD f29, 29 * FREGBYTES(sp)
|
||||
FLOAD f30, 30 * FREGBYTES(sp)
|
||||
FLOAD f31, 31 * FREGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * FREGBYTES
|
||||
#endif
|
||||
|
||||
mret
|
||||
101
riscv/rtthread/libcpu/risc-v/common/cpuport.c
Executable file
101
riscv/rtthread/libcpu/risc-v/common/cpuport.c
Executable file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, 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.
|
||||
* 2020/11/20 BalanceTWK Add FPU support
|
||||
* 2023/01/04 WangShun Adapt to CH32
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
#include "rt_hw_stack_frame.h"
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
void *parameter,
|
||||
rt_uint8_t *stack_addr,
|
||||
void *texit)
|
||||
{
|
||||
struct rt_hw_stack_frame *frame;
|
||||
rt_uint8_t *stk;
|
||||
rt_size_t i;
|
||||
|
||||
stk = stack_addr + sizeof(rt_ubase_t);
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
|
||||
stk -= sizeof(struct rt_hw_stack_frame);
|
||||
|
||||
frame = (struct rt_hw_stack_frame *)stk;
|
||||
|
||||
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
|
||||
{
|
||||
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
frame->ra = (rt_ubase_t)texit;
|
||||
frame->a0 = (rt_ubase_t)parameter;
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
|
||||
/* force to machine mode(MPP=11) and set MPIE to 1 */
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
frame->mstatus = 0x7880;
|
||||
#else
|
||||
frame->mstatus = 0x1880;
|
||||
#endif
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
rt_weak void rt_trigger_software_interrupt(void)
|
||||
{
|
||||
while (0);
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_do_after_save_above(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*/
|
||||
#ifndef RT_USING_SMP
|
||||
rt_weak void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread)
|
||||
{
|
||||
(void)from_thread;
|
||||
(void)to_thread;
|
||||
if (rt_thread_switch_interrupt_flag == 0)
|
||||
rt_interrupt_from_thread = from;
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
|
||||
rt_trigger_software_interrupt();
|
||||
|
||||
return ;
|
||||
}
|
||||
#endif /* end of RT_USING_SMP */
|
||||
69
riscv/rtthread/libcpu/risc-v/common/cpuport.h
Executable file
69
riscv/rtthread/libcpu/risc-v/common/cpuport.h
Executable file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
* 2020/11/20 BalanceTWK Add FPU support
|
||||
* 2023/01/04 WangShun Adapt to CH32
|
||||
* 2023/08/11 HPMicro Define ARCH_RISCV_FPU if FPU is enabled
|
||||
*/
|
||||
|
||||
#ifndef CPUPORT_H__
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef RT_USING_SMP
|
||||
typedef union {
|
||||
unsigned long slock;
|
||||
struct __arch_tickets {
|
||||
unsigned short owner;
|
||||
unsigned short next;
|
||||
} tickets;
|
||||
} rt_hw_spinlock_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Preprocessor Definition */
|
||||
#if __riscv_flen == 32
|
||||
#define ARCH_RISCV_FPU
|
||||
#define ARCH_RISCV_FPU_S
|
||||
#endif
|
||||
|
||||
#if __riscv_flen == 64
|
||||
#define ARCH_RISCV_FPU
|
||||
#define ARCH_RISCV_FPU_D
|
||||
#endif
|
||||
|
||||
/* bytes of register width */
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
#define STORE sd
|
||||
#define LOAD ld
|
||||
#define REGBYTES 8
|
||||
#else
|
||||
#define STORE sw
|
||||
#define LOAD lw
|
||||
#define REGBYTES 4
|
||||
#endif
|
||||
|
||||
/* Preprocessor Definition */
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
#ifdef ARCH_RISCV_FPU_D
|
||||
#define FSTORE fsd
|
||||
#define FLOAD fld
|
||||
#define FREGBYTES 8
|
||||
#define rv_floatreg_t rt_int64_t
|
||||
#endif
|
||||
#ifdef ARCH_RISCV_FPU_S
|
||||
#define FSTORE fsw
|
||||
#define FLOAD flw
|
||||
#define FREGBYTES 4
|
||||
#define rv_floatreg_t rt_int32_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
354
riscv/rtthread/libcpu/risc-v/common/interrupt_gcc.S
Executable file
354
riscv/rtthread/libcpu/risc-v/common/interrupt_gcc.S
Executable file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023/01/17 WangShun The first version
|
||||
* 2023/03/19 Flyingcys Add riscv_32e support
|
||||
* 2023/08/09 HPMicro Fix the issue t0 was modified unexpectedly before being saved
|
||||
*/
|
||||
#define __ASSEMBLY__
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry, "ax"
|
||||
#if defined(SOC_SERIES_GD32VF103V)
|
||||
.align 6
|
||||
#else
|
||||
.align 2
|
||||
#endif
|
||||
.global SW_handler
|
||||
|
||||
SW_handler:
|
||||
csrci mstatus, 0x8
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
#endif
|
||||
/* save all from thread context */
|
||||
#ifndef __riscv_32e
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
#else
|
||||
addi sp, sp, -16 * REGBYTES
|
||||
#endif
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
/* Mandatory set the MPIE of mstatus */
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp)
|
||||
STORE x4, 4 * 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)
|
||||
#ifndef __riscv_32e
|
||||
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)
|
||||
#endif
|
||||
/* switch to interrupt stack */
|
||||
csrrw sp,mscratch,sp
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
/* Do the work after saving the above */
|
||||
jal rt_hw_do_after_save_above
|
||||
|
||||
call rt_interrupt_leave
|
||||
/* switch to from thread stack */
|
||||
csrrw sp,mscratch,sp
|
||||
|
||||
/* Determine whether to trigger scheduling at the interrupt function */
|
||||
la t0, rt_thread_switch_interrupt_flag
|
||||
lw t2, 0(t0)
|
||||
beqz t2, 1f
|
||||
/* clear the flag of rt_thread_switch_interrupt_flag */
|
||||
sw zero, 0(t0)
|
||||
|
||||
csrr a0, mepc
|
||||
STORE a0, 0 * REGBYTES(sp)
|
||||
|
||||
la t0, rt_interrupt_from_thread
|
||||
LOAD t1, 0(t0)
|
||||
STORE sp, 0(t1)
|
||||
|
||||
la t0, rt_interrupt_to_thread
|
||||
LOAD t1, 0(t0)
|
||||
LOAD sp, 0(t1)
|
||||
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
1:
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
/* Set the mode after MRET */
|
||||
li t0, 0x1800
|
||||
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)
|
||||
#ifndef __riscv_32e
|
||||
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
|
||||
#else
|
||||
addi sp, sp, 16 * REGBYTES
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
FLOAD f0, 0 * FREGBYTES(sp)
|
||||
FLOAD f1, 1 * FREGBYTES(sp)
|
||||
FLOAD f2, 2 * FREGBYTES(sp)
|
||||
FLOAD f3, 3 * FREGBYTES(sp)
|
||||
FLOAD f4, 4 * FREGBYTES(sp)
|
||||
FLOAD f5, 5 * FREGBYTES(sp)
|
||||
FLOAD f6, 6 * FREGBYTES(sp)
|
||||
FLOAD f7, 7 * FREGBYTES(sp)
|
||||
FLOAD f8, 8 * FREGBYTES(sp)
|
||||
FLOAD f9, 9 * FREGBYTES(sp)
|
||||
FLOAD f10, 10 * FREGBYTES(sp)
|
||||
FLOAD f11, 11 * FREGBYTES(sp)
|
||||
FLOAD f12, 12 * FREGBYTES(sp)
|
||||
FLOAD f13, 13 * FREGBYTES(sp)
|
||||
FLOAD f14, 14 * FREGBYTES(sp)
|
||||
FLOAD f15, 15 * FREGBYTES(sp)
|
||||
FLOAD f16, 16 * FREGBYTES(sp)
|
||||
FLOAD f17, 17 * FREGBYTES(sp)
|
||||
FLOAD f18, 18 * FREGBYTES(sp)
|
||||
FLOAD f19, 19 * FREGBYTES(sp)
|
||||
FLOAD f20, 20 * FREGBYTES(sp)
|
||||
FLOAD f21, 21 * FREGBYTES(sp)
|
||||
FLOAD f22, 22 * FREGBYTES(sp)
|
||||
FLOAD f23, 23 * FREGBYTES(sp)
|
||||
FLOAD f24, 24 * FREGBYTES(sp)
|
||||
FLOAD f25, 25 * FREGBYTES(sp)
|
||||
FLOAD f26, 26 * FREGBYTES(sp)
|
||||
FLOAD f27, 27 * FREGBYTES(sp)
|
||||
FLOAD f28, 28 * FREGBYTES(sp)
|
||||
FLOAD f29, 29 * FREGBYTES(sp)
|
||||
FLOAD f30, 30 * FREGBYTES(sp)
|
||||
FLOAD f31, 31 * FREGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * FREGBYTES
|
||||
#endif
|
||||
mret
|
||||
|
||||
|
||||
.section .text.trap_entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
|
||||
/* save thread context to thread stack */
|
||||
#ifndef __riscv_32e
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
#else
|
||||
addi sp, sp, -16 * REGBYTES
|
||||
#endif
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, mstatus
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, mepc
|
||||
STORE x1, 0 * 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)
|
||||
#ifndef __riscv_32e
|
||||
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)
|
||||
#endif
|
||||
|
||||
/* switch to interrupt stack */
|
||||
move s0, sp
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* 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__ */
|
||||
#endif
|
||||
|
||||
/* handle interrupt */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, s0
|
||||
call handle_trap
|
||||
call rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* s0 --> sp */
|
||||
mv sp, s0
|
||||
mv a0, s0
|
||||
call rt_scheduler_do_irq_switch
|
||||
tail rt_hw_context_switch_exit
|
||||
|
||||
#else
|
||||
|
||||
/* 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)
|
||||
|
||||
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)
|
||||
|
||||
#endif
|
||||
|
||||
spurious_interrupt:
|
||||
tail rt_hw_context_switch_exit
|
||||
41
riscv/rtthread/libcpu/risc-v/common/riscv-ops.h
Executable file
41
riscv/rtthread/libcpu/risc-v/common/riscv-ops.h
Executable file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
|
||||
#ifndef RISCV_OPS_H__
|
||||
#define RISCV_OPS_H__
|
||||
|
||||
#if defined(__GNUC__) && !defined(__ASSEMBLER__)
|
||||
|
||||
#define read_csr(reg) ({ unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; })
|
||||
|
||||
#define write_csr(reg, val) ({ \
|
||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
||||
|
||||
#define set_csr(reg, bit) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; })
|
||||
|
||||
#define clear_csr(reg, bit) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; })
|
||||
#endif /* end of __GNUC__ */
|
||||
|
||||
#endif
|
||||
113
riscv/rtthread/libcpu/risc-v/common/riscv-plic.h
Executable file
113
riscv/rtthread/libcpu/risc-v/common/riscv-plic.h
Executable file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
|
||||
#ifndef RISCV_PLIC_H__
|
||||
#define RISCV_PLIC_H__
|
||||
|
||||
#ifndef PLIC_BASE_ADDR
|
||||
#define PLIC_BASE_ADDR 0x0
|
||||
#endif
|
||||
|
||||
/* Priority Register - 32 bits per source */
|
||||
#define PLIC_PRIORITY_OFFSET (0x00000000UL)
|
||||
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
|
||||
|
||||
/* Pending Register - 1 bit per soirce */
|
||||
#define PLIC_PENDING_OFFSET (0x00001000UL)
|
||||
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
|
||||
|
||||
/* Enable Register - 0x80 per target */
|
||||
#define PLIC_ENABLE_OFFSET (0x00002000UL)
|
||||
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
|
||||
|
||||
/* Priority Threshold Register - 0x1000 per target */
|
||||
#define PLIC_THRESHOLD_OFFSET (0x00200000UL)
|
||||
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
|
||||
|
||||
/* Claim Register - 0x1000 per target */
|
||||
#define PLIC_CLAIM_OFFSET (0x00200004UL)
|
||||
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
|
||||
|
||||
#if defined(__GNUC__) && !defined(__ASSEMBLER__)
|
||||
__attribute__((always_inline)) static inline void __plic_set_feature(unsigned int feature)
|
||||
{
|
||||
volatile unsigned int *feature_ptr = (volatile unsigned int *)PLIC_BASE_ADDR;
|
||||
*feature_ptr = feature;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_set_threshold(unsigned int threshold)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *threshold_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_THRESHOLD_OFFSET +
|
||||
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
|
||||
*threshold_ptr = threshold;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_set_priority(unsigned int source, unsigned int priority)
|
||||
{
|
||||
volatile unsigned int *priority_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_PRIORITY_OFFSET +
|
||||
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
|
||||
*priority_ptr = priority;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_set_pending(unsigned int source)
|
||||
{
|
||||
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_PENDING_OFFSET +
|
||||
((source >> 5) << 2));
|
||||
*current_ptr = (1 << (source & 0x1F));
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_irq_enable(unsigned int source)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_ENABLE_OFFSET +
|
||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
||||
((source >> 5) << 2));
|
||||
unsigned int current = *current_ptr;
|
||||
current = current | (1 << (source & 0x1F));
|
||||
*current_ptr = current;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_irq_disable(unsigned int source)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_ENABLE_OFFSET +
|
||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
||||
((source >> 5) << 2));
|
||||
unsigned int current = *current_ptr;
|
||||
current = current & ~((1 << (source & 0x1F)));
|
||||
*current_ptr = current;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline unsigned int __plic_irq_claim(void)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_CLAIM_OFFSET +
|
||||
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
||||
return *claim_addr;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_irq_complete(unsigned int source)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_CLAIM_OFFSET +
|
||||
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
||||
*claim_addr = source;
|
||||
}
|
||||
#endif /* end of __GNUC__ */
|
||||
|
||||
#endif
|
||||
88
riscv/rtthread/libcpu/risc-v/common/rt_hw_stack_frame.h
Executable file
88
riscv/rtthread/libcpu/risc-v/common/rt_hw_stack_frame.h
Executable file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
#ifndef RISCV_STACKFRAME_H
|
||||
|
||||
#define RISCV_STACKFRAME_H
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
typedef struct rt_hw_stack_frame
|
||||
{
|
||||
rt_ubase_t epc; /* epc - epc - program counter */
|
||||
rt_ubase_t ra; /* x1 - ra - return address for jumps */
|
||||
rt_ubase_t mstatus; /* - machine status register */
|
||||
rt_ubase_t gp; /* x3 - gp - global pointer */
|
||||
rt_ubase_t tp; /* x4 - tp - thread pointer */
|
||||
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
|
||||
rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
|
||||
rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
|
||||
rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
|
||||
rt_ubase_t s1; /* x9 - s1 - saved register 1 */
|
||||
rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
|
||||
rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
|
||||
rt_ubase_t a2; /* x12 - a2 - function argument 2 */
|
||||
rt_ubase_t a3; /* x13 - a3 - function argument 3 */
|
||||
rt_ubase_t a4; /* x14 - a4 - function argument 4 */
|
||||
rt_ubase_t a5; /* x15 - a5 - function argument 5 */
|
||||
#ifndef __riscv_32e
|
||||
rt_ubase_t a6; /* x16 - a6 - function argument 6 */
|
||||
rt_ubase_t a7; /* x17 - a7 - function argument 7 */
|
||||
rt_ubase_t s2; /* x18 - s2 - saved register 2 */
|
||||
rt_ubase_t s3; /* x19 - s3 - saved register 3 */
|
||||
rt_ubase_t s4; /* x20 - s4 - saved register 4 */
|
||||
rt_ubase_t s5; /* x21 - s5 - saved register 5 */
|
||||
rt_ubase_t s6; /* x22 - s6 - saved register 6 */
|
||||
rt_ubase_t s7; /* x23 - s7 - saved register 7 */
|
||||
rt_ubase_t s8; /* x24 - s8 - saved register 8 */
|
||||
rt_ubase_t s9; /* x25 - s9 - saved register 9 */
|
||||
rt_ubase_t s10; /* x26 - s10 - saved register 10 */
|
||||
rt_ubase_t s11; /* x27 - s11 - saved register 11 */
|
||||
rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
|
||||
rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
|
||||
rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
|
||||
rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
|
||||
#endif
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
rv_floatreg_t f0; /* f0 */
|
||||
rv_floatreg_t f1; /* f1 */
|
||||
rv_floatreg_t f2; /* f2 */
|
||||
rv_floatreg_t f3; /* f3 */
|
||||
rv_floatreg_t f4; /* f4 */
|
||||
rv_floatreg_t f5; /* f5 */
|
||||
rv_floatreg_t f6; /* f6 */
|
||||
rv_floatreg_t f7; /* f7 */
|
||||
rv_floatreg_t f8; /* f8 */
|
||||
rv_floatreg_t f9; /* f9 */
|
||||
rv_floatreg_t f10; /* f10 */
|
||||
rv_floatreg_t f11; /* f11 */
|
||||
rv_floatreg_t f12; /* f12 */
|
||||
rv_floatreg_t f13; /* f13 */
|
||||
rv_floatreg_t f14; /* f14 */
|
||||
rv_floatreg_t f15; /* f15 */
|
||||
rv_floatreg_t f16; /* f16 */
|
||||
rv_floatreg_t f17; /* f17 */
|
||||
rv_floatreg_t f18; /* f18 */
|
||||
rv_floatreg_t f19; /* f19 */
|
||||
rv_floatreg_t f20; /* f20 */
|
||||
rv_floatreg_t f21; /* f21 */
|
||||
rv_floatreg_t f22; /* f22 */
|
||||
rv_floatreg_t f23; /* f23 */
|
||||
rv_floatreg_t f24; /* f24 */
|
||||
rv_floatreg_t f25; /* f25 */
|
||||
rv_floatreg_t f26; /* f26 */
|
||||
rv_floatreg_t f27; /* f27 */
|
||||
rv_floatreg_t f28; /* f28 */
|
||||
rv_floatreg_t f29; /* f29 */
|
||||
rv_floatreg_t f30; /* f30 */
|
||||
rv_floatreg_t f31; /* f31 */
|
||||
#endif
|
||||
}rt_hw_stack_frame_t;
|
||||
|
||||
#endif /* RISCV_STACKFRAME_H */
|
||||
112
riscv/rtthread/libcpu/risc-v/common/trap_common.c
Executable file
112
riscv/rtthread/libcpu/risc-v/common/trap_common.c
Executable file
@@ -0,0 +1,112 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "riscv-ops.h"
|
||||
#include "rt_hw_stack_frame.h"
|
||||
|
||||
#define ISR_NUMBER 32
|
||||
static volatile rt_hw_stack_frame_t *s_stack_frame;
|
||||
static struct rt_irq_desc rv32irq_table[ISR_NUMBER];
|
||||
void rt_show_stack_frame(void);
|
||||
|
||||
/**
|
||||
* Temporary interrupt entry function
|
||||
*
|
||||
* @param mcause Machine Cause Register
|
||||
* @return RT_NULL
|
||||
*/
|
||||
rt_weak rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t mcause)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", mcause);
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt entry function initialization
|
||||
*/
|
||||
rt_weak void rt_hw_interrupt_init(void)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
for (idx = 0; idx < ISR_NUMBER; idx++)
|
||||
{
|
||||
rv32irq_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
|
||||
rv32irq_table[idx].param = RT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Break Entry Function Binding
|
||||
*
|
||||
* @param vector interrupt number
|
||||
* @param handler Break-in function requiring binding
|
||||
* @param param NULL
|
||||
* @param name NULL
|
||||
* @return old handler
|
||||
*/
|
||||
rt_weak 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;
|
||||
(void)param;
|
||||
(void)name;
|
||||
|
||||
if(vector < ISR_NUMBER)
|
||||
{
|
||||
old_handler = rv32irq_table[vector].handler;
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
rv32irq_table[vector].handler = (rt_isr_handler_t)handler;
|
||||
rv32irq_table[vector].param = param;
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query and Distribution Entry for Exception and Interrupt Sources
|
||||
*
|
||||
* @param mcause Machine Cause Register
|
||||
*/
|
||||
rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause)
|
||||
{
|
||||
rt_uint32_t mscratch = read_csr(0x340);
|
||||
rt_uint32_t irq_id = (mcause & 0x1F);
|
||||
rt_uint32_t exception = !(mcause & 0x80000000);
|
||||
if(exception)
|
||||
{
|
||||
s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
|
||||
rt_show_stack_frame();
|
||||
}
|
||||
else
|
||||
{
|
||||
rv32irq_table[irq_id].handler(irq_id, rv32irq_table[irq_id].param);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Print on Exception
|
||||
*/
|
||||
rt_weak void rt_show_stack_frame(void)
|
||||
{
|
||||
rt_kprintf("Stack frame:\r\n----------------------------------------\r\n");
|
||||
rt_kprintf("ra : 0x%08x\r\n", s_stack_frame->ra);
|
||||
rt_kprintf("mstatus : 0x%08x\r\n", read_csr(0x300));//mstatus
|
||||
rt_kprintf("t0 : 0x%08x\r\n", s_stack_frame->t0);
|
||||
rt_kprintf("t1 : 0x%08x\r\n", s_stack_frame->t1);
|
||||
rt_kprintf("t2 : 0x%08x\r\n", s_stack_frame->t2);
|
||||
rt_kprintf("a0 : 0x%08x\r\n", s_stack_frame->a0);
|
||||
rt_kprintf("a1 : 0x%08x\r\n", s_stack_frame->a1);
|
||||
rt_kprintf("a2 : 0x%08x\r\n", s_stack_frame->a2);
|
||||
rt_kprintf("a3 : 0x%08x\r\n", s_stack_frame->a3);
|
||||
rt_kprintf("a4 : 0x%08x\r\n", s_stack_frame->a4);
|
||||
rt_kprintf("a5 : 0x%08x\r\n", s_stack_frame->a5);
|
||||
#ifndef __riscv_32e
|
||||
rt_kprintf("a6 : 0x%08x\r\n", s_stack_frame->a6);
|
||||
rt_kprintf("a7 : 0x%08x\r\n", s_stack_frame->a7);
|
||||
rt_kprintf("t3 : 0x%08x\r\n", s_stack_frame->t3);
|
||||
rt_kprintf("t4 : 0x%08x\r\n", s_stack_frame->t4);
|
||||
rt_kprintf("t5 : 0x%08x\r\n", s_stack_frame->t5);
|
||||
rt_kprintf("t6 : 0x%08x\r\n", s_stack_frame->t6);
|
||||
#endif
|
||||
}
|
||||
187
riscv/rtthread/libcpu/risc-v/readme.md
Executable file
187
riscv/rtthread/libcpu/risc-v/readme.md
Executable file
@@ -0,0 +1,187 @@
|
||||
### RV32移植指南
|
||||
|
||||
#### 1.概述
|
||||
|
||||
为了简化32位RISC-V架构内核移植RT-Thread的流程,RT-Thread提供一分通用代码于common文件夹
|
||||
|
||||
| 文件名 | 文件内容 |
|
||||
| :-----------------: | :----------------------------: |
|
||||
| context_gcc.S | 开关全局中断,线程上下文切换等 |
|
||||
| cpuport.c | 线程栈初始化,软件中断触发等 |
|
||||
| cpuport.h | 数据加载写入指令 |
|
||||
| interrupt_gcc.S | 线程间上下文切换 |
|
||||
| riscv-ops.h | 控制状态寄存器读写 |
|
||||
| rt_hw_stack_frame.h | 线程栈格式 |
|
||||
| trap_common.c | 中断注册,中断查询分发 |
|
||||
|
||||
#### 2.移植接口
|
||||
|
||||
(1)软件中断触发函数,通常向量管理中断方式需实现该函数,非向量中断管理方式一般不需要
|
||||
|
||||
```c
|
||||
void rt_trigger_software_interrupt(void)
|
||||
```
|
||||
|
||||
(2)保存上文后执行函数,该函数向量中断与非向量中断均需实现
|
||||
|
||||
```c
|
||||
void rt_hw_do_after_save_above(void)
|
||||
```
|
||||
|
||||
该函数需要实现的工作如下:
|
||||
|
||||
步骤1:将函数返回地址(ra)保存栈中
|
||||
|
||||
步骤2:加载中断处理函数的入口参数
|
||||
|
||||
步骤3:调用中断处理函数(新移植的BSP推荐使用RT-Thread common_trap.c文件中提供的统一中断处理函数:rt_rv32_system_irq_handler)
|
||||
|
||||
步骤4:从栈中加载返回地址(ra),返回至SW_handler函数
|
||||
|
||||
#### 3.准备工作
|
||||
|
||||
- 准备一个基础的裸机工程,需具备以下条件:
|
||||
|
||||
- 明确中断管理方式(向量中断/非向量中断)
|
||||
|
||||
- 实现系统节拍定时器中断
|
||||
- 实现一个串口中断
|
||||
|
||||
#### 4.移植步骤
|
||||
|
||||
- 步骤一:配置中断管理入口,相关中断入口函数位于**common/interrupt_gcc.S**,入口函数为**SW_handler**
|
||||
|
||||
- 根据使用的中断管理方式,执行下述操作
|
||||
|
||||
- 向量中断管理方式
|
||||
|
||||
> 通常会使用一个软件中断(该中断的优先级被配置为最低)作为在中断中触发上下文切换的入口函数。SW_handler在此仅作为触发软件中断时的入口参数,其他类型中断触发时跳转至各自的中断入口函数。
|
||||
>
|
||||
|
||||
移植方法:修改原有的中断向量表中软件中断所在位置,将原有软件中断函数名修改为**SW_handler**
|
||||
|
||||
示例(ch32系列):
|
||||
|
||||
```assembly
|
||||
_vector_base:
|
||||
.option norvc;
|
||||
.word _start
|
||||
...
|
||||
.word SW_handler /* 将这里原来放置的软件中断函数名修改为SW_handler */
|
||||
```
|
||||
|
||||
- 非向量中断
|
||||
|
||||
> 当有中断触发时,会进入一个统一的中断入口函数进行中断查询分发。SW_handler在此处不仅作为作为在中断中触发上下文切换的入口函数,同时承担中断查询分发与执行。
|
||||
>
|
||||
|
||||
移植方法:将**SW_handler**的地址加载到保存统一中断入口地址的寄存器(通常为mtevc,具体名称需要根据具体的内核指定)
|
||||
|
||||
示例(hpm6750系列):
|
||||
|
||||
```assembly
|
||||
la t0, SW_handler
|
||||
csrw mtvec, t0
|
||||
```
|
||||
|
||||
- 步骤二:修改链接脚本,在中断栈顶名称后添加示例代码
|
||||
|
||||
- 将下述代码放置于链接脚本中中断栈顶名称之后
|
||||
|
||||
```assembly
|
||||
PROVIDE( __rt_rvstack = . );
|
||||
```
|
||||
|
||||
- 示例(core-v-mcu链接脚本):
|
||||
|
||||
```assembly
|
||||
.stack : ALIGN(16)
|
||||
{
|
||||
stack_start = .;
|
||||
__stack_bottom = .;
|
||||
. += __stack_size;
|
||||
__stack_top = .;
|
||||
PROVIDE( __rt_rvstack = . );//移植时添加
|
||||
stack = .;
|
||||
} > L2
|
||||
```
|
||||
|
||||
> __stack_top为core-v-mcu工程的中断栈顶名 不同工程此处的名称可能不一致 按上述方法将给出的代码放到具体工程链接脚本中断栈顶名称之后即可。
|
||||
|
||||
- 步骤三:实现在中断上下文切换的函数接口
|
||||
|
||||
<font color=red>RISC-V架构的内核通常采用非向量中断的管理方式,为了进一步降低难度,针对非向量模式的中断管理方式,common文件夹中的trap_common.c为用户提供了一套统一的中断查询分发、中断入口函数注册以及中断初始化函数,在rthw.h中声明,对于移植一个新的RV32内核,若采用非向量中断管理的方式,推荐使用方式一,若采用向量中断管理方式或针对中断的处理有专门的优化时推荐使用方式二,期望采用原有裸机工程的统一的中断查询与处理函数也可使用方式二。以下是两种实现方式的示例:</font>
|
||||
|
||||
方式一:面向非向量中断管理方式(例:core-v-mcu)
|
||||
|
||||
在RT-Thread的BSP框架中的board文件夹创建一个统一名称的汇编文件:trap_gcc.S,将该文件添加到编译环境即可,该函数的实现如下(用户直接使用,无需修改):
|
||||
|
||||
```assembly
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call rt_rv32_system_irq_handler
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
```
|
||||
|
||||
随后用户仅需调用rt_hw_interrupt_init进行初始化,再将中断入口函数通过rt_hw_interrupt_install函数注册即可,注册的中断入口函数为裸机原有的中断入口函数,示例代码如下(相关设备的中断入口函数注册之前不可使用该设备):
|
||||
|
||||
```c
|
||||
rt_hw_interrupt_init();//中断入口函数初始化
|
||||
rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");//注册系统定时器中断入口函数
|
||||
rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");//注册外部中断入口函数
|
||||
```
|
||||
|
||||
方式二:面向向量中断管理方式(例:CH32)与针对中断管理有专门优化的内核(例:GD32)
|
||||
|
||||
- 向量中断(可参考ch32)
|
||||
|
||||
在RT-Thread的BSP框架中的board文件夹创建需要的文件,实现下述的两个函数:
|
||||
|
||||
- 在void rt_trigger_software_interrupt(void) 中实现触发软件中断的操作
|
||||
|
||||
- 在void rt_hw_do_after_save_above(void) 中实现触发软件中断之后的工作,通常是清除软件中断置位标志位或类似操作
|
||||
|
||||
- 非向量中断(期望采用原有裸机工程的统一的中断查询与处理函数)
|
||||
|
||||
在RT-Thread的BSP框架中的board文件夹创建一个统一名称的汇编文件:trap_gcc.S,将该文件添加到编译环境即可,此步骤与方式一提供的方法相似,仅在调用中断处理函数以及传递的参数不同,需要根据具体的移植工程实现,方式二下该函数的实现如下:
|
||||
|
||||
示例代码:
|
||||
|
||||
```assembly
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4 // 移动栈指针
|
||||
STORE ra, 0 * REGBYTES(sp) // 将返回地址寄存器值保存至栈中
|
||||
|
||||
csrr a0, mscratch// 加载函数入口参数
|
||||
call trap_entry// 调用中断处理函数
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp) // 从栈中恢复返回地址寄存器值
|
||||
addi sp, sp, 4// 移动栈指针
|
||||
ret // 返回SW_handler
|
||||
```
|
||||
|
||||
trap_entry为用户实现的中断源查询分发的函数,在移植时仅需要将该函数名修改为用户的中断查询分发函数即可。
|
||||
|
||||
|
||||
|
||||
#### 5.验证
|
||||
|
||||
- 创建一个静态线程,在线程中调用RT-Thread提供的与系统时基相关函数接口,例如rt_thread_mdelay,调试观察系统是否可以正常运行
|
||||
- 移植RT-Thread的shell进一步验证系统是否移植成功
|
||||
|
||||
Reference in New Issue
Block a user