Compare commits

...

11 Commits

14 changed files with 17751 additions and 480 deletions

View File

@@ -2,8 +2,10 @@ cmake_minimum_required(VERSION 3.21)
include(CheckLinkerFlag)
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"
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"
CACHE FILEPATH "Path to the BSP startup assembly file")
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_library(bsp STATIC env/${BOARD}/init.c)
target_link_libraries(bsp PUBLIC startup wrap)
target_include_directories(bsp PUBLIC env/${BOARD})
add_library(runtime STATIC env/${BOARD}/init.c)
target_include_directories(runtime PUBLIC env/${BOARD} env include)
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)
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()
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)
target_include_directories(bsp INTERFACE include)
target_sources(bsp INTERFACE env/semihosting.c env/trap.c)
target_sources(runtime INTERFACE env/semihosting.c env/trap.c)
endif()
add_library(bsp INTERFACE)
target_link_libraries(bsp INTERFACE startup runtime wrap)

16
env/entry.S vendored
View File

@@ -10,12 +10,13 @@
.align 2
.global 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 x2, 2*REGBYTES(sp)
sw x3, 3*REGBYTES(sp)
sw x4, 4*REGBYTES(sp)
sw x5, 5*REGBYTES(sp)
sw x6, 6*REGBYTES(sp)
sw x7, 7*REGBYTES(sp)
@@ -53,9 +54,6 @@ trap_entry:
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 x6, 6*REGBYTES(sp)
lw x7, 7*REGBYTES(sp)
@@ -84,6 +82,9 @@ trap_entry:
lw x29, 29*REGBYTES(sp)
lw x30, 30*REGBYTES(sp)
lw x31, 31*REGBYTES(sp)
addi sp, sp, 28*REGBYTES
#else
addi sp, sp, 12*REGBYTES
#endif
mret
@@ -91,5 +92,4 @@ trap_entry:
handle_trap:
1:
j 1b
#endif

175
env/riscv_vp/flash.lds vendored
View File

@@ -4,174 +4,9 @@ ENTRY( _start )
INCLUDE memory_map.ld
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
dram PT_NULL;
}
REGION_ALIAS("REGION_TEXT", flash);
REGION_ALIAS("REGION_RODATA", flash);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
SECTIONS
{
__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 );
}
INCLUDE sections.ld

180
env/riscv_vp/init.c vendored
View File

@@ -2,18 +2,14 @@
#include <stdio.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
#include "platform.h"
extern int main(int argc, char** argv);
extern void trap_entry(void);
#define IRQ_M_SOFT 3
#define IRQ_M_TIMER 7
#define IRQ_M_EXT 11
#define NUM_INTERRUPTS 16
#define MTIMER_NEXT_TICK_INC 1000
#define IRQ_M_SOFT 3
#define IRQ_M_TIMER 7
#define IRQ_M_EXT 11
void handle_m_ext_interrupt(void);
void handle_m_time_interrupt(void);
@@ -21,118 +17,94 @@ uint32_t handle_trap(uint32_t mcause, uint32_t mepc, uint32_t sp);
void default_handler(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)));
static unsigned long mtime_lo(void)
{
static unsigned long mtime_lo(void) {
unsigned long ret;
__asm volatile("rdtime %0":"=r"(ret));
__asm volatile("rdtime %0" : "=r"(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;
__asm volatile("rdtimeh %0":"=r"(ret));
__asm volatile("rdtimeh %0" : "=r"(ret));
return ret;
}
uint64_t get_timer_value(void)
{
while (1) {
uint32_t hi = mtime_hi();
uint32_t lo = mtime_lo();
if (hi == mtime_hi())
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);
uint64_t get_timer_value(void) {
while(1) {
uint32_t hi = mtime_hi();
uint32_t lo = mtime_lo();
if(hi == mtime_hi())
return ((uint64_t)hi << 32) | lo;
}
} else {
write(1, "trap\n", 5);
_exit(1 + mcause);
}
return mepc;
}
void _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;
}
#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
}
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
}
void _fini(void) {}

View File

@@ -1,7 +1,7 @@
MEMORY
{
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
dram (wxa!ri) : ORIGIN = 0x40000000, LENGTH = 2048M
}

View File

@@ -21,10 +21,11 @@
#include "minres/devices/qspi.h"
#include "minres/devices/timer.h"
#include "minres/devices/uart.h"
#include <riscv/riscv_csr.h>
#define PERIPH(TYPE, ADDR) ((volatile TYPE*)(ADDR))
// values from memory_map.ld
#define XIP_START_LOC 0x30000000
#define XIP_START_LOC 0x20000000
#define RAM_START_LOC 0x00000000
#define APB_BASE 0x10000000
@@ -41,6 +42,9 @@
#include <stdint.h>
#define NUM_INTERRUPTS 16
#define MTIMER_NEXT_TICK_INC 1000
void init_pll(void);
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);

12
env/riscv_vp/ram.lds vendored Normal file
View 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
View File

@@ -4,174 +4,9 @@ ENTRY( _start )
INCLUDE memory_map.ld
PHDRS
{
rom PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
dram PT_NULL;
}
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_RODATA", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
SECTIONS
{
__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 );
}
INCLUDE sections.ld

171
env/riscv_vp/sections.ld vendored Normal file
View 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 );
}

34
env/start.S vendored
View File

@@ -9,18 +9,35 @@ _start:
.option push
.option norelax
.option norvc
//#ifdef WITH_SIGNATURE
#ifdef WITH_SIGNATURE
j 1f
.2byte 0x4e4d
.2byte 0x5352
.4byte 0x669
1:
//#endif
#endif
la gp, __global_pointer$
.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
csrw mtvec, t0
#ifdef HARTX_WAIT4WFI
/* block other cores until hart 0 has finished initialization */
csrr t0, mhartid
beqz t0, hart0_init
wfi
j hartx_start
hart0_init:
#endif
/* Load data section */
la a0, _data_lma
la a1, _data
@@ -50,6 +67,10 @@ _start:
call atexit
call __libc_init_array
#endif
la a0, mtx
li t0, 1
sw t0, 0(a0)
hartx_start:
#ifndef __riscv_float_abi_soft
/* Enable FPU */
li t0, MSTATUS_FS
@@ -60,9 +81,14 @@ _start:
fssr x0
1:
#endif
call _init
/* argc = argv = 0 */
li a0, 0
li a1, 0
call main
tail _exit
.data
mtx:
.word 0 # 32-bit value

View File

@@ -1,27 +1,36 @@
#ifndef _DEVICES_ACLINT_H
#define _DEVICES_ACLINT_H
#include <stdint.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_lo(reg, (uint32_t)value);
}
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);
return value;
static uint64_t get_aclint_mtime(volatile aclint_t* reg) {
// #if ( __riscv_xlen == 64)
// 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_mtimecmp0hi(reg, (uint32_t)(value >> 32));
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);
return value;
}

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

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,12 @@
extern ssize_t _bsp_write(int, const void*, size_t);
int __wrap_puts(const char* s) {
const char* str = s;
while(*str)
str++;
return _bsp_write(STDOUT_FILENO, s, str - s);
int __wrap_puts(const char* s) {
if(!s) return -1;
const char* str = s;
while(*str)
++str;
*(char*)str='\n';
return _bsp_write(STDOUT_FILENO, s, (str - s)+1);
}
weak_under_alias(puts);
weak_under_alias(puts);