Compare commits
14 Commits
bf0e4ec057
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 499468b819 | |||
| 925f08e0b9 | |||
| be32d2467c | |||
| c8ea882b3e | |||
| 5f220ff09b | |||
| d8728e319c | |||
| fce1372494 | |||
| fc3f6c57e5 | |||
| 328a961276 | |||
| 6e2607cecc | |||
| fced281870 | |||
| 703fbf67b4 | |||
| 59d0a22738 | |||
| 3df19468e9 |
@@ -2,8 +2,10 @@ cmake_minimum_required(VERSION 3.21)
|
|||||||
include(CheckLinkerFlag)
|
include(CheckLinkerFlag)
|
||||||
|
|
||||||
project(mnrs-bsp LANGUAGES ASM C)
|
project(mnrs-bsp LANGUAGES ASM C)
|
||||||
|
option(NO_INIT "use an empty init routine" OFF)
|
||||||
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/env/${BOARD}/link.lds"
|
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/env/${BOARD}/link.lds"
|
||||||
CACHE FILEPATH "Linker script to use for BSP linking")
|
CACHE FILEPATH "Linker script to use for BSP linking")
|
||||||
|
get_filename_component(LINKER_SCRIPT_DIR "${LINKER_SCRIPT}" DIRECTORY)
|
||||||
set(BSP_STARTUP "${CMAKE_CURRENT_SOURCE_DIR}/env/start.S"
|
set(BSP_STARTUP "${CMAKE_CURRENT_SOURCE_DIR}/env/start.S"
|
||||||
CACHE FILEPATH "Path to the BSP startup assembly file")
|
CACHE FILEPATH "Path to the BSP startup assembly file")
|
||||||
set(BSP_TRAP_HANDLER "${CMAKE_CURRENT_SOURCE_DIR}/env/entry.S"
|
set(BSP_TRAP_HANDLER "${CMAKE_CURRENT_SOURCE_DIR}/env/entry.S"
|
||||||
@@ -29,18 +31,22 @@ target_include_directories(startup PUBLIC env include)
|
|||||||
|
|
||||||
add_subdirectory(libwrap)
|
add_subdirectory(libwrap)
|
||||||
|
|
||||||
add_library(bsp STATIC env/${BOARD}/init.c)
|
add_library(runtime STATIC env/${BOARD}/init.c)
|
||||||
target_link_libraries(bsp PUBLIC startup wrap)
|
target_include_directories(runtime PUBLIC env/${BOARD} env include)
|
||||||
target_include_directories(bsp PUBLIC env/${BOARD})
|
if(NO_INIT)
|
||||||
|
target_compile_definitions(runtime PRIVATE NO_INIT)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_linker_flag(C "LINKER:--no-warn-rwx-segments" HAS_NO_WARN_RWX_SEGMENTS)
|
check_linker_flag(C "LINKER:--no-warn-rwx-segments" HAS_NO_WARN_RWX_SEGMENTS)
|
||||||
|
|
||||||
if(HAS_NO_WARN_RWX_SEGMENTS)
|
if(HAS_NO_WARN_RWX_SEGMENTS)
|
||||||
target_link_options(bsp INTERFACE LINKER:--no-warn-rwx-segments)
|
target_link_options(runtime INTERFACE LINKER:--no-warn-rwx-segments)
|
||||||
endif()
|
endif()
|
||||||
target_link_options(bsp INTERFACE LINKER: -nostartfiles -T ${LINKER_SCRIPT})
|
target_link_options(runtime INTERFACE LINKER: -nostartfiles -T ${LINKER_SCRIPT} -L${LINKER_SCRIPT_DIR})
|
||||||
|
|
||||||
if(SEMIHOSTING)
|
if(SEMIHOSTING)
|
||||||
target_include_directories(bsp INTERFACE include)
|
target_sources(runtime INTERFACE env/semihosting.c env/trap.c)
|
||||||
target_sources(bsp INTERFACE env/semihosting.c env/trap.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_library(bsp INTERFACE)
|
||||||
|
target_link_libraries(bsp INTERFACE startup runtime wrap)
|
||||||
|
|
||||||
|
|||||||
16
env/entry.S
vendored
16
env/entry.S
vendored
@@ -10,12 +10,13 @@
|
|||||||
.align 2
|
.align 2
|
||||||
.global trap_entry
|
.global trap_entry
|
||||||
trap_entry:
|
trap_entry:
|
||||||
addi sp, sp, -32*REGBYTES
|
#ifdef __riscv_abi_rve
|
||||||
|
addi sp, sp, -12*REGBYTES
|
||||||
|
#else
|
||||||
|
addi sp, sp, -28*REGBYTES
|
||||||
|
#endif
|
||||||
|
|
||||||
sw x1, 1*REGBYTES(sp)
|
sw x1, 1*REGBYTES(sp)
|
||||||
sw x2, 2*REGBYTES(sp)
|
|
||||||
sw x3, 3*REGBYTES(sp)
|
|
||||||
sw x4, 4*REGBYTES(sp)
|
|
||||||
sw x5, 5*REGBYTES(sp)
|
sw x5, 5*REGBYTES(sp)
|
||||||
sw x6, 6*REGBYTES(sp)
|
sw x6, 6*REGBYTES(sp)
|
||||||
sw x7, 7*REGBYTES(sp)
|
sw x7, 7*REGBYTES(sp)
|
||||||
@@ -53,9 +54,6 @@ trap_entry:
|
|||||||
|
|
||||||
|
|
||||||
lw x1, 1*REGBYTES(sp)
|
lw x1, 1*REGBYTES(sp)
|
||||||
lw x2, 2*REGBYTES(sp)
|
|
||||||
lw x3, 3*REGBYTES(sp)
|
|
||||||
lw x4, 4*REGBYTES(sp)
|
|
||||||
lw x5, 5*REGBYTES(sp)
|
lw x5, 5*REGBYTES(sp)
|
||||||
lw x6, 6*REGBYTES(sp)
|
lw x6, 6*REGBYTES(sp)
|
||||||
lw x7, 7*REGBYTES(sp)
|
lw x7, 7*REGBYTES(sp)
|
||||||
@@ -84,6 +82,9 @@ trap_entry:
|
|||||||
lw x29, 29*REGBYTES(sp)
|
lw x29, 29*REGBYTES(sp)
|
||||||
lw x30, 30*REGBYTES(sp)
|
lw x30, 30*REGBYTES(sp)
|
||||||
lw x31, 31*REGBYTES(sp)
|
lw x31, 31*REGBYTES(sp)
|
||||||
|
addi sp, sp, 28*REGBYTES
|
||||||
|
#else
|
||||||
|
addi sp, sp, 12*REGBYTES
|
||||||
#endif
|
#endif
|
||||||
mret
|
mret
|
||||||
|
|
||||||
@@ -91,5 +92,4 @@ trap_entry:
|
|||||||
handle_trap:
|
handle_trap:
|
||||||
1:
|
1:
|
||||||
j 1b
|
j 1b
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
175
env/riscv_vp/flash.lds
vendored
175
env/riscv_vp/flash.lds
vendored
@@ -4,174 +4,9 @@ ENTRY( _start )
|
|||||||
|
|
||||||
INCLUDE memory_map.ld
|
INCLUDE memory_map.ld
|
||||||
|
|
||||||
PHDRS
|
REGION_ALIAS("REGION_TEXT", flash);
|
||||||
{
|
REGION_ALIAS("REGION_RODATA", flash);
|
||||||
flash PT_LOAD;
|
REGION_ALIAS("REGION_DATA", ram);
|
||||||
ram_init PT_LOAD;
|
REGION_ALIAS("REGION_BSS", ram);
|
||||||
ram PT_NULL;
|
|
||||||
dram PT_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS
|
INCLUDE sections.ld
|
||||||
{
|
|
||||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
|
||||||
|
|
||||||
.init ORIGIN(flash) :
|
|
||||||
{
|
|
||||||
KEEP (*(SORT_NONE(.init)))
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
*(.text.unlikely .text.unlikely.*)
|
|
||||||
*(.text.startup .text.startup.*)
|
|
||||||
*(.text .text.*)
|
|
||||||
*(.gnu.linkonce.t.*)
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.fini :
|
|
||||||
{
|
|
||||||
KEEP (*(SORT_NONE(.fini)))
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
PROVIDE (__etext = .);
|
|
||||||
PROVIDE (_etext = .);
|
|
||||||
PROVIDE (etext = .);
|
|
||||||
|
|
||||||
.rodata :
|
|
||||||
{
|
|
||||||
*(.rdata)
|
|
||||||
*(.rodata .rodata.*)
|
|
||||||
*(.gnu.linkonce.r.*)
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
|
|
||||||
.preinit_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
|
||||||
KEEP (*(.preinit_array))
|
|
||||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.init_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__init_array_start = .);
|
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
|
||||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
|
||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.fini_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
|
||||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
|
||||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.ctors :
|
|
||||||
{
|
|
||||||
/* gcc uses crtbegin.o to find the start of
|
|
||||||
the constructors, so we make sure it is
|
|
||||||
first. Because this is a wildcard, it
|
|
||||||
doesn't matter if the user does not
|
|
||||||
actually link against crtbegin.o; the
|
|
||||||
linker won't look for a file to match a
|
|
||||||
wildcard. The wildcard also means that it
|
|
||||||
doesn't matter which directory crtbegin.o
|
|
||||||
is in. */
|
|
||||||
KEEP (*crtbegin.o(.ctors))
|
|
||||||
KEEP (*crtbegin?.o(.ctors))
|
|
||||||
/* We don't want to include the .ctor section from
|
|
||||||
the crtend.o file until after the sorted ctors.
|
|
||||||
The .ctor section from the crtend file contains the
|
|
||||||
end of ctors marker and it must be last */
|
|
||||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
|
||||||
KEEP (*(SORT(.ctors.*)))
|
|
||||||
KEEP (*(.ctors))
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.dtors :
|
|
||||||
{
|
|
||||||
KEEP (*crtbegin.o(.dtors))
|
|
||||||
KEEP (*crtbegin?.o(.dtors))
|
|
||||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
|
||||||
KEEP (*(SORT(.dtors.*)))
|
|
||||||
KEEP (*(.dtors))
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.dummy :
|
|
||||||
{
|
|
||||||
*(.comment.*)
|
|
||||||
|
|
||||||
}
|
|
||||||
.lalign :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _data_lma = . );
|
|
||||||
} >flash AT>flash :flash
|
|
||||||
|
|
||||||
.dalign :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _data = . );
|
|
||||||
} >ram AT>flash :ram_init
|
|
||||||
|
|
||||||
.data :
|
|
||||||
{
|
|
||||||
__DATA_BEGIN__ = .;
|
|
||||||
*(.data .data.*)
|
|
||||||
*(.gnu.linkonce.d.*)
|
|
||||||
} >ram AT>flash :ram_init
|
|
||||||
|
|
||||||
.sdata :
|
|
||||||
{
|
|
||||||
__SDATA_BEGIN__ = .;
|
|
||||||
*(.sdata .sdata.*)
|
|
||||||
*(.gnu.linkonce.s.*)
|
|
||||||
} >ram AT>flash :ram_init
|
|
||||||
|
|
||||||
.srodata :
|
|
||||||
{
|
|
||||||
*(.srodata.cst16)
|
|
||||||
*(.srodata.cst8)
|
|
||||||
*(.srodata.cst4)
|
|
||||||
*(.srodata.cst2)
|
|
||||||
*(.srodata .srodata.*)
|
|
||||||
} >ram AT>flash :ram_init
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _edata = . );
|
|
||||||
PROVIDE( edata = . );
|
|
||||||
|
|
||||||
PROVIDE( _fbss = . );
|
|
||||||
PROVIDE( __bss_start = . );
|
|
||||||
.bss :
|
|
||||||
{
|
|
||||||
*(.sbss*)
|
|
||||||
*(.gnu.linkonce.sb.*)
|
|
||||||
*(.bss .bss.*)
|
|
||||||
*(.gnu.linkonce.b.*)
|
|
||||||
*(COMMON)
|
|
||||||
. = ALIGN(4);
|
|
||||||
} >ram AT>ram :ram
|
|
||||||
|
|
||||||
. = ALIGN(8);
|
|
||||||
__BSS_END__ = .;
|
|
||||||
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
|
|
||||||
PROVIDE( _end = . );
|
|
||||||
PROVIDE( end = . );
|
|
||||||
|
|
||||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
|
||||||
{
|
|
||||||
PROVIDE( _heap_end = . );
|
|
||||||
. = __stack_size;
|
|
||||||
PROVIDE( _sp = . );
|
|
||||||
} >ram AT>ram :ram
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PROVIDE( tohost = . );
|
|
||||||
PROVIDE( fromhost = . + 8 );
|
|
||||||
}
|
|
||||||
183
env/riscv_vp/init.c
vendored
183
env/riscv_vp/init.c
vendored
@@ -2,18 +2,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "platform.h"
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
extern int main(int argc, char** argv);
|
extern int main(int argc, char** argv);
|
||||||
extern void trap_entry(void);
|
extern void trap_entry(void);
|
||||||
#define IRQ_M_SOFT 3
|
#define IRQ_M_SOFT 3
|
||||||
#define IRQ_M_TIMER 7
|
#define IRQ_M_TIMER 7
|
||||||
#define IRQ_M_EXT 11
|
#define IRQ_M_EXT 11
|
||||||
|
|
||||||
#define NUM_INTERRUPTS 16
|
|
||||||
#define MTIMER_NEXT_TICK_INC 1000
|
|
||||||
|
|
||||||
void handle_m_ext_interrupt(void);
|
void handle_m_ext_interrupt(void);
|
||||||
void handle_m_time_interrupt(void);
|
void handle_m_time_interrupt(void);
|
||||||
@@ -21,118 +17,97 @@ uint32_t handle_trap(uint32_t mcause, uint32_t mepc, uint32_t sp);
|
|||||||
void default_handler(void);
|
void default_handler(void);
|
||||||
void _init(void);
|
void _init(void);
|
||||||
|
|
||||||
typedef void (*my_interrupt_function_ptr_t) (void);
|
typedef void (*my_interrupt_function_ptr_t)(void);
|
||||||
my_interrupt_function_ptr_t localISR[NUM_INTERRUPTS] __attribute__((aligned(64)));
|
my_interrupt_function_ptr_t localISR[NUM_INTERRUPTS] __attribute__((aligned(64)));
|
||||||
|
|
||||||
static unsigned long mtime_lo(void)
|
static unsigned long mtime_lo(void) {
|
||||||
{
|
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
__asm volatile("rdtime %0":"=r"(ret));
|
__asm volatile("rdtime %0" : "=r"(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
|
||||||
#if __riscv_xlen==32
|
static uint32_t mtime_hi(void) {
|
||||||
|
|
||||||
static uint32_t mtime_hi(void)
|
|
||||||
{
|
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
__asm volatile("rdtimeh %0":"=r"(ret));
|
__asm volatile("rdtimeh %0" : "=r"(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t get_timer_value(void)
|
uint64_t get_timer_value(void) {
|
||||||
{
|
while(1) {
|
||||||
while (1) {
|
uint32_t hi = mtime_hi();
|
||||||
uint32_t hi = mtime_hi();
|
uint32_t lo = mtime_lo();
|
||||||
uint32_t lo = mtime_lo();
|
if(hi == mtime_hi())
|
||||||
if (hi == mtime_hi())
|
return ((uint64_t)hi << 32) | lo;
|
||||||
return ((uint64_t)hi << 32) | lo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif __riscv_xlen==64
|
|
||||||
|
|
||||||
uint64_t get_timer_value()
|
|
||||||
{
|
|
||||||
return mtime_lo();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned long get_timer_freq()
|
|
||||||
{
|
|
||||||
return 32768;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long get_cpu_freq()
|
|
||||||
{
|
|
||||||
return 100000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_pll(void){
|
|
||||||
//TODO: implement initialization
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uart_init(size_t baud_rate)
|
|
||||||
{
|
|
||||||
//TODO: implement initialization
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((weak)) handle_m_ext_interrupt(){
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((weak)) handle_m_time_interrupt(){
|
|
||||||
uint64_t time = get_aclint_mtime(aclint);
|
|
||||||
time+=MTIMER_NEXT_TICK_INC;
|
|
||||||
set_aclint_mtimecmp(aclint, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((weak)) default_handler(void) {
|
|
||||||
puts("default handler\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((weak)) interrupt_handler(unsigned) {
|
|
||||||
puts("interrupt handler\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t handle_trap(uint32_t mcause, uint32_t mepc, uint32_t sp){
|
|
||||||
if ((mcause & MCAUSE_INT)) {
|
|
||||||
if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) {
|
|
||||||
handle_m_ext_interrupt();
|
|
||||||
} else if (((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){
|
|
||||||
handle_m_time_interrupt();
|
|
||||||
} else {
|
|
||||||
interrupt_handler(mcause& ~MCAUSE_INT);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
write(1, "trap\n", 5);
|
|
||||||
_exit(1 + mcause);
|
|
||||||
}
|
|
||||||
return mepc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _init()
|
#elif __riscv_xlen == 64
|
||||||
{
|
|
||||||
|
uint64_t get_timer_value() { return mtime_lo(); }
|
||||||
#ifndef NO_INIT
|
|
||||||
init_pll();
|
|
||||||
uart_init(115200);
|
|
||||||
printf("core freq at %lu Hz\n", get_cpu_freq());
|
|
||||||
write_csr(mtvec, &trap_entry);
|
|
||||||
if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present
|
|
||||||
write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping
|
|
||||||
write_csr(fcsr, 0); // initialize rounding mode, undefined at reset
|
|
||||||
}
|
|
||||||
int i=0;
|
|
||||||
while(i<NUM_INTERRUPTS) {
|
|
||||||
localISR[i++] = default_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned long get_timer_freq() { return 32768; }
|
||||||
|
|
||||||
|
unsigned long get_cpu_freq() { return 100000000; }
|
||||||
|
|
||||||
|
void init_pll(void) {
|
||||||
|
// TODO: implement initialization
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fini(void)
|
static void uart_init(size_t baud_rate) {
|
||||||
{
|
// TODO: implement initialization
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __attribute__((weak)) handle_m_ext_interrupt() {}
|
||||||
|
|
||||||
|
void __attribute__((weak)) handle_m_time_interrupt() {
|
||||||
|
uint64_t time = get_aclint_mtime(aclint);
|
||||||
|
time += MTIMER_NEXT_TICK_INC;
|
||||||
|
set_aclint_mtimecmp(aclint, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((weak)) default_handler(void) { puts("default handler\n"); }
|
||||||
|
|
||||||
|
void __attribute__((weak)) interrupt_handler(unsigned) { puts("interrupt handler\n"); }
|
||||||
|
|
||||||
|
uint32_t handle_trap(uint32_t mcause, uint32_t mepc, uint32_t sp) {
|
||||||
|
if((mcause & MCAUSE_INT)) {
|
||||||
|
if((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) {
|
||||||
|
handle_m_ext_interrupt();
|
||||||
|
} else if(((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)) {
|
||||||
|
handle_m_time_interrupt();
|
||||||
|
} else {
|
||||||
|
interrupt_handler(mcause & ~MCAUSE_INT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write(1, "trap\n", 5);
|
||||||
|
_exit(1 + mcause);
|
||||||
|
}
|
||||||
|
return mepc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((weak)) _init() {
|
||||||
|
#ifndef NO_INIT
|
||||||
|
init_pll();
|
||||||
|
uart_init(115200);
|
||||||
|
printf("core freq at %lu Hz\n", get_cpu_freq());
|
||||||
|
write_csr(mtvec, &trap_entry);
|
||||||
|
if(read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present
|
||||||
|
write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping
|
||||||
|
write_csr(fcsr, 0); // initialize rounding mode, undefined at reset
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while(i < NUM_INTERRUPTS) {
|
||||||
|
localISR[i++] = default_handler;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(NUM_HARTS) && NUM_HARTS > 1
|
||||||
|
for(int i = 1; i < NUM_HARTS; ++i)
|
||||||
|
set_aclint_msip(aclint, i, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fini(void) {}
|
||||||
|
|||||||
2
env/riscv_vp/memory_map.ld
vendored
2
env/riscv_vp/memory_map.ld
vendored
@@ -1,7 +1,7 @@
|
|||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
ram (wxa!ri) : ORIGIN = 0x00000000, LENGTH = 128K
|
ram (wxa!ri) : ORIGIN = 0x00000000, LENGTH = 128K
|
||||||
rom (rxai!w) : ORIGIN = 0x1000E000, LENGTH = 2k
|
rom (rxai!w) : ORIGIN = 0x10080000, LENGTH = 8k
|
||||||
flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 16M
|
flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 16M
|
||||||
dram (wxa!ri) : ORIGIN = 0x40000000, LENGTH = 2048M
|
dram (wxa!ri) : ORIGIN = 0x40000000, LENGTH = 2048M
|
||||||
}
|
}
|
||||||
|
|||||||
6
env/riscv_vp/platform.h
vendored
6
env/riscv_vp/platform.h
vendored
@@ -21,10 +21,11 @@
|
|||||||
#include "minres/devices/qspi.h"
|
#include "minres/devices/qspi.h"
|
||||||
#include "minres/devices/timer.h"
|
#include "minres/devices/timer.h"
|
||||||
#include "minres/devices/uart.h"
|
#include "minres/devices/uart.h"
|
||||||
|
#include <riscv/riscv_csr.h>
|
||||||
|
|
||||||
#define PERIPH(TYPE, ADDR) ((volatile TYPE*)(ADDR))
|
#define PERIPH(TYPE, ADDR) ((volatile TYPE*)(ADDR))
|
||||||
// values from memory_map.ld
|
// values from memory_map.ld
|
||||||
#define XIP_START_LOC 0x30000000
|
#define XIP_START_LOC 0x20000000
|
||||||
#define RAM_START_LOC 0x00000000
|
#define RAM_START_LOC 0x00000000
|
||||||
#define APB_BASE 0x10000000
|
#define APB_BASE 0x10000000
|
||||||
|
|
||||||
@@ -41,6 +42,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define NUM_INTERRUPTS 16
|
||||||
|
#define MTIMER_NEXT_TICK_INC 1000
|
||||||
|
|
||||||
void init_pll(void);
|
void init_pll(void);
|
||||||
unsigned long get_cpu_freq(void);
|
unsigned long get_cpu_freq(void);
|
||||||
unsigned long get_timer_freq(void);
|
unsigned long get_timer_freq(void);
|
||||||
|
|||||||
12
env/riscv_vp/ram.lds
vendored
Normal file
12
env/riscv_vp/ram.lds
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
|
||||||
|
ENTRY( _start )
|
||||||
|
|
||||||
|
INCLUDE memory_map.ld
|
||||||
|
|
||||||
|
REGION_ALIAS("REGION_TEXT", ram);
|
||||||
|
REGION_ALIAS("REGION_RODATA", ram);
|
||||||
|
REGION_ALIAS("REGION_DATA", ram);
|
||||||
|
REGION_ALIAS("REGION_BSS", ram);
|
||||||
|
|
||||||
|
INCLUDE sections.ld
|
||||||
175
env/riscv_vp/rom.lds
vendored
175
env/riscv_vp/rom.lds
vendored
@@ -4,174 +4,9 @@ ENTRY( _start )
|
|||||||
|
|
||||||
INCLUDE memory_map.ld
|
INCLUDE memory_map.ld
|
||||||
|
|
||||||
PHDRS
|
REGION_ALIAS("REGION_TEXT", rom);
|
||||||
{
|
REGION_ALIAS("REGION_RODATA", rom);
|
||||||
rom PT_LOAD;
|
REGION_ALIAS("REGION_DATA", ram);
|
||||||
ram_init PT_LOAD;
|
REGION_ALIAS("REGION_BSS", ram);
|
||||||
ram PT_NULL;
|
|
||||||
dram PT_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS
|
INCLUDE sections.ld
|
||||||
{
|
|
||||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
|
||||||
|
|
||||||
.init ORIGIN(rom) :
|
|
||||||
{
|
|
||||||
KEEP (*(SORT_NONE(.init)))
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
*(.text.unlikely .text.unlikely.*)
|
|
||||||
*(.text.startup .text.startup.*)
|
|
||||||
*(.text .text.*)
|
|
||||||
*(.gnu.linkonce.t.*)
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.fini :
|
|
||||||
{
|
|
||||||
KEEP (*(SORT_NONE(.fini)))
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
PROVIDE (__etext = .);
|
|
||||||
PROVIDE (_etext = .);
|
|
||||||
PROVIDE (etext = .);
|
|
||||||
|
|
||||||
.rodata :
|
|
||||||
{
|
|
||||||
*(.rdata)
|
|
||||||
*(.rodata .rodata.*)
|
|
||||||
*(.gnu.linkonce.r.*)
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
|
|
||||||
.preinit_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
|
||||||
KEEP (*(.preinit_array))
|
|
||||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.init_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__init_array_start = .);
|
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
|
||||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
|
||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.fini_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
|
||||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
|
||||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.ctors :
|
|
||||||
{
|
|
||||||
/* gcc uses crtbegin.o to find the start of
|
|
||||||
the constructors, so we make sure it is
|
|
||||||
first. Because this is a wildcard, it
|
|
||||||
doesn't matter if the user does not
|
|
||||||
actually link against crtbegin.o; the
|
|
||||||
linker won't look for a file to match a
|
|
||||||
wildcard. The wildcard also means that it
|
|
||||||
doesn't matter which directory crtbegin.o
|
|
||||||
is in. */
|
|
||||||
KEEP (*crtbegin.o(.ctors))
|
|
||||||
KEEP (*crtbegin?.o(.ctors))
|
|
||||||
/* We don't want to include the .ctor section from
|
|
||||||
the crtend.o file until after the sorted ctors.
|
|
||||||
The .ctor section from the crtend file contains the
|
|
||||||
end of ctors marker and it must be last */
|
|
||||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
|
||||||
KEEP (*(SORT(.ctors.*)))
|
|
||||||
KEEP (*(.ctors))
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.dtors :
|
|
||||||
{
|
|
||||||
KEEP (*crtbegin.o(.dtors))
|
|
||||||
KEEP (*crtbegin?.o(.dtors))
|
|
||||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
|
||||||
KEEP (*(SORT(.dtors.*)))
|
|
||||||
KEEP (*(.dtors))
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.dummy :
|
|
||||||
{
|
|
||||||
*(.comment.*)
|
|
||||||
|
|
||||||
}
|
|
||||||
.lalign :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _data_lma = . );
|
|
||||||
} >rom AT>rom :rom
|
|
||||||
|
|
||||||
.dalign :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _data = . );
|
|
||||||
} >ram AT>rom :ram_init
|
|
||||||
|
|
||||||
.data :
|
|
||||||
{
|
|
||||||
__DATA_BEGIN__ = .;
|
|
||||||
*(.data .data.*)
|
|
||||||
*(.gnu.linkonce.d.*)
|
|
||||||
} >ram AT>rom :ram_init
|
|
||||||
|
|
||||||
.sdata :
|
|
||||||
{
|
|
||||||
__SDATA_BEGIN__ = .;
|
|
||||||
*(.sdata .sdata.*)
|
|
||||||
*(.gnu.linkonce.s.*)
|
|
||||||
} >ram AT>rom :ram_init
|
|
||||||
|
|
||||||
.srodata :
|
|
||||||
{
|
|
||||||
*(.srodata.cst16)
|
|
||||||
*(.srodata.cst8)
|
|
||||||
*(.srodata.cst4)
|
|
||||||
*(.srodata.cst2)
|
|
||||||
*(.srodata .srodata.*)
|
|
||||||
} >ram AT>rom :ram_init
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _edata = . );
|
|
||||||
PROVIDE( edata = . );
|
|
||||||
|
|
||||||
PROVIDE( _fbss = . );
|
|
||||||
PROVIDE( __bss_start = . );
|
|
||||||
.bss :
|
|
||||||
{
|
|
||||||
*(.sbss*)
|
|
||||||
*(.gnu.linkonce.sb.*)
|
|
||||||
*(.bss .bss.*)
|
|
||||||
*(.gnu.linkonce.b.*)
|
|
||||||
*(COMMON)
|
|
||||||
. = ALIGN(4);
|
|
||||||
} >ram AT>ram :ram
|
|
||||||
|
|
||||||
. = ALIGN(8);
|
|
||||||
__BSS_END__ = .;
|
|
||||||
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
|
|
||||||
PROVIDE( _end = . );
|
|
||||||
PROVIDE( end = . );
|
|
||||||
|
|
||||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
|
||||||
{
|
|
||||||
PROVIDE( _heap_end = . );
|
|
||||||
. = __stack_size;
|
|
||||||
PROVIDE( _sp = . );
|
|
||||||
} >ram AT>ram :ram
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PROVIDE( tohost = . );
|
|
||||||
PROVIDE( fromhost = . + 8 );
|
|
||||||
}
|
|
||||||
171
env/riscv_vp/sections.ld
vendored
Normal file
171
env/riscv_vp/sections.ld
vendored
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
flash PT_LOAD;
|
||||||
|
ram_init PT_LOAD;
|
||||||
|
ram PT_NULL;
|
||||||
|
dram PT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
||||||
|
__stack_segment_size = DEFINED(__stack_segment_size) ? __stack_segment_size : __stack_size;
|
||||||
|
.init ORIGIN(REGION_TEXT) :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
} >REGION_TEXT AT>REGION_TEXT :flash
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.unlikely.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text .text.*)
|
||||||
|
*(.gnu.linkonce.t.*)
|
||||||
|
} >REGION_TEXT AT>REGION_TEXT :flash
|
||||||
|
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
} >REGION_TEXT AT>REGION_TEXT :flash
|
||||||
|
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rdata)
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
*(.gnu.linkonce.r.*)
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.srodata :
|
||||||
|
{
|
||||||
|
*(.srodata.cst16)
|
||||||
|
*(.srodata.cst8)
|
||||||
|
*(.srodata.cst4)
|
||||||
|
*(.srodata.cst2)
|
||||||
|
*(.srodata .srodata.*)
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.dummy :
|
||||||
|
{
|
||||||
|
*(.comment.*)
|
||||||
|
|
||||||
|
}
|
||||||
|
.lalign :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
PROVIDE( _data_lma = . );
|
||||||
|
} >REGION_RODATA AT>REGION_RODATA :flash
|
||||||
|
|
||||||
|
.dalign :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
PROVIDE( _data = . );
|
||||||
|
} >REGION_DATA AT>REGION_RODATA :ram_init
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
__DATA_BEGIN__ = .;
|
||||||
|
*(.data .data.*)
|
||||||
|
*(.gnu.linkonce.d.*)
|
||||||
|
} >REGION_DATA AT>REGION_RODATA :ram_init
|
||||||
|
|
||||||
|
.sdata :
|
||||||
|
{
|
||||||
|
__SDATA_BEGIN__ = .;
|
||||||
|
*(.sdata .sdata.*)
|
||||||
|
*(.gnu.linkonce.s.*)
|
||||||
|
} >REGION_DATA AT>REGION_RODATA :ram_init
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
PROVIDE( _edata = . );
|
||||||
|
PROVIDE( edata = . );
|
||||||
|
|
||||||
|
PROVIDE( _fbss = . );
|
||||||
|
PROVIDE( __bss_start = . );
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.sbss*)
|
||||||
|
*(.gnu.linkonce.sb.*)
|
||||||
|
*(.bss .bss.*)
|
||||||
|
*(.gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(4);
|
||||||
|
} >REGION_BSS AT>REGION_BSS :ram
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
__BSS_END__ = .;
|
||||||
|
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
|
||||||
|
PROVIDE( _end = . );
|
||||||
|
PROVIDE( end = . );
|
||||||
|
|
||||||
|
.stack ORIGIN(ram) + LENGTH(ram) - __stack_segment_size :
|
||||||
|
{
|
||||||
|
PROVIDE( _heap_end = . );
|
||||||
|
. = __stack_segment_size;
|
||||||
|
PROVIDE( _sp = . );
|
||||||
|
} >REGION_BSS AT>REGION_BSS :ram
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PROVIDE( tohost = . );
|
||||||
|
PROVIDE( fromhost = . + 8 );
|
||||||
|
}
|
||||||
37
env/start.S
vendored
37
env/start.S
vendored
@@ -9,18 +9,38 @@ _start:
|
|||||||
.option push
|
.option push
|
||||||
.option norelax
|
.option norelax
|
||||||
.option norvc
|
.option norvc
|
||||||
//#ifdef WITH_SIGNATURE
|
#ifdef WITH_SIGNATURE
|
||||||
j 1f
|
j 1f
|
||||||
.2byte 0x4e4d
|
.2byte 0x4e4d
|
||||||
.2byte 0x5352
|
.2byte 0x5352
|
||||||
.4byte 0x669
|
.4byte 0x669
|
||||||
1:
|
1:
|
||||||
//#endif
|
#endif
|
||||||
la gp, __global_pointer$
|
la gp, __global_pointer$
|
||||||
.option pop
|
.option pop
|
||||||
la sp, _sp
|
csrr t0, mhartid // Get hart ID
|
||||||
|
la t1, __stack_size // stack size
|
||||||
|
la sp, _sp // Base stack address
|
||||||
|
/* this loop is to avoid multiplication which is not available on all ISAs */
|
||||||
|
1:
|
||||||
|
beqz t0, 2f
|
||||||
|
sub sp, sp, t1 // Subtract __stack_size to get per-hart stack base
|
||||||
|
addi t0, t0, -1
|
||||||
|
j 1b
|
||||||
|
2:
|
||||||
la t0, trap_entry
|
la t0, trap_entry
|
||||||
csrw mtvec, t0
|
csrw mtvec, t0
|
||||||
|
#if defined(NUM_HARTS) && NUM_HARTS>1
|
||||||
|
/* block other cores until hart 0 has finished initialization */
|
||||||
|
csrr t0, mhartid
|
||||||
|
beqz t0, hart0_init
|
||||||
|
/* enable MSI locally */
|
||||||
|
csrwi mie, 0x8
|
||||||
|
wfi
|
||||||
|
csrw mie, zero
|
||||||
|
j hartx_start
|
||||||
|
hart0_init:
|
||||||
|
#endif
|
||||||
/* Load data section */
|
/* Load data section */
|
||||||
la a0, _data_lma
|
la a0, _data_lma
|
||||||
la a1, _data
|
la a1, _data
|
||||||
@@ -50,6 +70,10 @@ _start:
|
|||||||
call atexit
|
call atexit
|
||||||
call __libc_init_array
|
call __libc_init_array
|
||||||
#endif
|
#endif
|
||||||
|
la a0, mtx
|
||||||
|
li t0, 1
|
||||||
|
sw t0, 0(a0)
|
||||||
|
hartx_start:
|
||||||
#ifndef __riscv_float_abi_soft
|
#ifndef __riscv_float_abi_soft
|
||||||
/* Enable FPU */
|
/* Enable FPU */
|
||||||
li t0, MSTATUS_FS
|
li t0, MSTATUS_FS
|
||||||
@@ -60,9 +84,14 @@ _start:
|
|||||||
fssr x0
|
fssr x0
|
||||||
1:
|
1:
|
||||||
#endif
|
#endif
|
||||||
|
call _init
|
||||||
/* argc = argv = 0 */
|
/* argc = argv = 0 */
|
||||||
li a0, 0
|
li a0, 0
|
||||||
li a1, 0
|
li a1, 0
|
||||||
call main
|
call main
|
||||||
tail _exit
|
tail _exit
|
||||||
|
|
||||||
|
|
||||||
|
.data
|
||||||
|
mtx:
|
||||||
|
.word 0 # 32-bit value
|
||||||
|
|||||||
@@ -1,27 +1,36 @@
|
|||||||
#ifndef _DEVICES_ACLINT_H
|
#ifndef _DEVICES_ACLINT_H
|
||||||
#define _DEVICES_ACLINT_H
|
#define _DEVICES_ACLINT_H
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "gen/aclint.h"
|
#include "gen/aclint.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static void set_aclint_mtime(volatile aclint_t* reg, uint64_t value) {
|
||||||
static void set_aclint_mtime(volatile aclint_t* reg, uint64_t value){
|
|
||||||
set_aclint_mtime_hi(reg, (uint32_t)(value >> 32));
|
set_aclint_mtime_hi(reg, (uint32_t)(value >> 32));
|
||||||
set_aclint_mtime_lo(reg, (uint32_t)value);
|
set_aclint_mtime_lo(reg, (uint32_t)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_aclint_mtime(volatile aclint_t* reg){
|
static uint64_t get_aclint_mtime(volatile aclint_t* reg) {
|
||||||
uint64_t value = ((uint64_t)get_aclint_mtime_hi(reg) << 32) | (uint64_t)get_aclint_mtime_lo(reg);
|
// #if ( __riscv_xlen == 64)
|
||||||
return value;
|
// volatile uint64_t *mtime = (volatile uint64_t *)(RISCV_MTIME_ADDR);
|
||||||
|
// return *mtime;
|
||||||
|
// #else
|
||||||
|
uint32_t mtimeh_val;
|
||||||
|
uint32_t mtimel_val;
|
||||||
|
do {
|
||||||
|
mtimeh_val = get_aclint_mtime_hi(reg);
|
||||||
|
mtimel_val = get_aclint_mtime_lo(reg);
|
||||||
|
} while(mtimeh_val != get_aclint_mtime_hi(reg));
|
||||||
|
return (uint64_t)((((uint64_t)mtimeh_val) << 32) | mtimel_val);
|
||||||
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_aclint_mtimecmp(volatile aclint_t* reg, uint64_t value){
|
static void set_aclint_mtimecmp(volatile aclint_t* reg, uint64_t value) {
|
||||||
set_aclint_mtimecmp0lo(reg, (uint32_t)0xFFFFFFFF);
|
set_aclint_mtimecmp0lo(reg, (uint32_t)0xFFFFFFFF);
|
||||||
set_aclint_mtimecmp0hi(reg, (uint32_t)(value >> 32));
|
set_aclint_mtimecmp0hi(reg, (uint32_t)(value >> 32));
|
||||||
set_aclint_mtimecmp0lo(reg, (uint32_t)value);
|
set_aclint_mtimecmp0lo(reg, (uint32_t)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_aclint_mtimecmp(volatile aclint_t* reg){
|
static uint64_t get_aclint_mtimecmp(volatile aclint_t* reg) {
|
||||||
uint64_t value = ((uint64_t)get_aclint_mtimecmp0hi(reg) << 32) | (uint64_t)get_aclint_mtimecmp0lo(reg);
|
uint64_t value = ((uint64_t)get_aclint_mtimecmp0hi(reg) << 32) | (uint64_t)get_aclint_mtimecmp0lo(reg);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,26 +13,26 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile uint32_t MSIP0;
|
volatile uint32_t MSIP[4096];
|
||||||
uint8_t fill0[16380];
|
struct {
|
||||||
volatile uint32_t MTIMECMP0LO;
|
volatile uint32_t LO;
|
||||||
volatile uint32_t MTIMECMP0HI;
|
volatile uint32_t HI;
|
||||||
uint8_t fill1[32752];
|
} MTIMECMP[4095];
|
||||||
volatile uint32_t MTIME_LO;
|
volatile uint32_t MTIME_LO;
|
||||||
volatile uint32_t MTIME_HI;
|
volatile uint32_t MTIME_HI;
|
||||||
} aclint_t;
|
} aclint_t;
|
||||||
|
|
||||||
#define ACLINT_MSIP0_OFFS 0
|
#define ACLINT_MSIP_OFFS 0
|
||||||
#define ACLINT_MSIP0_MASK 0x1
|
#define ACLINT_MSIP_MASK 0x1
|
||||||
#define ACLINT_MSIP0(V) ((V & ACLINT_MSIP0_MASK) << ACLINT_MSIP0_OFFS)
|
#define ACLINT_MSIP(V) ((V & ACLINT_MSIP0_MASK) << ACLINT_MSIP0_OFFS)
|
||||||
|
|
||||||
#define ACLINT_MTIMECMP0LO_OFFS 0
|
#define ACLINT_MTIMECMPLO_OFFS 0
|
||||||
#define ACLINT_MTIMECMP0LO_MASK 0xffffffff
|
#define ACLINT_MTIMECMPLO_MASK 0xffffffff
|
||||||
#define ACLINT_MTIMECMP0LO(V) ((V & ACLINT_MTIMECMP0LO_MASK) << ACLINT_MTIMECMP0LO_OFFS)
|
#define ACLINT_MTIMECMPLO(V) ((V & ACLINT_MTIMECMP0LO_MASK) << ACLINT_MTIMECMP0LO_OFFS)
|
||||||
|
|
||||||
#define ACLINT_MTIMECMP0HI_OFFS 0
|
#define ACLINT_MTIMECMPHI_OFFS 0
|
||||||
#define ACLINT_MTIMECMP0HI_MASK 0xffffffff
|
#define ACLINT_MTIMECMPHI_MASK 0xffffffff
|
||||||
#define ACLINT_MTIMECMP0HI(V) ((V & ACLINT_MTIMECMP0HI_MASK) << ACLINT_MTIMECMP0HI_OFFS)
|
#define ACLINT_MTIMECMPHI(V) ((V & ACLINT_MTIMECMP0HI_MASK) << ACLINT_MTIMECMP0HI_OFFS)
|
||||||
|
|
||||||
#define ACLINT_MTIME_LO_OFFS 0
|
#define ACLINT_MTIME_LO_OFFS 0
|
||||||
#define ACLINT_MTIME_LO_MASK 0xffffffff
|
#define ACLINT_MTIME_LO_MASK 0xffffffff
|
||||||
@@ -43,33 +43,55 @@ typedef struct {
|
|||||||
#define ACLINT_MTIME_HI(V) ((V & ACLINT_MTIME_HI_MASK) << ACLINT_MTIME_HI_OFFS)
|
#define ACLINT_MTIME_HI(V) ((V & ACLINT_MTIME_HI_MASK) << ACLINT_MTIME_HI_OFFS)
|
||||||
|
|
||||||
// ACLINT_MSIP0
|
// ACLINT_MSIP0
|
||||||
static inline uint32_t get_aclint_msip0(volatile aclint_t* reg) { return reg->MSIP0; }
|
static inline uint32_t get_aclint_msip0(volatile aclint_t* reg) { return reg->MSIP[0]; }
|
||||||
static inline void set_aclint_msip0(volatile aclint_t* reg, uint32_t value) { reg->MSIP0 = value; }
|
static inline void set_aclint_msip0(volatile aclint_t* reg, uint32_t value) { reg->MSIP[0] = value; }
|
||||||
static inline uint32_t get_aclint_msip0_msip(volatile aclint_t* reg) { return (reg->MSIP0 >> 0) & 0x1; }
|
static inline uint32_t get_aclint_msip0_msip(volatile aclint_t* reg) { return (reg->MSIP[0] >> 0) & 0x1; }
|
||||||
static inline void set_aclint_msip0_msip(volatile aclint_t* reg, uint8_t value) { reg->MSIP0 = (reg->MSIP0 & ~(0x1U << 0)) | (value << 0); }
|
static inline void set_aclint_msip0_msip(volatile aclint_t* reg, uint8_t value) {
|
||||||
|
reg->MSIP[0] = (reg->MSIP[0] & ~(0x1U << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLINT_MSIP
|
||||||
|
static inline uint32_t get_aclint_msip(volatile aclint_t* reg, unsigned idx) { return reg->MSIP[idx]; }
|
||||||
|
static inline void set_aclint_msip(volatile aclint_t* reg, unsigned idx, uint32_t value) { reg->MSIP[idx] = value; }
|
||||||
|
static inline uint32_t get_aclint_msip_msip(volatile aclint_t* reg, unsigned idx) { return (reg->MSIP[idx] >> 0) & 0x1; }
|
||||||
|
static inline void set_aclint_msip_msip(volatile aclint_t* reg, unsigned idx, uint8_t value) {
|
||||||
|
reg->MSIP[idx] = (reg->MSIP[idx] & ~(0x1U << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
|
||||||
// ACLINT_MTIMECMP0LO
|
// ACLINT_MTIMECMP0LO
|
||||||
static inline uint32_t get_aclint_mtimecmp0lo(volatile aclint_t* reg) { return (reg->MTIMECMP0LO >> 0) & 0xffffffff; }
|
static inline uint32_t get_aclint_mtimecmp0lo(volatile aclint_t* reg) { return (reg->MTIMECMP[0].LO >> 0) & 0xffffffff; }
|
||||||
static inline void set_aclint_mtimecmp0lo(volatile aclint_t* reg, uint32_t value) {
|
static inline void set_aclint_mtimecmp0lo(volatile aclint_t* reg, uint32_t value) {
|
||||||
reg->MTIMECMP0LO = (reg->MTIMECMP0LO & ~(0xffffffffU << 0)) | (value << 0);
|
reg->MTIMECMP[0].LO = (reg->MTIMECMP[0].LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLINT_MTIMECMPxLO
|
||||||
|
static inline uint32_t get_aclint_mtimecmplo(volatile aclint_t* reg, unsigned idx) { return (reg->MTIMECMP[idx].LO >> 0) & 0xffffffff; }
|
||||||
|
static inline void set_aclint_mtimecmplo(volatile aclint_t* reg, unsigned idx, uint32_t value) {
|
||||||
|
reg->MTIMECMP[idx].LO = (reg->MTIMECMP[idx].LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACLINT_MTIMECMP0HI
|
// ACLINT_MTIMECMP0HI
|
||||||
static inline uint32_t get_aclint_mtimecmp0hi(volatile aclint_t* reg) { return (reg->MTIMECMP0HI >> 0) & 0xffffffff; }
|
static inline uint32_t get_aclint_mtimecmp0hi(volatile aclint_t* reg) { return (reg->MTIMECMP[0].HI >> 0) & 0xffffffff; }
|
||||||
static inline void set_aclint_mtimecmp0hi(volatile aclint_t* reg, uint32_t value) {
|
static inline void set_aclint_mtimecmp0hi(volatile aclint_t* reg, uint32_t value) {
|
||||||
reg->MTIMECMP0HI = (reg->MTIMECMP0HI & ~(0xffffffffU << 0)) | (value << 0);
|
reg->MTIMECMP[0].HI = (reg->MTIMECMP[0].HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLINT_MTIMECMPxHI
|
||||||
|
static inline uint32_t get_aclint_mtimecmphi(volatile aclint_t* reg, unsigned idx) { return (reg->MTIMECMP[idx].HI >> 0) & 0xffffffff; }
|
||||||
|
static inline void set_aclint_mtimecmphi(volatile aclint_t* reg, unsigned idx, uint32_t value) {
|
||||||
|
reg->MTIMECMP[idx].HI = (reg->MTIMECMP[idx].HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACLINT_MTIME_LO
|
// ACLINT_MTIME_LO
|
||||||
static inline uint32_t get_aclint_mtime_lo(volatile aclint_t* reg) { return (reg->MTIME_LO >> 0) & 0xffffffff; }
|
static inline uint32_t get_aclint_mtime_lo(volatile aclint_t* reg) { return (reg->MTIME_LO >> 0) & 0xffffffff; }
|
||||||
static inline void set_aclint_mtime_lo(volatile aclint_t* reg, uint32_t value) {
|
static inline void set_aclint_mtime_lo(volatile aclint_t* reg, uint32_t value) {
|
||||||
reg->MTIME_LO = (reg->MTIME_LO & ~(0xffffffffU << 0)) | (value << 0);
|
reg->MTIME_LO = (reg->MTIME_LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACLINT_MTIME_HI
|
// ACLINT_MTIME_HI
|
||||||
static inline uint32_t get_aclint_mtime_hi(volatile aclint_t* reg) { return (reg->MTIME_HI >> 0) & 0xffffffff; }
|
static inline uint32_t get_aclint_mtime_hi(volatile aclint_t* reg) { return (reg->MTIME_HI >> 0) & 0xffffffff; }
|
||||||
static inline void set_aclint_mtime_hi(volatile aclint_t* reg, uint32_t value) {
|
static inline void set_aclint_mtime_hi(volatile aclint_t* reg, uint32_t value) {
|
||||||
reg->MTIME_HI = (reg->MTIME_HI & ~(0xffffffffU << 0)) | (value << 0);
|
reg->MTIME_HI = (reg->MTIME_HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _BSP_ACLINT_H */
|
#endif /* _BSP_ACLINT_H */
|
||||||
|
|||||||
3790
include/riscv/riscv_csr.h
Normal file
3790
include/riscv/riscv_csr.h
Normal file
File diff suppressed because it is too large
Load Diff
13609
include/riscv/riscv_csr.hpp
Normal file
13609
include/riscv/riscv_csr.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
extern ssize_t _bsp_write(int, const void*, size_t);
|
extern ssize_t _bsp_write(int, const void*, size_t);
|
||||||
|
|
||||||
int __wrap_puts(const char* s) {
|
int __wrap_puts(const char* s) {
|
||||||
const char* str = s;
|
if(!s) return -1;
|
||||||
while(*str)
|
const char* str = s;
|
||||||
str++;
|
while(*str)
|
||||||
return _bsp_write(STDOUT_FILENO, s, str - s);
|
++str;
|
||||||
|
*(char*)str='\n';
|
||||||
|
return _bsp_write(STDOUT_FILENO, s, (str - s)+1);
|
||||||
}
|
}
|
||||||
weak_under_alias(puts);
|
weak_under_alias(puts);
|
||||||
|
|||||||
Reference in New Issue
Block a user