From 20161cc1afc43992326c62da6bfb91c6167836ef Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 30 Jul 2025 06:35:53 +0200 Subject: [PATCH] adds RISCV-VP platform --- env/riscv_vp/.gitignore | 1 + env/riscv_vp/bsp_read.c | 21 +++++ env/riscv_vp/bsp_write.c | 21 +++++ env/riscv_vp/flash.lds | 177 +++++++++++++++++++++++++++++++++++++ env/riscv_vp/init.c | 138 +++++++++++++++++++++++++++++ env/riscv_vp/memory_map.ld | 7 ++ env/riscv_vp/platform.h | 48 ++++++++++ 7 files changed, 413 insertions(+) create mode 100644 env/riscv_vp/.gitignore create mode 100644 env/riscv_vp/bsp_read.c create mode 100644 env/riscv_vp/bsp_write.c create mode 100644 env/riscv_vp/flash.lds create mode 100644 env/riscv_vp/init.c create mode 100644 env/riscv_vp/memory_map.ld create mode 100644 env/riscv_vp/platform.h diff --git a/env/riscv_vp/.gitignore b/env/riscv_vp/.gitignore new file mode 100644 index 0000000..cc5bb74 --- /dev/null +++ b/env/riscv_vp/.gitignore @@ -0,0 +1 @@ +/*.o diff --git a/env/riscv_vp/bsp_read.c b/env/riscv_vp/bsp_read.c new file mode 100644 index 0000000..68ba715 --- /dev/null +++ b/env/riscv_vp/bsp_read.c @@ -0,0 +1,21 @@ +#include "platform.h" +#include +#include +#include +#include + +ssize_t _bsp_read(int fd, void *ptr, size_t len) { + uint8_t *current = (uint8_t *)ptr; + ssize_t result = 0; + if (isatty(fd)) { + for (current = (uint8_t *)ptr; (current < ((uint8_t *)ptr) + len) && + (get_uart_rx_tx_reg_rx_avail(uart) > 0); + current++) { + *current = uart_read(uart); + result++; + } + + return result; + } + return EOF; +} diff --git a/env/riscv_vp/bsp_write.c b/env/riscv_vp/bsp_write.c new file mode 100644 index 0000000..5e16b4e --- /dev/null +++ b/env/riscv_vp/bsp_write.c @@ -0,0 +1,21 @@ +/* See LICENSE of license details. */ + +#include "platform.h" +#include +#include +#include +#include + +ssize_t _bsp_write(int fd, const void *ptr, size_t len) { + const uint8_t *current = (const uint8_t *)ptr; + if (isatty(fd)) { + for (size_t jj = 0; jj < len; jj++) { + uart_write(uart, current[jj]); + if (current[jj] == '\n') { + uart_write(uart, '\r'); + } + } + return len; + } + return 1; +} diff --git a/env/riscv_vp/flash.lds b/env/riscv_vp/flash.lds new file mode 100644 index 0000000..9209015 --- /dev/null +++ b/env/riscv_vp/flash.lds @@ -0,0 +1,177 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +INCLUDE memory_map.ld + +PHDRS +{ + flash PT_LOAD; + ram_init PT_LOAD; + ram PT_NULL; + dram PT_NULL; +} + +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 ); +} diff --git a/env/riscv_vp/init.c b/env/riscv_vp/init.c new file mode 100644 index 0000000..3c830cc --- /dev/null +++ b/env/riscv_vp/init.c @@ -0,0 +1,138 @@ +#include +#include +#include + +#include "platform.h" +#include "encoding.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 + +void handle_m_ext_interrupt(void); +void handle_m_time_interrupt(void); +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); +my_interrupt_function_ptr_t localISR[NUM_INTERRUPTS] __attribute__((aligned(64))); + +static unsigned long mtime_lo(void) +{ + unsigned long ret; + __asm volatile("rdtime %0":"=r"(ret)); + return ret; +} + + +#if __riscv_xlen==32 + +static uint32_t mtime_hi(void) +{ + unsigned long 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); + } + } 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 + +void init_pll(void); +unsigned long get_cpu_freq(void); +unsigned long get_timer_freq(void); + +#endif /* _ISS_PLATFORM_H */