mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-11-09 20:45:41 +08:00
Merge pull request #4711 from bigmagic123/rv64
Rv64 qemu virt Support M-Mode
This commit is contained in:
30 files changed
+1303
-472
No files matched your search
@@ -213,6 +213,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
|
||||
# CONFIG_RT_USING_RYM is not set
|
||||
# CONFIG_RT_USING_ULOG is not set
|
||||
# CONFIG_RT_USING_UTEST is not set
|
||||
# CONFIG_RT_USING_RT_LINK is not set
|
||||
|
||||
#
|
||||
# RT-Thread Utestcases
|
||||
@@ -335,6 +336,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
|
||||
# CONFIG_PKG_USING_HELIX is not set
|
||||
# CONFIG_PKG_USING_AZUREGUIX is not set
|
||||
# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
|
||||
# CONFIG_PKG_USING_NUEMWIN is not set
|
||||
|
||||
#
|
||||
# tools packages
|
||||
@@ -492,6 +494,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
|
||||
# CONFIG_PKG_USING_LIBNFC is not set
|
||||
# CONFIG_PKG_USING_MFOC is not set
|
||||
# CONFIG_PKG_USING_TMC51XX is not set
|
||||
# CONFIG_PKG_USING_TCA9534 is not set
|
||||
|
||||
#
|
||||
# AI packages
|
||||
@@ -519,6 +522,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
|
||||
# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
|
||||
# CONFIG_PKG_USING_CANFESTIVAL is not set
|
||||
# CONFIG_PKG_USING_ZLIB is not set
|
||||
# CONFIG_PKG_USING_MINIZIP is not set
|
||||
# CONFIG_PKG_USING_DSTR is not set
|
||||
# CONFIG_PKG_USING_TINYFRAME is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
|
||||
@@ -558,7 +562,8 @@ CONFIG_BOARD_virt=y
|
||||
CONFIG_RT_USING_USERSPACE=y
|
||||
|
||||
#
|
||||
# General Purpose UARTs
|
||||
# RISCV qemu virt64 configs
|
||||
#
|
||||
# CONFIG_BSP_USING_UART1 is not set
|
||||
# CONFIG_RISCV_S_MODE is not set
|
||||
CONFIG___STACKSIZE__=16384
|
||||
@@ -0,0 +1,136 @@
|
||||
# QEMU/RISCV64 VIRT板级支持包说明
|
||||
|
||||
## 1. 简介
|
||||
|
||||
RISC-V是一种开放和免费的指令集体系结构(ISA)。本工程是在QEMU的RISCV64 VIRT版本上进行的一份移植。
|
||||
|
||||
## 2. 编译说明
|
||||
|
||||
首先可以下载交叉编译工具链,建议采用sifive的工具链进行编译。
|
||||
```
|
||||
https://www.sifive.com/software
|
||||
```
|
||||
选择对应的平台即可。
|
||||
|
||||
这里推荐在Ubuntu上进行开发工作。
|
||||
|
||||
解压工具链到指定的目录。
|
||||
|
||||
```
|
||||
export RTT_EXEC_PATH=~/gcc/bin
|
||||
```
|
||||
|
||||
进入到`rt-thread/bsp/qemu-riscv-virt64`目录进行输入
|
||||
```
|
||||
scons
|
||||
```
|
||||
可以看到正常生成`rtthread.elf`与`rtthread.bin`文件。
|
||||
|
||||
## 3. 执行
|
||||
|
||||
本工程提供了riscv64的两种可配置运行模式,默认运行在M-Mode下。
|
||||
|
||||
*M-Mode*
|
||||
|
||||
首先安装`qemu-system-riscv64`。
|
||||
|
||||
```
|
||||
sudo apt install qemu-system-misc
|
||||
```
|
||||
直接输入
|
||||
```
|
||||
./qemu-nographic.sh
|
||||
```
|
||||
可以看到程序运行
|
||||
|
||||
```
|
||||
heap: [0x80035804 - 0x86435804]
|
||||
|
||||
\ | /
|
||||
- RT - Thread Operating System
|
||||
/ | \ 4.0.4 build May 21 2021
|
||||
2006 - 2021 Copyright by rt-thread team
|
||||
Hello RISC-V!
|
||||
msh />
|
||||
```
|
||||
|
||||
*S-Mode*
|
||||
|
||||
如果运行在S-Mode下,那么需要通过menuconfig选择配置
|
||||
|
||||
```
|
||||
scons --menuconfig
|
||||
```
|
||||
选择如下:
|
||||
```
|
||||
RISCV qemu virt64 configs --->
|
||||
[*] RT-Thread run in riscv smode
|
||||
```
|
||||
保存后,重新`scons`编译即可。
|
||||
|
||||
要让rt-thread运行在S-Mode,首先需要启动opensbi,然后通过opensbi启动rt-thread。
|
||||
|
||||
自行编译的qemu或者下载的高版本的qemu内置opensbi,执行`./qemu-nographic-smode.sh`即可正常运行。
|
||||
|
||||
通过`sudo apt install qemu-system-misc`安装的qemu版本较低,可自行编译opensbi。
|
||||
|
||||
```
|
||||
git clone git@github.com:riscv/opensbi.git
|
||||
cd opensbi
|
||||
make PLATFORM=generic CROSS_COMPILE=~/gcc/bin/riscv64-unknown-elf-
|
||||
```
|
||||
最后生成的`/build/platform/generic/firmware/fw_jump.elf`则是需要的文件。
|
||||
|
||||
输入以下的命令即可运行:
|
||||
|
||||
```
|
||||
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -bios ~/opensbi/build/platform/generic/firmware/fw_jump.elf
|
||||
```
|
||||
可以看到如下的结果
|
||||
```
|
||||
OpenSBI v0.9
|
||||
____ _____ ____ _____
|
||||
/ __ \ / ____| _ \_ _|
|
||||
| | | |_ __ ___ _ __ | (___ | |_) || |
|
||||
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
|
||||
| |__| | |_) | __/ | | |____) | |_) || |_
|
||||
\____/| .__/ \___|_| |_|_____/|____/_____|
|
||||
| |
|
||||
|_|
|
||||
|
||||
Platform Name : riscv-virtio,qemu
|
||||
Platform Features : timer,mfdeleg
|
||||
.
|
||||
.
|
||||
.
|
||||
Boot HART ISA : rv64imafdcsu
|
||||
Boot HART Features : scounteren,mcounteren
|
||||
Boot HART PMP Count : 16
|
||||
Boot HART PMP Granularity : 4
|
||||
Boot HART PMP Address Bits: 54
|
||||
Boot HART MHPM Count : 0
|
||||
Boot HART MHPM Count : 0
|
||||
Boot HART MIDELEG : 0x0000000000000222
|
||||
Boot HART MEDELEG : 0x000000000000b109
|
||||
heap: [0x80235a58 - 0x86635a58]
|
||||
|
||||
\ | /
|
||||
- RT - Thread Operating System
|
||||
/ | \ 4.0.4 build May 21 2021
|
||||
2006 - 2021 Copyright by rt-thread team
|
||||
Hello RISC-V!
|
||||
msh />
|
||||
```
|
||||
## 4. 支持情况
|
||||
|
||||
| 驱动 | 支持情况 | 备注 |
|
||||
| ------ | ---- | :------: |
|
||||
| UART | 支持 | UART0 |
|
||||
| PLIC | 支持 | - |
|
||||
| CLIC | 支持 | - |
|
||||
|
||||
## 5. 联系人信息
|
||||
|
||||
维护人:[bernard][1]
|
||||
|
||||
[1]: https://github.com/BernardXiong
|
||||
@@ -31,7 +31,11 @@ stack_size = 4096
|
||||
|
||||
stack_lds = open('link_stacksize.lds', 'w')
|
||||
if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__')
|
||||
stack_lds.write('__STACKSIZE__ = %d;' % stack_size)
|
||||
stack_lds.write('__STACKSIZE__ = %d;\r\n' % stack_size)
|
||||
if GetDepend('RISCV_S_MODE'): start_addr = int(0x80200000)
|
||||
else: start_addr = int(0x80000000)
|
||||
stack_lds.write('__START_ADDR__ = 0x%x;' % start_addr)
|
||||
|
||||
stack_lds.close()
|
||||
|
||||
# make a building
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
@@ -14,9 +15,7 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void rt_hw_uart_start_rx_thread();
|
||||
rt_hw_uart_start_rx_thread();
|
||||
printf("Hello RISC-V\n");
|
||||
printf("Hello RISC-V!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
menu "General Purpose UARTs"
|
||||
menu "RISCV qemu virt64 configs"
|
||||
|
||||
menuconfig BSP_USING_UART1
|
||||
bool "Enable UART1"
|
||||
@@ -14,5 +14,8 @@ menuconfig BSP_USING_UART1
|
||||
default 21
|
||||
endif
|
||||
|
||||
endmenu
|
||||
config RISCV_S_MODE
|
||||
bool "RT-Thread run in riscv smode"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "sbi.h"
|
||||
#include "riscv.h"
|
||||
#include "stack.h"
|
||||
#include "riscv_io.h"
|
||||
#include "plic.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
void primary_cpu_entry(void)
|
||||
{
|
||||
@@ -33,11 +36,6 @@ void primary_cpu_entry(void)
|
||||
entry();
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_init()
|
||||
{
|
||||
/* Enable machine external interrupts. */
|
||||
set_csr(sie, SIP_SEIP);
|
||||
}
|
||||
|
||||
void rt_hw_board_init(void)
|
||||
{
|
||||
@@ -46,10 +44,7 @@ void rt_hw_board_init(void)
|
||||
/* initialize hardware interrupt */
|
||||
rt_hw_uart_init();
|
||||
|
||||
rt_hw_tick_init();
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t) RT_HW_HEAP_BEGIN, (rt_ubase_t) RT_HW_HEAP_END);
|
||||
/* initialize memory system */
|
||||
rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
|
||||
#endif
|
||||
@@ -58,6 +53,8 @@ void rt_hw_board_init(void)
|
||||
/* set console device */
|
||||
rt_console_set_device("uart");
|
||||
#endif /* RT_USING_CONSOLE */
|
||||
rt_hw_tick_init();
|
||||
rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t) RT_HW_HEAP_BEGIN, (rt_ubase_t) RT_HW_HEAP_END);
|
||||
|
||||
#ifdef RT_USING_COMPONENTS_INIT
|
||||
rt_components_board_init();
|
||||
@@ -71,137 +68,3 @@ void rt_hw_cpu_reset(void)
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine);
|
||||
|
||||
void dump_regs(struct rt_hw_stack_frame *regs)
|
||||
{
|
||||
rt_kprintf("--------------Dump Registers-----------------\n");
|
||||
|
||||
rt_kprintf("Function Registers:\n");
|
||||
rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n",regs -> ra,regs -> user_sp_exc_stack);
|
||||
rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n",regs -> gp,regs -> tp);
|
||||
rt_kprintf("Temporary Registers:\n");
|
||||
rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n",regs -> t0,regs -> t1);
|
||||
rt_kprintf("\tt2(x7) = 0x%p\n",regs -> t2);
|
||||
rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n",regs -> t3,regs -> t4);
|
||||
rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n",regs -> t5,regs -> t6);
|
||||
rt_kprintf("Saved Registers:\n");
|
||||
rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n",regs -> s0_fp,regs -> s1);
|
||||
rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n",regs -> s2,regs -> s3);
|
||||
rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n",regs -> s4,regs -> s5);
|
||||
rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n",regs -> s6,regs -> s7);
|
||||
rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n",regs -> s8,regs -> s9);
|
||||
rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n",regs -> s10,regs -> s11);
|
||||
rt_kprintf("Function Arguments Registers:\n");
|
||||
rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n",regs -> a0,regs -> a1);
|
||||
rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n",regs -> a2,regs -> a3);
|
||||
rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n",regs -> a4,regs -> a5);
|
||||
rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n",regs -> a6,regs -> a7);
|
||||
rt_kprintf("sstatus = 0x%p\n",regs -> sstatus);
|
||||
rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
|
||||
rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
|
||||
rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
|
||||
rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
|
||||
rt_kprintf("\t%s\n",(regs -> sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
|
||||
rt_size_t satp_v = read_csr(satp);
|
||||
rt_kprintf("satp = 0x%p\n",satp_v);
|
||||
const char *mode_str = "Unknown Address Translation/Protection Mode";
|
||||
|
||||
switch(__MASKVALUE(satp_v >> 60,__MASK(4)))
|
||||
{
|
||||
case 0:
|
||||
mode_str = "No Address Translation/Protection Mode";
|
||||
break;
|
||||
|
||||
case 8:
|
||||
mode_str = "Page-based 39-bit Virtual Addressing Mode";
|
||||
break;
|
||||
|
||||
case 9:
|
||||
mode_str = "Page-based 48-bit Virtual Addressing Mode";
|
||||
break;
|
||||
}
|
||||
|
||||
rt_kprintf("\tMode = %s\n",mode_str);
|
||||
rt_kprintf("-----------------Dump OK---------------------\n");
|
||||
}
|
||||
|
||||
static const char *Exception_Name[] =
|
||||
{
|
||||
"Instruction Address Misaligned",
|
||||
"Instruction Access Fault",
|
||||
"Illegal Instruction",
|
||||
"Breakpoint",
|
||||
"Load Address Misaligned",
|
||||
"Load Access Fault",
|
||||
"Store/AMO Address Misaligned",
|
||||
"Store/AMO Access Fault",
|
||||
"Environment call from U-mode",
|
||||
"Environment call from S-mode",
|
||||
"Reserved-10",
|
||||
"Reserved-11",
|
||||
"Instruction Page Fault",
|
||||
"Load Page Fault",
|
||||
"Reserved-14",
|
||||
"Store/AMO Page Fault"
|
||||
};
|
||||
|
||||
static const char *Interrupt_Name[] =
|
||||
{
|
||||
"User Software Interrupt",
|
||||
"Supervisor Software Interrupt",
|
||||
"Reversed-2",
|
||||
"Reversed-3",
|
||||
"User Timer Interrupt",
|
||||
"Supervisor Timer Interrupt",
|
||||
"Reversed-6",
|
||||
"Reversed-7",
|
||||
"User External Interrupt",
|
||||
"Supervisor External Interrupt",
|
||||
"Reserved-10",
|
||||
"Reserved-11",
|
||||
};
|
||||
|
||||
void handle_trap(rt_size_t scause,rt_size_t stval,rt_size_t sepc,struct rt_hw_stack_frame *sp)
|
||||
{
|
||||
if(scause == (uint64_t)(0x8000000000000005))
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
tick_isr();
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_size_t id = __MASKVALUE(scause,__MASK(63UL));
|
||||
const char *msg;
|
||||
|
||||
if(scause >> 63)
|
||||
{
|
||||
if(id < sizeof(Interrupt_Name) / sizeof(const char *))
|
||||
{
|
||||
msg = Interrupt_Name[id];
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Unknown Interrupt";
|
||||
}
|
||||
|
||||
rt_kprintf("Unhandled Interrupt %ld:%s\n",id,msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(id < sizeof(Exception_Name) / sizeof(const char *))
|
||||
{
|
||||
msg = Exception_Name[id];
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Unknown Exception";
|
||||
}
|
||||
|
||||
rt_kprintf("Unhandled Exception %ld:%s\n",id,msg);
|
||||
}
|
||||
|
||||
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n",scause,stval,sepc);
|
||||
dump_regs(sp);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Xim
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
@@ -13,8 +15,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sbi.h"
|
||||
|
||||
#define UART_DEFAULT_BAUDRATE 115200
|
||||
#include "interrupt.h"
|
||||
|
||||
struct device_uart
|
||||
{
|
||||
@@ -27,24 +28,26 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg
|
||||
static int drv_uart_putc(struct rt_serial_device *serial, char c);
|
||||
static int drv_uart_getc(struct rt_serial_device *serial);
|
||||
|
||||
const struct rt_uart_ops _uart_ops =
|
||||
void virt_uart_init(void)
|
||||
{
|
||||
rt_uart_configure,
|
||||
uart_control,
|
||||
drv_uart_putc,
|
||||
drv_uart_getc,
|
||||
//TODO: add DMA support
|
||||
RT_NULL
|
||||
};
|
||||
//http://byterunner.com/16550.html
|
||||
uart_write_reg(IER, 0x00);
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
return ;
|
||||
uint8_t lcr = uart_read_reg(LCR);
|
||||
uart_write_reg(LCR, lcr | (1 << 7));
|
||||
uart_write_reg(DLL, 0x03);
|
||||
uart_write_reg(DLM, 0x00);
|
||||
|
||||
lcr = 0;
|
||||
uart_write_reg(LCR, lcr | (3 << 0));
|
||||
|
||||
/*
|
||||
* enable receive interrupts.
|
||||
*/
|
||||
uint8_t ier = uart_read_reg(IER);
|
||||
uart_write_reg(IER, ier | (1 << 0));
|
||||
}
|
||||
|
||||
struct rt_serial_device serial1;
|
||||
struct device_uart uart1;
|
||||
|
||||
/*
|
||||
* UART interface
|
||||
*/
|
||||
@@ -58,22 +61,6 @@ static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial
|
||||
return (RT_EOK);
|
||||
}
|
||||
|
||||
#define UART_LSR_DR 0x01 /* Data ready */
|
||||
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
|
||||
|
||||
#define UART_RBR(hw) HWREG32(hw + 0x00)
|
||||
#define UART_IER(hw) HWREG32(hw + 0x04)
|
||||
#define UART_LSR(hw) HWREG32(hw + 0x14)
|
||||
|
||||
static volatile uint64_t uart_hwbase = 0x10000000;
|
||||
|
||||
void uart_putc(char c)
|
||||
{
|
||||
while ((UART_LSR(uart_hwbase) & UART_LSR_THRE) == 0);
|
||||
|
||||
UART_RBR(uart_hwbase) = c;
|
||||
}
|
||||
|
||||
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
|
||||
{
|
||||
struct device_uart *uart;
|
||||
@@ -98,38 +85,38 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg
|
||||
|
||||
static int drv_uart_putc(struct rt_serial_device *serial, char c)
|
||||
{
|
||||
sbi_console_putchar(c);
|
||||
return (1);
|
||||
while ((uart_read_reg(LSR) & LSR_TX_IDLE) == 0);
|
||||
return uart_write_reg(THR, c);
|
||||
}
|
||||
|
||||
static int drv_uart_getc(struct rt_serial_device *serial)
|
||||
{
|
||||
return sbi_console_getchar();
|
||||
}
|
||||
|
||||
char rt_hw_console_getchar(void)
|
||||
{
|
||||
return sbi_console_getchar();
|
||||
}
|
||||
|
||||
static void uart_rx(void *param)
|
||||
{
|
||||
struct rt_serial_device *serial = (struct rt_serial_device *)param;
|
||||
|
||||
while(1)
|
||||
{
|
||||
rt_hw_serial_isr((struct rt_serial_device *)serial,RT_SERIAL_EVENT_RX_IND);
|
||||
rt_thread_mdelay(10);
|
||||
if (uart_read_reg(LSR) & LSR_RX_READY){
|
||||
return uart_read_reg(RHR);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
//return sbi_console_getchar();
|
||||
}
|
||||
|
||||
void rt_hw_uart_start_rx_thread()
|
||||
static void rt_hw_uart_isr(int irqno, void *param)
|
||||
{
|
||||
rt_thread_t th;
|
||||
RT_ASSERT((th = rt_thread_create("uartrx",uart_rx,(void *)&serial1,8192,8,20)) != RT_NULL);
|
||||
RT_ASSERT(rt_thread_startup(th) == RT_EOK);
|
||||
struct rt_serial_device *serial = (struct rt_serial_device*)param;
|
||||
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
|
||||
}
|
||||
|
||||
struct rt_serial_device serial1;
|
||||
struct device_uart uart1;
|
||||
|
||||
const struct rt_uart_ops _uart_ops =
|
||||
{
|
||||
rt_uart_configure,
|
||||
uart_control,
|
||||
drv_uart_putc,
|
||||
drv_uart_getc,
|
||||
RT_NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* UART Initiation
|
||||
*/
|
||||
@@ -138,7 +125,6 @@ int rt_hw_uart_init(void)
|
||||
struct rt_serial_device *serial;
|
||||
struct device_uart *uart;
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
|
||||
{
|
||||
serial = &serial1;
|
||||
uart = &uart1;
|
||||
@@ -147,19 +133,19 @@ int rt_hw_uart_init(void)
|
||||
serial->config = config;
|
||||
serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
|
||||
|
||||
uart->hw_base = 0x10000000;
|
||||
uart->irqno = 0xa;
|
||||
uart->hw_base = UART_BASE;
|
||||
uart->irqno = UART0_IRQ;
|
||||
|
||||
virt_uart_init();
|
||||
|
||||
rt_hw_serial_register(serial,
|
||||
"uart",
|
||||
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
|
||||
uart);
|
||||
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart");
|
||||
|
||||
rt_hw_interrupt_umask(uart->irqno);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WEAK for SDK 0.5.6 */
|
||||
RT_WEAK void uart_debug_init(int uart_channel)
|
||||
{
|
||||
}
|
||||
@@ -1,15 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Xim
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_UART_H__
|
||||
#define __DRV_UART_H__
|
||||
|
||||
void rt_hw_uart_start_rx_thread();
|
||||
#define UART0_IRQ (10)
|
||||
|
||||
#define UART_DEFAULT_BAUDRATE 115200
|
||||
|
||||
#define UART_BASE (0x10000000L)
|
||||
|
||||
#define RHR 0 // Receive Holding Register (read mode)
|
||||
#define THR 0 // Transmit Holding Register (write mode)
|
||||
#define DLL 0 // LSB of Divisor Latch (write mode)
|
||||
#define IER 1 // Interrupt Enable Register (write mode)
|
||||
#define DLM 1 // MSB of Divisor Latch (write mode)
|
||||
#define FCR 2 // FIFO Control Register (write mode)
|
||||
#define ISR 2 // Interrupt Status Register (read mode)
|
||||
#define LCR 3 // Line Control Register
|
||||
#define MCR 4 // Modem Control Register
|
||||
#define LSR 5 // Line Status Register
|
||||
#define MSR 6 // Modem Status Register
|
||||
#define SPR 7 // ScratchPad Register
|
||||
|
||||
#define UART_REG(reg) ((volatile uint8_t *)(UART_BASE + reg))
|
||||
|
||||
#define LSR_RX_READY (1 << 0)
|
||||
#define LSR_TX_IDLE (1 << 5)
|
||||
|
||||
#define uart_read_reg(reg) (*(UART_REG(reg)))
|
||||
#define uart_write_reg(reg, v) (*(UART_REG(reg)) = (v))
|
||||
|
||||
int rt_hw_uart_init(void);
|
||||
void drv_uart_puts(char *str); // for syscall
|
||||
|
||||
#endif /* __DRV_UART_H__ */
|
||||
@@ -49,4 +49,4 @@ static inline uint32_t read_reg(
|
||||
return readl(addr + offset);
|
||||
}
|
||||
|
||||
#endif // ARCH_IO_H
|
||||
#endif // ARCH_IO_H
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
*/
|
||||
#include "rtthread.h"
|
||||
#include "plic.h"
|
||||
#include <riscv_io.h>
|
||||
#include "encoding.h"
|
||||
|
||||
/*
|
||||
* Each PLIC interrupt source can be assigned a priority by writing
|
||||
* to its 32-bit memory-mapped priority register.
|
||||
* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
|
||||
* A priority value of 0 is reserved to mean "never interrupt" and
|
||||
* effectively disables the interrupt.
|
||||
* Priority 1 is the lowest active priority, and priority 7 is the highest.
|
||||
* Ties between global interrupts of the same priority are broken by
|
||||
* the Interrupt ID; interrupts with the lowest ID have the highest
|
||||
* effective priority.
|
||||
*/
|
||||
void plic_set_priority(int irq, int priority)
|
||||
{
|
||||
*(uint32_t*)PLIC_PRIORITY(irq) = priority;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each global interrupt can be enabled by setting the corresponding
|
||||
* bit in the enables registers.
|
||||
*/
|
||||
void plic_irq_enable(int irq)
|
||||
{
|
||||
int hart = r_mhartid();
|
||||
*(uint32_t*)PLIC_ENABLE(hart) = ((*(uint32_t*)PLIC_ENABLE(hart)) | (1 << irq));
|
||||
#ifdef RISCV_S_MODE
|
||||
set_csr(sie, read_csr(sie) | MIP_SEIP);
|
||||
#else
|
||||
set_csr(mie, read_csr(mie) | MIP_MEIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
void plic_irq_disable(int irq)
|
||||
{
|
||||
int hart = r_mhartid();
|
||||
*(uint32_t*)PLIC_ENABLE(hart) = (((*(uint32_t*)PLIC_ENABLE(hart)) & (~(1 << irq))));
|
||||
}
|
||||
|
||||
/*
|
||||
* PLIC will mask all interrupts of a priority less than or equal to threshold.
|
||||
* Maximum threshold is 7.
|
||||
* For example, a threshold value of zero permits all interrupts with
|
||||
* non-zero priority, whereas a value of 7 masks all interrupts.
|
||||
* Notice, the threshold is global for PLIC, not for each interrupt source.
|
||||
*/
|
||||
void plic_set_threshold(int threshold)
|
||||
{
|
||||
int hart = r_mhartid();
|
||||
*(uint32_t*)PLIC_THRESHOLD(hart) = threshold;
|
||||
}
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
* Query the PLIC what interrupt we should serve.
|
||||
* Perform an interrupt claim by reading the claim register, which
|
||||
* returns the ID of the highest-priority pending interrupt or zero if there
|
||||
* is no pending interrupt.
|
||||
* A successful claim also atomically clears the corresponding pending bit
|
||||
* on the interrupt source.
|
||||
* RETURN VALUE:
|
||||
* the ID of the highest-priority pending interrupt or zero if there
|
||||
* is no pending interrupt.
|
||||
*/
|
||||
int plic_claim(void)
|
||||
{
|
||||
int hart = r_mhartid();
|
||||
int irq = *(uint32_t*)PLIC_CLAIM(hart);
|
||||
return irq;
|
||||
}
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
* Writing the interrupt ID it received from the claim (irq) to the
|
||||
* complete register would signal the PLIC we've served this IRQ.
|
||||
* The PLIC does not check whether the completion ID is the same as the
|
||||
* last claim ID for that target. If the completion ID does not match an
|
||||
* interrupt source that is currently enabled for the target, the completion
|
||||
* is silently ignored.
|
||||
* RETURN VALUE: none
|
||||
*/
|
||||
void plic_complete(int irq)
|
||||
{
|
||||
int hart = r_mhartid();
|
||||
*(uint32_t*)PLIC_COMPLETE(hart) = irq;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
*/
|
||||
|
||||
#ifndef PLIC_H
|
||||
#define PLIC_H
|
||||
|
||||
#include <rtconfig.h>
|
||||
/*
|
||||
* This machine puts platform-level interrupt controller (PLIC) here.
|
||||
* Here only list PLIC registers in Machine mode.
|
||||
*
|
||||
*/
|
||||
|
||||
#define VIRT_PLIC_BASE 0x0c000000L
|
||||
|
||||
#define PLIC_PRIORITY_OFFSET (0x0)
|
||||
#define PLIC_PENDING_OFFSET (0x1000)
|
||||
|
||||
#ifndef RISCV_S_MODE
|
||||
#define PLIC_MENABLE_OFFSET (0x2000)
|
||||
#define PLIC_MTHRESHOLD_OFFSET (0x200000)
|
||||
#define PLIC_MCLAIM_OFFSET (0x200004)
|
||||
#define PLIC_MCOMPLETE_OFFSET (0x200004)
|
||||
|
||||
#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_MENABLE_OFFSET + (hart) * 0x80)
|
||||
#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_MTHRESHOLD_OFFSET + (hart) * 0x1000)
|
||||
#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_MCLAIM_OFFSET + (hart) * 0x1000)
|
||||
#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_MCOMPLETE_OFFSET + (hart) * 0x1000)
|
||||
|
||||
#else
|
||||
#define PLIC_SENABLE_OFFSET (0x2080)
|
||||
#define PLIC_STHRESHOLD_OFFSET (0x201000)
|
||||
#define PLIC_SCLAIM_OFFSET (0x201004)
|
||||
#define PLIC_SCOMPLETE_OFFSET (0x201004)
|
||||
|
||||
#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_SENABLE_OFFSET + (hart) * 0x80)
|
||||
#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_STHRESHOLD_OFFSET + (hart) * 0x1000)
|
||||
#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_SCLAIM_OFFSET + (hart) * 0x1000)
|
||||
#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_SCOMPLETE_OFFSET + (hart) * 0x1000)
|
||||
#endif
|
||||
|
||||
#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4)
|
||||
#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32))
|
||||
|
||||
void plic_set_priority(int irq, int priority);
|
||||
void plic_irq_enable(int irq);
|
||||
void plic_irq_disable(int irq);
|
||||
void plic_set_threshold(int mthreshold);
|
||||
int plic_claim(void);
|
||||
void plic_complete(int irq);
|
||||
|
||||
#endif
|
||||
@@ -21,13 +21,13 @@ OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
SRAM : ORIGIN = 0x80200000, LENGTH = 0x7FF000
|
||||
SRAM : ORIGIN = __START_ADDR__, LENGTH = 0x7FF000
|
||||
}
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x80200000 ;
|
||||
. = __START_ADDR__ ;
|
||||
|
||||
/* __STACKSIZE__ = 4096; */
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
__STACKSIZE__ = 16384;
|
||||
__STACKSIZE__ = 16384;
|
||||
__START_ADDR__ = 0x80000000;
|
||||
+1
@@ -0,0 +1 @@
|
||||
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin
|
||||
Regular → Executable
+1
-1
@@ -1 +1 @@
|
||||
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin
|
||||
qemu-system-riscv64 -nographic -machine virt -m 256M -bios rtthread.bin
|
||||
@@ -177,7 +177,7 @@
|
||||
#define BOARD_virt
|
||||
#define RT_USING_USERSPACE
|
||||
|
||||
/* General Purpose UARTs */
|
||||
/* RISCV qemu virt64 configs */
|
||||
|
||||
#define __STACKSIZE__ 16384
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -18,17 +18,17 @@
|
||||
|
||||
/**
|
||||
* @brief from thread used interrupt context switch
|
||||
*
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
/**
|
||||
* @brief to thread used interrupt context switch
|
||||
*
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
/**
|
||||
* @brief flag to indicate context switch in interrupt or not
|
||||
*
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
|
||||
|
||||
@@ -70,8 +70,11 @@ rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame));
|
||||
|
||||
/* force to supervisor mode(SPP=1) and set SPIE and SUM to 1 */
|
||||
frame->sstatus = 0x00040120;
|
||||
#ifndef RISCV_S_MODE
|
||||
frame->xstatus = 0x00007880;
|
||||
#else
|
||||
frame->xstatus = 0x00040120;
|
||||
#endif
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -22,7 +22,34 @@
|
||||
// error here, not portable
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#ifdef RISCV_U_MODE
|
||||
#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
//csr in s-mode
|
||||
// M/U/S Interrupt Registers
|
||||
#define SRC_XIE sie
|
||||
#define SRC_XIP sip
|
||||
#define SRC_XTVEC stvec
|
||||
#define SRC_XSTATUS sstatus
|
||||
#define SRC_XSCRATCH sscratch
|
||||
#define SRC_XEPC sepc
|
||||
#define SRC_XCAUSE scause
|
||||
#define SRC_XTVAL stval
|
||||
#define XRET sret
|
||||
#else
|
||||
//csr in m-mode
|
||||
// M/U/S Interrupt Registers
|
||||
#define SRC_XIE mie
|
||||
#define SRC_XIP mip
|
||||
#define SRC_XTVEC mtvec
|
||||
#define SRC_XSTATUS mstatus
|
||||
#define SRC_XSCRATCH mscratch
|
||||
#define SRC_XEPC mepc
|
||||
#define SRC_XCAUSE mcause
|
||||
#define SRC_XTVAL mtval
|
||||
#define XRET mret
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic The first version
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPT_H__
|
||||
#define INTERRUPT_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include "stack.h"
|
||||
|
||||
int rt_hw_clint_ipi_enable(void);
|
||||
int rt_hw_clint_ipi_disable(void);
|
||||
int rt_hw_plic_irq_enable(int irq_number);
|
||||
int rt_hw_plic_irq_disable(int irq_number);
|
||||
void rt_hw_interrupt_init(void);
|
||||
void rt_hw_interrupt_mask(int vector);
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name);
|
||||
void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -26,4 +26,4 @@
|
||||
#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit))
|
||||
#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
+103
-75
File diff suppressed because it is too large.
Load diff
@@ -16,7 +16,7 @@ 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 sstatus; /* - supervisor status register */
|
||||
rt_ubase_t xstatus; /* - supervisor/machine/user 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 */
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, sstatus
|
||||
csrr x1, SRC_XSTATUS
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, sepc
|
||||
csrr x1, SRC_XEPC
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x3, 3 * REGBYTES(sp)
|
||||
@@ -54,17 +54,17 @@
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
csrr t0, sscratch
|
||||
csrr t0, SRC_XSCRATCH
|
||||
STORE t0, 32 * REGBYTES(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL_ONLY
|
||||
/* resw ra to sepc */
|
||||
LOAD x1, 0 * REGBYTES(sp)
|
||||
csrw sepc, x1
|
||||
csrw SRC_XEPC, x1
|
||||
|
||||
LOAD x1, 2 * REGBYTES(sp)
|
||||
csrw sstatus, x1
|
||||
csrw SRC_XSTATUS, x1
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
@@ -104,10 +104,10 @@
|
||||
.macro RESTORE_ALL
|
||||
/* resw ra to sepc */
|
||||
LOAD x1, 0 * REGBYTES(sp)
|
||||
csrw sepc, x1
|
||||
csrw SRC_XEPC, x1
|
||||
|
||||
LOAD x1, 2 * REGBYTES(sp)
|
||||
csrw sstatus, x1
|
||||
csrw SRC_XSTATUS, x1
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
@@ -152,12 +152,4 @@
|
||||
.option pop
|
||||
.endm
|
||||
|
||||
.macro OPEN_INTERRUPT
|
||||
csrsi sstatus, 2
|
||||
.endm
|
||||
|
||||
.macro CLOSE_INTERRUPT
|
||||
csrci sstatus, 2
|
||||
.endm
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -10,71 +10,48 @@
|
||||
* 2020/6/12 Xim Port to QEMU and remove SMP support
|
||||
*/
|
||||
|
||||
#define SSTATUS_FS 0x00006000U /* initial state of FPU, clear to disable */
|
||||
#define XSTATUS_FS (3 << 13) /* initial state of FPU, clear to disable */
|
||||
#define XSTATUS_PUM (1 << 18)
|
||||
#include <cpuport.h>
|
||||
|
||||
.global _start
|
||||
.section ".start", "ax"
|
||||
_start:
|
||||
j 1f
|
||||
.word 0xdeadbeef
|
||||
.align 3
|
||||
.global g_wake_up
|
||||
g_wake_up:
|
||||
.dword 1
|
||||
.dword 0
|
||||
1:
|
||||
csrw sie, 0
|
||||
csrw sip, 0
|
||||
la t0, trap_entry
|
||||
csrw stvec, t0
|
||||
#ifndef RISCV_S_MODE
|
||||
# setup stacks per hart
|
||||
csrr t0, mhartid # read current hart id
|
||||
slli t0, t0, 10 # shift left the hart id by 1024
|
||||
|
||||
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
|
||||
# park harts with id != 0
|
||||
csrr a0, mhartid # read current hart id
|
||||
bnez a0, park # if we're not on the hart 0
|
||||
#endif
|
||||
|
||||
csrw SRC_XIE, 0 # clear Interrupt Registers
|
||||
csrw SRC_XIP, 0
|
||||
|
||||
la t0, trap_entry
|
||||
csrw SRC_XTVEC, t0 # set Trap Vector Base Address Register
|
||||
|
||||
/* set to disable FPU */
|
||||
li t0, SSTATUS_FS
|
||||
csrc sstatus, t0
|
||||
li t0, 0x40000 // SUM in sstatus
|
||||
csrs sstatus, t0
|
||||
li t0, XSTATUS_FS # close fpu
|
||||
csrc SRC_XSTATUS, t0
|
||||
#ifdef RISCV_S_MODE
|
||||
li t0, XSTATUS_PUM # PUM has no effect
|
||||
csrs SRC_XSTATUS, t0
|
||||
#endif
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
// removed SMP support here
|
||||
la sp, __stack_start__
|
||||
li t0, __STACKSIZE__
|
||||
add sp, sp, t0
|
||||
csrw sscratch, sp
|
||||
csrw SRC_XSCRATCH, sp
|
||||
j primary_cpu_entry
|
||||
|
||||
park:
|
||||
wfi
|
||||
j park
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -11,8 +11,12 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <encoding.h>
|
||||
#include "sbi.h"
|
||||
#include "tick.h"
|
||||
#include <riscv_io.h>
|
||||
#include <encoding.h>
|
||||
|
||||
#define VIRT_CLINT_TIMEBASE_FREQ (10000000)
|
||||
|
||||
static volatile uint64_t time_elapsed = 0;
|
||||
static volatile unsigned long tick_cycles = 0;
|
||||
@@ -27,11 +31,13 @@ static uint64_t get_ticks()
|
||||
|
||||
int tick_isr(void)
|
||||
{
|
||||
// uint64_t core_id = current_coreid();
|
||||
int tick_cycles = 40000;
|
||||
// clint->mtimecmp[core_id] += tick_cycles;
|
||||
int tick_cycles = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
|
||||
rt_tick_increase();
|
||||
#ifdef RISCV_S_MODE
|
||||
sbi_set_timer(get_ticks() + tick_cycles);
|
||||
#else
|
||||
*(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + tick_cycles;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -39,10 +45,9 @@ int tick_isr(void)
|
||||
/* 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;
|
||||
unsigned long interval = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
/* Clear the Supervisor-Timer bit in SIE */
|
||||
clear_csr(sie, SIP_STIP);
|
||||
|
||||
@@ -54,6 +59,11 @@ int rt_hw_tick_init(void)
|
||||
|
||||
/* Enable the Supervisor-Timer bit in SIE */
|
||||
set_csr(sie, SIP_STIP);
|
||||
|
||||
#else
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
clear_csr(mip, MIP_MTIP);
|
||||
*(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + interval;
|
||||
set_csr(mie, MIP_MTIP);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -11,6 +11,11 @@
|
||||
#ifndef TICK_H__
|
||||
#define TICK_H__
|
||||
|
||||
//ask the CLINT for a timer interrupt.
|
||||
#define CLINT (0x2000000L)
|
||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 4*(hartid))
|
||||
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
|
||||
|
||||
int tick_isr(void);
|
||||
int rt_hw_tick_init(void);
|
||||
|
||||
|
||||
Reference in new issue
Block a user