未验证 提交 81c7bf89 编写于 作者: B Bernard Xiong 提交者: GitHub

Merge pull request #4711 from bigmagic123/rv64

Rv64 qemu virt Support M-Mode
...@@ -213,6 +213,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 ...@@ -213,6 +213,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_RYM is not set
# CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_ULOG is not set
# CONFIG_RT_USING_UTEST is not set # CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_RT_LINK is not set
# #
# RT-Thread Utestcases # RT-Thread Utestcases
...@@ -335,6 +336,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 ...@@ -335,6 +336,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# CONFIG_PKG_USING_HELIX is not set # CONFIG_PKG_USING_HELIX is not set
# CONFIG_PKG_USING_AZUREGUIX is not set # CONFIG_PKG_USING_AZUREGUIX is not set
# CONFIG_PKG_USING_TOUCHGFX2RTT is not set # CONFIG_PKG_USING_TOUCHGFX2RTT is not set
# CONFIG_PKG_USING_NUEMWIN is not set
# #
# tools packages # tools packages
...@@ -492,6 +494,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 ...@@ -492,6 +494,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# CONFIG_PKG_USING_LIBNFC is not set # CONFIG_PKG_USING_LIBNFC is not set
# CONFIG_PKG_USING_MFOC is not set # CONFIG_PKG_USING_MFOC is not set
# CONFIG_PKG_USING_TMC51XX is not set # CONFIG_PKG_USING_TMC51XX is not set
# CONFIG_PKG_USING_TCA9534 is not set
# #
# AI packages # AI packages
...@@ -519,6 +522,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 ...@@ -519,6 +522,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
# CONFIG_PKG_USING_CANFESTIVAL is not set # CONFIG_PKG_USING_CANFESTIVAL is not set
# CONFIG_PKG_USING_ZLIB 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_DSTR is not set
# CONFIG_PKG_USING_TINYFRAME is not set # CONFIG_PKG_USING_TINYFRAME is not set
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set # CONFIG_PKG_USING_KENDRYTE_DEMO is not set
...@@ -558,7 +562,8 @@ CONFIG_BOARD_virt=y ...@@ -558,7 +562,8 @@ CONFIG_BOARD_virt=y
CONFIG_RT_USING_USERSPACE=y CONFIG_RT_USING_USERSPACE=y
# #
# General Purpose UARTs # RISCV qemu virt64 configs
# #
# CONFIG_BSP_USING_UART1 is not set # CONFIG_BSP_USING_UART1 is not set
# CONFIG_RISCV_S_MODE is not set
CONFIG___STACKSIZE__=16384 CONFIG___STACKSIZE__=16384
# 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 ...@@ -31,7 +31,11 @@ stack_size = 4096
stack_lds = open('link_stacksize.lds', 'w') stack_lds = open('link_stacksize.lds', 'w')
if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__') 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() stack_lds.close()
# make a building # make a building
......
/* /*
* Copyright (c) 2006-2018, RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2021-05-20 bigmagic first version
*/ */
#include <rtthread.h> #include <rtthread.h>
...@@ -14,9 +15,7 @@ ...@@ -14,9 +15,7 @@
int main(void) int main(void)
{ {
void rt_hw_uart_start_rx_thread(); printf("Hello RISC-V!\n");
rt_hw_uart_start_rx_thread();
printf("Hello RISC-V\n");
return 0; return 0;
} }
menu "General Purpose UARTs" menu "RISCV qemu virt64 configs"
menuconfig BSP_USING_UART1 menuconfig BSP_USING_UART1
bool "Enable UART1" bool "Enable UART1"
...@@ -14,5 +14,8 @@ menuconfig BSP_USING_UART1 ...@@ -14,5 +14,8 @@ menuconfig BSP_USING_UART1
default 21 default 21
endif endif
endmenu config RISCV_S_MODE
bool "RT-Thread run in riscv smode"
default y
endmenu
/* /*
* Copyright (c) 2006-2020, RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#include "sbi.h" #include "sbi.h"
#include "riscv.h" #include "riscv.h"
#include "stack.h" #include "stack.h"
#include "riscv_io.h"
#include "plic.h"
#include "interrupt.h"
void primary_cpu_entry(void) void primary_cpu_entry(void)
{ {
...@@ -33,11 +36,6 @@ void primary_cpu_entry(void) ...@@ -33,11 +36,6 @@ void primary_cpu_entry(void)
entry(); entry();
} }
void rt_hw_interrupt_init()
{
/* Enable machine external interrupts. */
set_csr(sie, SIP_SEIP);
}
void rt_hw_board_init(void) void rt_hw_board_init(void)
{ {
...@@ -46,10 +44,7 @@ void rt_hw_board_init(void) ...@@ -46,10 +44,7 @@ void rt_hw_board_init(void)
/* initialize hardware interrupt */ /* initialize hardware interrupt */
rt_hw_uart_init(); rt_hw_uart_init();
rt_hw_tick_init();
#ifdef RT_USING_HEAP #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 */ /* initialize memory system */
rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
#endif #endif
...@@ -58,6 +53,8 @@ void rt_hw_board_init(void) ...@@ -58,6 +53,8 @@ void rt_hw_board_init(void)
/* set console device */ /* set console device */
rt_console_set_device("uart"); rt_console_set_device("uart");
#endif /* RT_USING_CONSOLE */ #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 #ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init(); rt_components_board_init();
...@@ -71,137 +68,3 @@ void rt_hw_cpu_reset(void) ...@@ -71,137 +68,3 @@ void rt_hw_cpu_reset(void)
} }
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); 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);
}
}
/* /*
* Copyright (c) 2006-2020, RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
......
/* /*
* Copyright (c) 2019-2020, Xim * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs:
* Date Author Notes
* 2021-05-20 bigmagic first version
*/ */
#include <rthw.h> #include <rthw.h>
#include <rtdevice.h> #include <rtdevice.h>
...@@ -13,8 +15,7 @@ ...@@ -13,8 +15,7 @@
#include <stdio.h> #include <stdio.h>
#include "sbi.h" #include "sbi.h"
#include "interrupt.h"
#define UART_DEFAULT_BAUDRATE 115200
struct device_uart struct device_uart
{ {
...@@ -27,24 +28,26 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg ...@@ -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_putc(struct rt_serial_device *serial, char c);
static int drv_uart_getc(struct rt_serial_device *serial); 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
};
void uart_init(void)
{ {
return ; //http://byterunner.com/16550.html
uart_write_reg(IER, 0x00);
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 * UART interface
*/ */
...@@ -58,22 +61,6 @@ static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial ...@@ -58,22 +61,6 @@ static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial
return (RT_EOK); 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) static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{ {
struct device_uart *uart; struct device_uart *uart;
...@@ -98,37 +85,37 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg ...@@ -98,37 +85,37 @@ 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_putc(struct rt_serial_device *serial, char c)
{ {
sbi_console_putchar(c); while ((uart_read_reg(LSR) & LSR_TX_IDLE) == 0);
return (1); return uart_write_reg(THR, c);
} }
static int drv_uart_getc(struct rt_serial_device *serial) static int drv_uart_getc(struct rt_serial_device *serial)
{ {
return sbi_console_getchar(); if (uart_read_reg(LSR) & LSR_RX_READY){
return uart_read_reg(RHR);
} else {
return -1;
}
//return sbi_console_getchar();
} }
char rt_hw_console_getchar(void) static void rt_hw_uart_isr(int irqno, void *param)
{ {
return sbi_console_getchar(); struct rt_serial_device *serial = (struct rt_serial_device*)param;
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
} }
static void uart_rx(void *param) struct rt_serial_device serial1;
{ struct device_uart uart1;
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);
}
}
void rt_hw_uart_start_rx_thread() const struct rt_uart_ops _uart_ops =
{ {
rt_thread_t th; rt_uart_configure,
RT_ASSERT((th = rt_thread_create("uartrx",uart_rx,(void *)&serial1,8192,8,20)) != RT_NULL); uart_control,
RT_ASSERT(rt_thread_startup(th) == RT_EOK); drv_uart_putc,
} drv_uart_getc,
RT_NULL
};
/* /*
* UART Initiation * UART Initiation
...@@ -138,7 +125,6 @@ int rt_hw_uart_init(void) ...@@ -138,7 +125,6 @@ int rt_hw_uart_init(void)
struct rt_serial_device *serial; struct rt_serial_device *serial;
struct device_uart *uart; struct device_uart *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
{ {
serial = &serial1; serial = &serial1;
uart = &uart1; uart = &uart1;
...@@ -147,19 +133,19 @@ int rt_hw_uart_init(void) ...@@ -147,19 +133,19 @@ int rt_hw_uart_init(void)
serial->config = config; serial->config = config;
serial->config.baud_rate = UART_DEFAULT_BAUDRATE; serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
uart->hw_base = 0x10000000; uart->hw_base = UART_BASE;
uart->irqno = 0xa; uart->irqno = UART0_IRQ;
virt_uart_init();
rt_hw_serial_register(serial, rt_hw_serial_register(serial,
"uart", "uart",
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart); 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 */ return 0;
RT_WEAK void uart_debug_init(int uart_channel)
{
} }
/* /*
* Copyright (c) 2019-2020, Xim * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs:
* Date Author Notes
* 2021-05-20 bigmagic first version
*/ */
#ifndef __DRV_UART_H__ #ifndef __DRV_UART_H__
#define __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); int rt_hw_uart_init(void);
void drv_uart_puts(char *str); // for syscall
#endif /* __DRV_UART_H__ */ #endif /* __DRV_UART_H__ */
...@@ -49,4 +49,4 @@ static inline uint32_t read_reg( ...@@ -49,4 +49,4 @@ static inline uint32_t read_reg(
return readl(addr + offset); return readl(addr + offset);
} }
#endif // ARCH_IO_H #endif // ARCH_IO_H
\ No newline at end of file
/*
* 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;
}
/*
* 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" ) ...@@ -21,13 +21,13 @@ OUTPUT_ARCH( "riscv" )
MEMORY MEMORY
{ {
SRAM : ORIGIN = 0x80200000, LENGTH = 0x7FF000 SRAM : ORIGIN = __START_ADDR__, LENGTH = 0x7FF000
} }
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x80200000 ; . = __START_ADDR__ ;
/* __STACKSIZE__ = 4096; */ /* __STACKSIZE__ = 4096; */
......
__STACKSIZE__ = 16384; __STACKSIZE__ = 16384;
\ No newline at end of file __START_ADDR__ = 0x80000000;
\ No newline at end of file
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin
\ No newline at end of file
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 @@ ...@@ -177,7 +177,7 @@
#define BOARD_virt #define BOARD_virt
#define RT_USING_USERSPACE #define RT_USING_USERSPACE
/* General Purpose UARTs */ /* RISCV qemu virt64 configs */
#define __STACKSIZE__ 16384 #define __STACKSIZE__ 16384
......
...@@ -9,44 +9,299 @@ ...@@ -9,44 +9,299 @@
* 2018/12/27 Jesven Add SMP support * 2018/12/27 Jesven Add SMP support
* 2021/02/02 lizhirui Add userspace support * 2021/02/02 lizhirui Add userspace support
*/ */
#include "cpuport.h" #include "cpuport.h"
#include "stackframe.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:
#ifdef RISCV_S_MODE
csrrci a0, sstatus, 2
#else
csrrci a0, mstatus, 8
#endif
ret
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
csrw SRC_XSTATUS, 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 .globl rt_hw_context_switch_to
rt_hw_context_switch_to: rt_hw_context_switch_to:
LOAD sp, (a0) LOAD sp, (a0)
la s0, rt_current_thread #ifdef RT_USING_SMP
LOAD s1, (s0) mv a0, a1
call rt_cpus_lock_status_restore
RESTORE_ALL #endif
sret LOAD a0, 2 * REGBYTES(sp)
csrw SRC_XSTATUS, 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); * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
* #endif
* *
* a0 --> from * a0 --> from
* a1 --> to * a1 --> to
* a2 --> to_thread
*/ */
.globl rt_hw_context_switch .globl rt_hw_context_switch
rt_hw_context_switch: rt_hw_context_switch:
mv t2, sp /* saved from thread context
li t0, 0x120//set SPIE and SPP = 1 * x1/ra -> sp(0)
csrs sstatus, t0//if enter here,caller must be in system thread * x1/ra -> sp(1)
csrw sepc, ra//return address * mstatus.mie -> sp(2)
//saved from thread context * x(i) -> sp(i-4)
SAVE_ALL */
#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
addi sp, sp, -32 * REGBYTES
STORE sp, (a0)
STORE x1, 0 * REGBYTES(sp)
STORE x1, 1 * REGBYTES(sp)
csrr a0, SRC_XSTATUS
#ifdef RISCV_S_MODE
andi a0, a0, 2
beqz a0, save_spie
li a0, 0x20
save_spie:
STORE a0, 2 * REGBYTES(sp)
#else
andi a0, a0, 8
beqz a0, save_mpie
li a0, 0x80
save_mpie:
STORE a0, 2 * REGBYTES(sp)
#endif
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)
#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 SRC_XEPC, a0
LOAD x1, 1 * REGBYTES(sp)
#ifdef RISCV_S_MODE
li t0, 0x00000120
csrw sstatus, t0
LOAD a0, 2 * REGBYTES(sp)
csrs sstatus, a0
#else
li t0, 0x00007800
csrw mstatus, t0
LOAD a0, 2 * REGBYTES(sp)
csrs mstatus, a0
#endif
STORE t2, 32 * REGBYTES(sp)//save user_sp 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)
STORE sp, (a0) addi sp, sp, 32 * REGBYTES
//restore to thread context #ifdef ARCH_RISCV_FPU
LOAD sp, (a1) 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)
la s0, rt_current_thread addi sp, sp, 32 * FREGBYTES
LOAD s1, (s0) #endif
RESTORE_ALL XRET
sret
...@@ -18,17 +18,17 @@ ...@@ -18,17 +18,17 @@
/** /**
* @brief from thread used interrupt context switch * @brief from thread used interrupt context switch
* *
*/ */
volatile rt_ubase_t rt_interrupt_from_thread = 0; volatile rt_ubase_t rt_interrupt_from_thread = 0;
/** /**
* @brief to thread used interrupt context switch * @brief to thread used interrupt context switch
* *
*/ */
volatile rt_ubase_t rt_interrupt_to_thread = 0; volatile rt_ubase_t rt_interrupt_to_thread = 0;
/** /**
* @brief flag to indicate context switch in interrupt or not * @brief flag to indicate context switch in interrupt or not
* *
*/ */
volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
...@@ -70,8 +70,11 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, ...@@ -70,8 +70,11 @@ rt_uint8_t *rt_hw_stack_init(void *tentry,
frame->epc = (rt_ubase_t)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)); 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 */ #ifndef RISCV_S_MODE
frame->sstatus = 0x00040120; frame->xstatus = 0x00007880;
#else
frame->xstatus = 0x00040120;
#endif
return stk; return stk;
} }
......
/* /*
* Copyright (c) 2006-2018, RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
...@@ -22,7 +22,34 @@ ...@@ -22,7 +22,34 @@
// error here, not portable // error here, not portable
#endif #endif
#endif
#ifdef RISCV_U_MODE #ifdef RISCV_U_MODE
#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL #define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL
#endif #endif
\ No newline at end of file
#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
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/01 Bernard The first version
* 2018/12/27 Jesven Change irq enable/disable to cpu0
*/
#include "tick.h"
#include <plic.h>
#include "encoding.h"
#include "riscv.h"
#include "interrupt.h"
#define CPU_NUM 2
#define MAX_HANDLERS 128
static struct rt_irq_desc irq_desc[MAX_HANDLERS];
static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
{
rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
return RT_NULL;
}
int rt_hw_clint_ipi_enable(void)
{
/* Set the Machine-Software bit in MIE */
set_csr(mie, MIP_MSIP);
return 0;
}
int rt_hw_clint_ipi_disable(void)
{
/* Clear the Machine-Software bit in MIE */
clear_csr(mie, MIP_MSIP);
return 0;
}
int rt_hw_plic_irq_enable(int irq_number)
{
plic_irq_enable(irq_number);
return 0;
}
int rt_hw_plic_irq_disable(int irq_number)
{
plic_irq_disable(irq_number);
return 0;
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
int idx = 0;
/* init exceptions table */
for (idx = 0; idx < MAX_HANDLERS; idx++)
{
//rt_hw_interrupt_mask(idx);
irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
irq_desc[idx].param = RT_NULL;
#ifdef RT_USING_INTERRUPT_INFO
rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
irq_desc[idx].counter = 0;
#endif
}
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
rt_hw_plic_irq_disable(vector);
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
plic_set_priority(vector, 1);
plic_set_threshold(0);
rt_hw_plic_irq_enable(vector);
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if(vector < MAX_HANDLERS)
{
old_handler = irq_desc[vector].handler;
if (handler != RT_NULL)
{
irq_desc[vector].handler = (rt_isr_handler_t)handler;
irq_desc[vector].param = param;
#ifdef RT_USING_INTERRUPT_INFO
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
irq_desc[vector].counter = 0;
#endif
}
}
return old_handler;
}
RT_WEAK
void plic_irq_handle(int irq)
{
rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq);
return ;
}
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("xstatus = 0x%p\n",regs -> xstatus);
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
rt_kprintf("\t%s\n",(regs -> xstatus & (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");
}
void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp)
{
int cause = (xcause & 0xFFFFFFFF);
int plic_irq = 0;
if (xcause & (1UL << 63))
{
switch (cause)
{
case IRQ_M_SOFT:
{
}
break;
case IRQ_M_TIMER:
tick_isr();
break;
case IRQ_S_TIMER:
tick_isr();
break;
case IRQ_S_EXT:
plic_irq = plic_claim();
plic_complete(plic_irq);
irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
break;
case IRQ_M_EXT:
plic_irq = plic_claim();
plic_complete(plic_irq);
irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
break;
}
}
else
{
rt_thread_t tid;
extern long list_thread();
rt_hw_interrupt_disable();
rt_kprintf("xcause = %08x,xtval = %08x,xepc = %08x\n", xcause, xtval, xepc);
tid = rt_thread_self();
rt_kprintf("\nException:\n");
switch (cause)
{
case CAUSE_MISALIGNED_FETCH:
rt_kprintf("Instruction address misaligned");
break;
case CAUSE_FAULT_FETCH:
rt_kprintf("Instruction access fault");
break;
case CAUSE_ILLEGAL_INSTRUCTION:
rt_kprintf("Illegal instruction");
break;
case CAUSE_BREAKPOINT:
rt_kprintf("Breakpoint");
break;
case CAUSE_MISALIGNED_LOAD:
rt_kprintf("Load address misaligned");
break;
case CAUSE_FAULT_LOAD:
rt_kprintf("Load access fault");
break;
case CAUSE_MISALIGNED_STORE:
rt_kprintf("Store address misaligned");
break;
case CAUSE_FAULT_STORE:
rt_kprintf("Store access fault");
break;
case CAUSE_USER_ECALL:
rt_kprintf("Environment call from U-mode");
break;
case CAUSE_SUPERVISOR_ECALL:
rt_kprintf("Environment call from S-mode");
break;
case CAUSE_HYPERVISOR_ECALL:
rt_kprintf("Environment call from H-mode");
break;
case CAUSE_MACHINE_ECALL:
rt_kprintf("Environment call from M-mode");
break;
default:
rt_kprintf("Uknown exception : %08lX", cause);
break;
}
rt_kprintf("\n");
dump_regs(sp);
rt_kprintf("exception pc => 0x%08x\n", xepc);
rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
while(1);
}
rt_hw_interrupt_enable(0);
}
/*
* 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
...@@ -11,31 +11,125 @@ ...@@ -11,31 +11,125 @@
*/ */
#include "cpuport.h" #include "cpuport.h"
#include "encoding.h"
#include "stackframe.h"
.section .text.entry .section .text.entry
.align 2 .align 2
.global trap_entry .global trap_entry
.extern __stack_cpu0
.extern get_current_thread_kernel_stack_top
trap_entry: trap_entry:
//backup sp #ifdef ARCH_RISCV_FPU
csrrw sp, sscratch, sp addi sp, sp, -32 * FREGBYTES
//load interrupt stack
la sp, __stack_cpu0 FSTORE f0, 0 * FREGBYTES(sp)
//backup context FSTORE f1, 1 * FREGBYTES(sp)
SAVE_ALL FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
RESTORE_SYS_GP FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
csrr a0, scause FSTORE f6, 6 * FREGBYTES(sp)
csrrc a1, stval, zero FSTORE f7, 7 * FREGBYTES(sp)
csrr a2, sepc FSTORE f8, 8 * FREGBYTES(sp)
mv a3, sp FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
/* scause, stval, sepc, 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 */
addi sp, sp, -32 * REGBYTES
STORE x1, 1 * REGBYTES(sp)
csrr x1, SRC_XSTATUS
STORE x1, 2 * REGBYTES(sp)
csrr x1, SRC_XEPC
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)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
/* switch to interrupt stack */
move s0, sp
#ifndef RISCV_S_MODE
/* get cpu id */
csrr t0, mhartid
#else
li t0, 0
#endif
/* switch interrupt stack of current cpu */
la sp, __stack_start__
addi t1, t0, 1
li t2, __STACKSIZE__
mul t1, t1, t2
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
/* handle interrupt */
call rt_interrupt_enter
csrr a0, SRC_XCAUSE
csrr a1, SRC_XEPC
mv a2, s0
call handle_trap 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 */ /* need to switch new thread */
la s0, rt_thread_switch_interrupt_flag la s0, rt_thread_switch_interrupt_flag
...@@ -43,41 +137,6 @@ trap_entry: ...@@ -43,41 +137,6 @@ trap_entry:
beqz s2, spurious_interrupt beqz s2, spurious_interrupt
sw zero, 0(s0) sw zero, 0(s0)
.global rt_hw_context_switch_interrupt_do
rt_hw_context_switch_interrupt_do:
//switch to thread kernel stack
csrr t0, sstatus
andi t0, t0, 0x100
beqz t0, __restore_sp_from_tcb_interrupt
__restore_sp_from_sscratch_interrupt:
csrr t0, sscratch
j __move_stack_context_interrupt
__restore_sp_from_tcb_interrupt:
la s0, rt_interrupt_from_thread
LOAD a0, 0(s0)
jal rt_thread_sp_to_thread
jal get_thread_kernel_stack_top
mv t0, a0
__move_stack_context_interrupt:
mv t1, sp//src
mv sp, t0//switch stack
addi sp, sp, -33 * REGBYTES
//copy context
li s0, 33//cnt
mv t2, sp//dst
copy_context_loop_interrupt:
LOAD t0, 0(t1)
STORE t0, 0(t2)
addi s0, s0, -1
addi t1, t1, 8
addi t2, t2, 8
bnez s0, copy_context_loop_interrupt
la s0, rt_interrupt_from_thread la s0, rt_interrupt_from_thread
LOAD s1, 0(s0) LOAD s1, 0(s0)
STORE sp, 0(s1) STORE sp, 0(s1)
...@@ -86,16 +145,7 @@ copy_context_loop_interrupt: ...@@ -86,16 +145,7 @@ copy_context_loop_interrupt:
LOAD s1, 0(s0) LOAD s1, 0(s0)
LOAD sp, 0(s1) LOAD sp, 0(s1)
#endif
spurious_interrupt: spurious_interrupt:
RESTORE_ALL tail rt_hw_context_switch_exit
sret
.global rt_hw_interrupt_enable
rt_hw_interrupt_enable:
csrs sstatus, a0
jr ra
.global rt_hw_interrupt_disable
rt_hw_interrupt_disable:
csrrci a0, sstatus, 2
jr ra
...@@ -26,4 +26,4 @@ ...@@ -26,4 +26,4 @@
#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit)) #define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit))
#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit)) #define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit))
#endif #endif
\ No newline at end of file
...@@ -10,100 +10,128 @@ ...@@ -10,100 +10,128 @@
#ifndef __RISCV_IO_H__ #ifndef __RISCV_IO_H__
#define __RISCV_IO_H__ #define __RISCV_IO_H__
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr) // which hart (core) is this?
{ static inline uint32_t r_mhartid()
asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); {
} #ifndef RISCV_S_MODE
uint32_t x;
static inline void __raw_writew(rt_uint16_t val, volatile void *addr) asm volatile("csrr %0, mhartid" : "=r" (x) );
{ return x;
asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); #else
} return 0;
#endif
static inline void __raw_writel(rt_uint32_t val, volatile void *addr) }
{
asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
} {
asm volatile("sb %0, 0(%1)"
#if __riscv_xlen != 32 :
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr) : "r"(val), "r"(addr));
{ }
asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
} static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
#endif {
asm volatile("sh %0, 0(%1)"
static inline rt_uint8_t __raw_readb(const volatile void *addr) :
{ : "r"(val), "r"(addr));
rt_uint8_t val; }
asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr)); static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
return val; {
} asm volatile("sw %0, 0(%1)"
:
static inline rt_uint16_t __raw_readw(const volatile void *addr) : "r"(val), "r"(addr));
{ }
rt_uint16_t val;
#if __riscv_xlen != 32
asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr)); static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
return val; {
} asm volatile("sd %0, 0(%1)"
:
static inline rt_uint32_t __raw_readl(const volatile void *addr) : "r"(val), "r"(addr));
{ }
rt_uint32_t val; #endif
asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr)); static inline rt_uint8_t __raw_readb(const volatile void *addr)
return val; {
} rt_uint8_t val;
#if __riscv_xlen != 32 asm volatile("lb %0, 0(%1)"
static inline rt_uint64_t __raw_readq(const volatile void *addr) : "=r"(val)
{ : "r"(addr));
rt_uint64_t val; return val;
}
asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
return val; static inline rt_uint16_t __raw_readw(const volatile void *addr)
} {
#endif rt_uint16_t val;
/* FIXME: These are now the same as asm-generic */ asm volatile("lh %0, 0(%1)"
: "=r"(val)
/* clang-format off */ : "r"(addr));
return val;
#define __io_rbr() do {} while (0) }
#define __io_rar() do {} while (0)
#define __io_rbw() do {} while (0) static inline rt_uint32_t __raw_readl(const volatile void *addr)
#define __io_raw() do {} while (0) {
rt_uint32_t val;
#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) asm volatile("lw %0, 0(%1)"
#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) : "=r"(val)
: "r"(addr));
#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) return val;
#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) }
#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
#if __riscv_xlen != 32
#if __riscv_xlen != 32 static inline rt_uint64_t __raw_readq(const volatile void *addr)
#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) {
#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) rt_uint64_t val;
#endif
asm volatile("ld %0, 0(%1)"
#define __io_br() do {} while (0) : "=r"(val)
#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); : "r"(addr));
#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); return val;
#define __io_aw() do {} while (0) }
#endif
#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) /* FIXME: These are now the same as asm-generic */
#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
/* clang-format off */
#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) #define __io_rbr() do {} while (0)
#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) #define __io_rar() do {} while (0)
#define __io_rbw() do {} while (0)
#if __riscv_xlen != 32 #define __io_raw() do {} while (0)
#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) #define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
#endif #define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
#endif
\ No newline at end of file #define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
#if __riscv_xlen != 32
#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
#endif
#define __io_br() do {} while (0)
#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
#define __io_aw() do {} while (0)
#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
#if __riscv_xlen != 32
#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
#endif
#endif
...@@ -16,7 +16,7 @@ struct rt_hw_stack_frame ...@@ -16,7 +16,7 @@ struct rt_hw_stack_frame
{ {
rt_ubase_t epc; /* epc - epc - program counter */ rt_ubase_t epc; /* epc - epc - program counter */
rt_ubase_t ra; /* x1 - ra - return address for jumps */ 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 gp; /* x3 - gp - global pointer */
rt_ubase_t tp; /* x4 - tp - thread pointer */ rt_ubase_t tp; /* x4 - tp - thread pointer */
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
......
...@@ -19,10 +19,10 @@ ...@@ -19,10 +19,10 @@
STORE x1, 1 * REGBYTES(sp) STORE x1, 1 * REGBYTES(sp)
csrr x1, sstatus csrr x1, SRC_XSTATUS
STORE x1, 2 * REGBYTES(sp) STORE x1, 2 * REGBYTES(sp)
csrr x1, sepc csrr x1, SRC_XEPC
STORE x1, 0 * REGBYTES(sp) STORE x1, 0 * REGBYTES(sp)
STORE x3, 3 * REGBYTES(sp) STORE x3, 3 * REGBYTES(sp)
...@@ -54,17 +54,17 @@ ...@@ -54,17 +54,17 @@
STORE x29, 29 * REGBYTES(sp) STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp) STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp) STORE x31, 31 * REGBYTES(sp)
csrr t0, sscratch csrr t0, SRC_XSCRATCH
STORE t0, 32 * REGBYTES(sp) STORE t0, 32 * REGBYTES(sp)
.endm .endm
.macro RESTORE_ALL_ONLY .macro RESTORE_ALL_ONLY
/* resw ra to sepc */ /* resw ra to sepc */
LOAD x1, 0 * REGBYTES(sp) LOAD x1, 0 * REGBYTES(sp)
csrw sepc, x1 csrw SRC_XEPC, x1
LOAD x1, 2 * REGBYTES(sp) LOAD x1, 2 * REGBYTES(sp)
csrw sstatus, x1 csrw SRC_XSTATUS, x1
LOAD x1, 1 * REGBYTES(sp) LOAD x1, 1 * REGBYTES(sp)
...@@ -104,10 +104,10 @@ ...@@ -104,10 +104,10 @@
.macro RESTORE_ALL .macro RESTORE_ALL
/* resw ra to sepc */ /* resw ra to sepc */
LOAD x1, 0 * REGBYTES(sp) LOAD x1, 0 * REGBYTES(sp)
csrw sepc, x1 csrw SRC_XEPC, x1
LOAD x1, 2 * REGBYTES(sp) LOAD x1, 2 * REGBYTES(sp)
csrw sstatus, x1 csrw SRC_XSTATUS, x1
LOAD x1, 1 * REGBYTES(sp) LOAD x1, 1 * REGBYTES(sp)
...@@ -152,12 +152,4 @@ ...@@ -152,12 +152,4 @@
.option pop .option pop
.endm .endm
.macro OPEN_INTERRUPT #endif
csrsi sstatus, 2
.endm
.macro CLOSE_INTERRUPT
csrci sstatus, 2
.endm
#endif
\ No newline at end of file
...@@ -10,71 +10,48 @@ ...@@ -10,71 +10,48 @@
* 2020/6/12 Xim Port to QEMU and remove SMP support * 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> #include <cpuport.h>
.global _start .global _start
.section ".start", "ax" .section ".start", "ax"
_start: _start:
j 1f #ifndef RISCV_S_MODE
.word 0xdeadbeef # setup stacks per hart
.align 3 csrr t0, mhartid # read current hart id
.global g_wake_up slli t0, t0, 10 # shift left the hart id by 1024
g_wake_up:
.dword 1 # park harts with id != 0
.dword 0 csrr a0, mhartid # read current hart id
1: bnez a0, park # if we're not on the hart 0
csrw sie, 0 #endif
csrw sip, 0
la t0, trap_entry
csrw stvec, t0
li x1, 0 csrw SRC_XIE, 0 # clear Interrupt Registers
li x2, 0 csrw SRC_XIP, 0
li x3, 0
li x4, 0 la t0, trap_entry
li x5, 0 csrw SRC_XTVEC, t0 # set Trap Vector Base Address Register
li x6, 0
li x7, 0
li x8, 0
li x9, 0
li x10,0
li x11,0
li x12,0
li x13,0
li x14,0
li x15,0
li x16,0
li x17,0
li x18,0
li x19,0
li x20,0
li x21,0
li x22,0
li x23,0
li x24,0
li x25,0
li x26,0
li x27,0
li x28,0
li x29,0
li x30,0
li x31,0
/* set to disable FPU */ /* set to disable FPU */
li t0, SSTATUS_FS li t0, XSTATUS_FS # close fpu
csrc sstatus, t0 csrc SRC_XSTATUS, t0
li t0, 0x40000 // SUM in sstatus #ifdef RISCV_S_MODE
csrs sstatus, t0 li t0, XSTATUS_PUM # PUM has no effect
csrs SRC_XSTATUS, t0
#endif
.option push .option push
.option norelax .option norelax
la gp, __global_pointer$ la gp, __global_pointer$
.option pop .option pop
// removed SMP support here
la sp, __stack_start__ la sp, __stack_start__
li t0, __STACKSIZE__ li t0, __STACKSIZE__
add sp, sp, t0 add sp, sp, t0
csrw sscratch, sp csrw SRC_XSCRATCH, sp
j primary_cpu_entry j primary_cpu_entry
park:
wfi
j park
\ No newline at end of file
/* /*
* Copyright (c) 2006-2018, RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
...@@ -11,8 +11,12 @@ ...@@ -11,8 +11,12 @@
#include <rthw.h> #include <rthw.h>
#include <rtthread.h> #include <rtthread.h>
#include <encoding.h>
#include "sbi.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 uint64_t time_elapsed = 0;
static volatile unsigned long tick_cycles = 0; static volatile unsigned long tick_cycles = 0;
...@@ -27,11 +31,13 @@ static uint64_t get_ticks() ...@@ -27,11 +31,13 @@ static uint64_t get_ticks()
int tick_isr(void) int tick_isr(void)
{ {
// uint64_t core_id = current_coreid(); int tick_cycles = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
int tick_cycles = 40000;
// clint->mtimecmp[core_id] += tick_cycles;
rt_tick_increase(); rt_tick_increase();
#ifdef RISCV_S_MODE
sbi_set_timer(get_ticks() + tick_cycles); sbi_set_timer(get_ticks() + tick_cycles);
#else
*(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + tick_cycles;
#endif
return 0; return 0;
} }
...@@ -39,10 +45,9 @@ int tick_isr(void) ...@@ -39,10 +45,9 @@ int tick_isr(void)
/* Sets and enable the timer interrupt */ /* Sets and enable the timer interrupt */
int rt_hw_tick_init(void) int rt_hw_tick_init(void)
{ {
/* Read core id */ unsigned long interval = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
// unsigned long core_id = current_coreid();
unsigned long interval = 1000/RT_TICK_PER_SECOND;
#ifdef RISCV_S_MODE
/* Clear the Supervisor-Timer bit in SIE */ /* Clear the Supervisor-Timer bit in SIE */
clear_csr(sie, SIP_STIP); clear_csr(sie, SIP_STIP);
...@@ -54,6 +59,11 @@ int rt_hw_tick_init(void) ...@@ -54,6 +59,11 @@ int rt_hw_tick_init(void)
/* Enable the Supervisor-Timer bit in SIE */ /* Enable the Supervisor-Timer bit in SIE */
set_csr(sie, SIP_STIP); 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; return 0;
} }
/* /*
* Copyright (c) 2006-2018, RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
...@@ -11,6 +11,11 @@ ...@@ -11,6 +11,11 @@
#ifndef TICK_H__ #ifndef TICK_H__
#define 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 tick_isr(void);
int rt_hw_tick_init(void); int rt_hw_tick_init(void);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册