Browse Source

[libcpu] Add unified RISC-V libcpu porting.

Bernard Xiong 6 years ago
parent
commit
2a7d814f77

+ 81 - 1
bsp/rv32m1_vega/README.md

@@ -1 +1,81 @@
-# RT-Thread BSP for RV32M1 VEGA board
+# RV32M1_VEGA 板级支持包
+
+## 1. 简介
+
+RV32M1_VEGA开发板是一款多核异构的RISC-V 32开发板,包含了两个RISC-V 32位核心,同时也包括了BLE外设。
+
+| 硬件 | 描述 |
+| -- | -- |
+|芯片型号| RV32M1 |
+|CPU| RV32IMC, with extensons for post-incrementing load and stores, |
+| | multiply-accumulate extensions, ALU extensions, hardware loops. |
+| | RV32IEMC |
+|主频| 48MHz或72MHz |
+| | 48MHz或72MHz |
+|片内SRAM| 256kB + 128kB |
+|片内Flash| 1MB + 256kB |
+
+## 2. 编译说明
+
+当前测试的工具链是以标准的GNU GCC 7.2.0 & newlib 2.5.0方式,并以标准的RV32IMC构架进行编译,所以RV32M1的扩展指令未支持,RT-Thread ENV版本是1.0。
+
+Windows上编译推荐使用[env工具][1],可以在console下进入到`bsp/rv32m1_vega/ri5cy`目录中,运行以下命令:
+
+    scons
+
+来编译这个板级支持包。如果编译正确无误,会产生rtthread.elf、rtthread.bin文件。其中rtthread.bin需要烧写到设备中进行运行。
+
+## 3. 烧写及执行
+
+请使用JLink接入到RV32M1_VEGA开发板的RISC-V核的JTAG接口上,同时把JLink在PC上的驱动更改为WinUSB模式。JTAG接口位于RV32M1芯片和天线座子旁边,小的20pin JTAG接口。
+
+使用USB线连接到标记了SDA的USB口上,在PC上会出现一个串口设备,可以使用115200-N-8-1的配置方式打开这个串口。设备使用的串口引脚是:`[PTC7/PTC8]`
+
+当正确编译产生出rtthread.bin映像文件后,可以使用gdb连接到openocd,并以`load`命令烧写到flash中。
+
+关于更多使用JTAG,使用gdb调试RV32M1_VEGA开发板的情况,建议参考开发板的[开发环境搭建](https://github.com/open-isa-org/open-isa.org/blob/master/RV32M1_Vega_Develop_Environment_Setup.pdf)的文档。
+
+### 3.1 运行结果
+
+如果编译 & 烧写无误,当按`SW1`复位按钮复位设备后,会在串口上看到RT-Thread的启动logo信息:
+
+``` text
+ \ | /
+- RT -     Thread Operating System
+ / | \     4.0.0 build Dec  5 2018
+ 2006 - 2018 Copyright by rt-thread team
+File System initialized!
+Hello RT-Thread!
+msh />
+```
+
+## 4. 驱动支持情况及计划
+
+| 驱动 | 支持情况  |  备注  |
+| ------ | ----  | :------  |
+| UART | 支持 | UART0, RX(PTC7), TX(PTC8) |
+|  | 未支持 | UART1, RX(PTA25), TX(PTA26) |
+| clock | 支持 |  |
+| GPIO | 支持(列表可能不完善,同时也需要按照使用到的IO调整pinmux、clock) |  |
+| MMC/SD | 支持 |  |
+
+### 4.1 IO在板级支持包中的映射情况
+
+| IO号 | 板级代码中的定义 |
+| -- | -- |
+| PTA22 | LED_BLUE |
+| PTA23 | LED_GREEN |
+| PTA24 | LED_RED |
+| PTA24 | LED_STS |
+| PTE8 | BTN_SW3 |
+| PTE9 | BTN_SW4 |
+| PTE12 | BTN_SW5 |
+| PTA0 | BTN_SW2/BTN_NMI |
+
+## 5. 参考
+
+* [开发板用户手册](https://github.com/open-isa-org/open-isa.org/blob/master/RV32M1_VEGA_Board_User_Guide.pdf)
+* 芯片[数据手册](https://github.com/open-isa-org/open-isa.org/blob/master/Reference%20Manual%20and%20Data%20Sheet/RV32M1DS_Rev.1.1.pdf)
+* [open-isa链接](https://github.com/open-isa-org/open-isa.org)
+
+  [1]: https://www.rt-thread.org/page/download.html

+ 14 - 7
libcpu/SConscript

@@ -2,30 +2,37 @@ Import('RTT_ROOT')
 Import('rtconfig')
 from building import *
 
+arch = rtconfig.ARCH
 comm = rtconfig.ARCH + '/common'
 path = rtconfig.ARCH + '/' + rtconfig.CPU
+src  = []
 ASFLAGS = ''
 
 # The set of source files associated with this SConscript file.
 if rtconfig.PLATFORM == 'armcc':
-	src = Glob(path + '/*.c') + Glob(path + '/*_rvds.S') + Glob(comm + '/*.c')
+    src += Glob(path + '/*.c') + Glob(path + '/*_rvds.S') 
+    src += Glob(comm + '/*.c') + Glob(comm + '/*_rvds.S')
 
 if rtconfig.PLATFORM == 'gcc':
-	src = Glob(path + '/*.c') + Glob(path + '/*_gcc.S') + Glob(comm + '/*.c') + Glob(path + '/*_init.S')
+    src += Glob(path + '/*_init.S')
+    src += Glob(path + '/*.c') + Glob(path + '/*_gcc.S') 
+    src += Glob(comm + '/*.c') + Glob(comm + '/*_gcc.S')
 
 if rtconfig.PLATFORM == 'iar':
-	src = Glob(path + '/*.c') + Glob(path + '/*_iar.S') + Glob(comm + '/*.c')
+    src += Glob(path + '/*.c') + Glob(path + '/*_iar.S')
+    src += Glob(comm + '/*.c') + Glob(comm + '/*_iar.S')
 
 if rtconfig.PLATFORM == 'cl':
-	src = Glob(path + '/*.c')
+    src = Glob(path + '/*.c')
 
 if rtconfig.PLATFORM == 'mingw':
-	src = Glob(path + '/*.c')
+    src = Glob(path + '/*.c')
 
 if rtconfig.PLATFORM == 'armcc' and rtconfig.ARCH == 'arm' and rtconfig.CPU == 'arm926':
     ASFLAGS = ' --cpreproc'
-    
-CPPPATH = [RTT_ROOT + '/libcpu/' + rtconfig.ARCH + '/' + rtconfig.CPU, RTT_ROOT + '/libcpu/' + rtconfig.ARCH + '/common']
+
+CPPPATH = [RTT_ROOT + '/libcpu/' + arch + '/' + rtconfig.CPU, RTT_ROOT + '/libcpu/' + arch + '/common']
+
 group = DefineGroup(rtconfig.CPU.upper(), src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
 
 Return('group')

+ 180 - 0
libcpu/risc-v/common/context_gcc.S

@@ -0,0 +1,180 @@
+/*
+ * 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
+ */
+
+#include "cpuport.h"
+
+/*
+ * 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
+
+/*
+ * void rt_hw_context_switch_to(rt_ubase_t to)
+ * a0 --> to
+ */
+    .globl rt_hw_context_switch_to
+rt_hw_context_switch_to:
+    LOAD sp, (a0)
+
+    /* load epc from stack */
+    LOAD a0,   0 * REGBYTES(sp)
+    csrw mepc, a0
+    LOAD x1,   1 * REGBYTES(sp)
+    /* load mstatus from stack */
+    LOAD a0,   2 * REGBYTES(sp)
+    csrw 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)
+    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
+
+/*
+ * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to)
+ * a0 --> from
+ * a1 --> to
+ */
+    .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)
+     */
+    addi  sp,  sp, -32 * REGBYTES
+    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)
+    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)
+
+    /* restore to thread context
+     * sp(0) -> epc;
+     * sp(1) -> ra;
+     * sp(i) -> x(i+2)
+     */
+    LOAD sp,  (a1)
+
+    /* resw ra to mepc */
+    LOAD a1,   0 * REGBYTES(sp)
+    csrw mepc, a1
+    LOAD x1,   1 * REGBYTES(sp)
+
+    /* force to machin mode(MPP=11) */
+    li a1, 0x00001800;
+    csrs mstatus, a1
+    LOAD a1,   2 * REGBYTES(sp)
+    csrs mstatus, a1
+
+    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

+ 105 - 0
libcpu/risc-v/common/cpuport.c

@@ -0,0 +1,105 @@
+/*
+ * 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 "cpuport.h"
+
+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;
+
+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                 */
+    rt_ubase_t a6;         /* x16 - a6     - function argument 6                 */
+    rt_ubase_t a7;         /* x17 - s7     - 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                */
+};
+
+/**
+ * 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;
+    int                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 */
+    frame->mstatus = 0x00007880;
+
+    return stk;
+}
+
+void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
+{
+    if (rt_thread_switch_interrupt_flag == 0)
+        rt_interrupt_from_thread = from;
+
+    rt_interrupt_to_thread = to;
+    rt_thread_switch_interrupt_flag = 1;
+
+    return ;
+}

+ 27 - 0
libcpu/risc-v/common/cpuport.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-10-03     Bernard      The first version
+ */
+
+#ifndef CPUPORT_H__
+#define CPUPORT_H__
+
+#include <rtconfig.h>
+
+/* 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
+
+#endif

+ 41 - 0
libcpu/risc-v/common/riscv-ops.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006-2018, 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 - 0
libcpu/risc-v/common/riscv-plic.h

@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2006-2018, 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

+ 1 - 1
src/irq.c

@@ -52,7 +52,7 @@ void rt_interrupt_leave_sethook(void (*hook)(void))
 #ifdef RT_USING_SMP
 #define rt_interrupt_nest rt_cpu_self()->irq_nest
 #else
-volatile rt_uint8_t rt_interrupt_nest;
+volatile rt_uint8_t rt_interrupt_nest = 0;
 #endif
 
 /**