From 2fbd3186155779c9512829cf4a6fa10e5de4ff9a Mon Sep 17 00:00:00 2001 From: imi415 Date: Mon, 12 Apr 2021 01:27:48 +0800 Subject: [PATCH] Initial commit. --- .gitmodules | 3 ++ CMakeLists.txt | 84 ++++++++++++++++++++++++++++++++ include/flute_system.h | 13 +++++ include/main.h | 10 ++++ include/soc_peripherals.h | 39 +++++++++++++++ include/system_defs.h | 13 +++++ include/xilinx_gpio.h | 23 +++++++++ include/xilinx_timer.h | 16 ++++++ include/xilinx_uartlite.h | 21 ++++++++ lib/printf | 1 + riscv64-unknown-eabi.cmake | 5 ++ src/drivers/xilinx_gpio.c | 35 ++++++++++++++ src/drivers/xilinx_timer.c | 2 + src/drivers/xilinx_uartlite.c | 27 +++++++++++ src/flute_it.c | 22 +++++++++ src/flute_system.c | 23 +++++++++ src/main.c | 52 ++++++++++++++++++++ src/soc_peripherals.c | 5 ++ src/syscalls.c | 34 +++++++++++++ src/system_init.c | 28 +++++++++++ startup/flute_bram.ld | 91 +++++++++++++++++++++++++++++++++++ startup/startup.S | 90 ++++++++++++++++++++++++++++++++++ 22 files changed, 637 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 include/flute_system.h create mode 100644 include/main.h create mode 100644 include/soc_peripherals.h create mode 100644 include/system_defs.h create mode 100644 include/xilinx_gpio.h create mode 100644 include/xilinx_timer.h create mode 100644 include/xilinx_uartlite.h create mode 160000 lib/printf create mode 100644 riscv64-unknown-eabi.cmake create mode 100644 src/drivers/xilinx_gpio.c create mode 100644 src/drivers/xilinx_timer.c create mode 100644 src/drivers/xilinx_uartlite.c create mode 100644 src/flute_it.c create mode 100644 src/flute_system.c create mode 100644 src/main.c create mode 100644 src/soc_peripherals.c create mode 100644 src/syscalls.c create mode 100644 src/system_init.c create mode 100644 startup/flute_bram.ld create mode 100644 startup/startup.S diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4de5efe --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/printf"] + path = lib/printf + url = https://github.com/mpaland/printf.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..02027d1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,84 @@ +cmake_minimum_required(VERSION 3.10) + +project(Flute_Hello) + +enable_language(CXX) +enable_language(ASM) + +# Device specific settings, goes to CFLAGS and LDFLAGS +set(CFLAGS_HARDWARE "-mabi=lp64 -march=rv64imac") + +# Extra CFlags +set(CFLAGS_EXTRA "-Og") +set(LDFLAGS_EXTRA "-Wl,--print-memory-usage") + +# Different linker scripts +set(LDSCRIPT_BRAM "${CMAKE_SOURCE_DIR}/startup/flute_bram.ld") + +# Copy them from Makefile +set(C_SOURCES + "src/main.c" + "src/flute_system.c" + "src/flute_it.c" + "src/soc_peripherals.c" + "src/syscalls.c" + "src/system_init.c" + "src/drivers/xilinx_gpio.c" + "src/drivers/xilinx_timer.c" + "src/drivers/xilinx_uartlite.c" + "lib/printf/printf.c" +) + +# Copy them from Makefile +set(ASM_SOURCES + "startup/startup.S" +) + +# Copy them from Makefile +add_definitions( +) + +# Copy them from Makefile +include_directories( + "include" + "lib/printf" +) + +# Final compiler flags +set(CMAKE_C_FLAGS "${CFLAGS_HARDWARE} ${CFLAGS_EXTRA} -Wall -fdata-sections -ffunction-sections") +set(CMAKE_CXX_FLAGS "${CFLAGS_HARDWARE} ${CFLAGS_EXTRA} -Wall -fdata-sections -ffunction-sections") +set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp") +set(CMAKE_EXE_LINKER_FLAGS "${CFLAGS_HARDWARE} -Wl,--gc-sections -specs=nano.specs -nostartfiles -lc -lm -lnosys ${LDFLAGS_EXTRA}") + +# Main targets are added here + +# **** Internal BRAM **** + +# Create ELF +add_executable("${CMAKE_PROJECT_NAME}_BRAM.elf" ${C_SOURCES} ${ASM_SOURCES}) + +target_link_options("${CMAKE_PROJECT_NAME}_BRAM.elf" + PRIVATE "-T${LDSCRIPT_BRAM}" + PRIVATE "-Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}_BRAM.map,--cref" +) + +target_compile_options("${CMAKE_PROJECT_NAME}_BRAM.elf" + PRIVATE "${FINAL_C_FLAGS}" +) + +add_custom_command(OUTPUT "${CMAKE_PROJECT_NAME}_BRAM.hex" + COMMAND ${CMAKE_OBJCOPY} "-O" "ihex" "${CMAKE_PROJECT_NAME}_BRAM.elf" "${CMAKE_PROJECT_NAME}_BRAM.hex" + DEPENDS "${CMAKE_PROJECT_NAME}_BRAM.elf" +) +add_custom_target("${CMAKE_PROJECT_NAME}_BRAM_HEX" + DEPENDS "${CMAKE_PROJECT_NAME}_BRAM.hex" +) + +add_custom_command(OUTPUT "${CMAKE_PROJECT_NAME}_BRAM.bin" + COMMAND ${CMAKE_OBJCOPY} "-O" "binary" "${CMAKE_PROJECT_NAME}_BRAM.elf" "${CMAKE_PROJECT_NAME}_BRAM.bin" + DEPENDS "${CMAKE_PROJECT_NAME}_BRAM.elf" +) + +add_custom_target("${CMAKE_PROJECT_NAME}_BRAM_BIN" + DEPENDS "${CMAKE_PROJECT_NAME}_BRAM.bin" +) \ No newline at end of file diff --git a/include/flute_system.h b/include/flute_system.h new file mode 100644 index 0000000..cb296c1 --- /dev/null +++ b/include/flute_system.h @@ -0,0 +1,13 @@ +#ifndef __IBEX_SYSTEM_H +#define __IBEX_SYSTEM_H + +#include + +#define __csrr(csr, val) asm volatile("csrr %0, " csr "\n" : "=r"(val)) +#define __csrw(csr, val) asm volatile("csrw " csr ", %0\n" : : "r"(val)) +#define __csrs(csr, val) asm volatile("csrs " csr ", %0\n" : : "r"(val)) +#define __csrc(csr, val) asm volatile("csrc " csr ", %0\n" : : "r"(val)) + +void System_Delay(uint64_t ticks); + +#endif \ No newline at end of file diff --git a/include/main.h b/include/main.h new file mode 100644 index 0000000..a8d3c6e --- /dev/null +++ b/include/main.h @@ -0,0 +1,10 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#include "flute_system.h" +#include "soc_peripherals.h" + +extern xilinx_uartlite_handle_t soc_uart; +extern xilinx_gpio_handle_t soc_gpio; + +#endif \ No newline at end of file diff --git a/include/soc_peripherals.h b/include/soc_peripherals.h new file mode 100644 index 0000000..05923ec --- /dev/null +++ b/include/soc_peripherals.h @@ -0,0 +1,39 @@ +#ifndef __SOC_PERIPHERALS_H +#define __SOC_PERIPHERALS_H + +#include "xilinx_uartlite.h" +#include "xilinx_gpio.h" +#include "xilinx_timer.h" + +#include "flute_system.h" + +// Peripheral defines +#define UART0_BASE 0x40000000 +#define GPIO0_BASE 0x40010000 +#define TIMER0_BASE 0x40020000 + +#define CLINT_BASE 0x02000000 + +// SoC config +#define SYS_CLK_FREQ 32000000 +#define SYS_TICK_RATE 1000 + +#define SYS_TICK_STEP (SYS_CLK_FREQ / SYS_TICK_RATE) + +// Peripherals +extern __IO xilinx_uartlite_t *UART0; +extern __IO xilinx_gpio_t *GPIO0; +extern __IO xilinx_timer_t *TIMER0; + +// SysTick +extern volatile uint64_t SysTick; + +static inline uint32_t GetTick() { + return SysTick; +} + +static inline uint32_t GetCoreClock() { + return SYS_CLK_FREQ; +} + +#endif \ No newline at end of file diff --git a/include/system_defs.h b/include/system_defs.h new file mode 100644 index 0000000..aba2e10 --- /dev/null +++ b/include/system_defs.h @@ -0,0 +1,13 @@ +#ifndef __XILINX_IP_DEFS_H +#define __XILINX_IP_DEFS_H + +#include + +#define __IO volatile + +#define RET_OK 0 +#define RET_ERR 1 + +typedef int sys_ret_t; + +#endif \ No newline at end of file diff --git a/include/xilinx_gpio.h b/include/xilinx_gpio.h new file mode 100644 index 0000000..409fd7c --- /dev/null +++ b/include/xilinx_gpio.h @@ -0,0 +1,23 @@ +#ifndef __XILINX_GPIO_H +#define __XILINX_GPIO_H + +#include "system_defs.h" + +typedef struct { + __IO uint32_t DATA; + __IO uint32_t TRI; + __IO uint32_t DATA2; + __IO uint32_t TRI2; +} xilinx_gpio_t; + +typedef struct { + __IO xilinx_gpio_t *instance; +} xilinx_gpio_handle_t; + +sys_ret_t xilinx_gpio_init(xilinx_gpio_handle_t *handle); +sys_ret_t xilinx_gpio_pinmode(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t output); +sys_ret_t xilinx_gpio_write(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t value); +uint8_t xilinx_gpio_read(xilinx_gpio_handle_t *handle, uint32_t pin); +sys_ret_t xilinx_gpio_toggle(xilinx_gpio_handle_t *handle, uint32_t pin); + +#endif \ No newline at end of file diff --git a/include/xilinx_timer.h b/include/xilinx_timer.h new file mode 100644 index 0000000..306b1e0 --- /dev/null +++ b/include/xilinx_timer.h @@ -0,0 +1,16 @@ +#ifndef __XILINX_TIMER_H +#define __XILINX_TIMER_H + +#include "system_defs.h" + +typedef struct { + __IO uint32_t TCSR0; + __IO uint32_t TLR0; + __IO uint32_t TCR0; + __IO uint32_t RSVD; + __IO uint32_t TCSR1; + __IO uint32_t TLR1; + __IO uint32_t TCR1; +} xilinx_timer_t; + +#endif \ No newline at end of file diff --git a/include/xilinx_uartlite.h b/include/xilinx_uartlite.h new file mode 100644 index 0000000..d525261 --- /dev/null +++ b/include/xilinx_uartlite.h @@ -0,0 +1,21 @@ +#ifndef __XILINX_UARTLITE_H +#define __XILINX_UARTLITE_H + +#include "system_defs.h" + +typedef struct { + __IO uint32_t RX_FIFO; + __IO uint32_t TX_FIFO; + __IO uint32_t STAT; + __IO uint32_t CTRL; +} xilinx_uartlite_t; + +typedef struct { + __IO xilinx_uartlite_t *instance; +} xilinx_uartlite_handle_t; + +sys_ret_t xilinx_uartlite_init(xilinx_uartlite_handle_t *handle); +sys_ret_t xilinx_uartlite_send(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len); +sys_ret_t xilinx_uartlite_receive(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len); + +#endif \ No newline at end of file diff --git a/lib/printf b/lib/printf new file mode 160000 index 0000000..d3b9846 --- /dev/null +++ b/lib/printf @@ -0,0 +1 @@ +Subproject commit d3b984684bb8a8bdc48cc7a1abecb93ce59bbe3e diff --git a/riscv64-unknown-eabi.cmake b/riscv64-unknown-eabi.cmake new file mode 100644 index 0000000..94bcd7c --- /dev/null +++ b/riscv64-unknown-eabi.cmake @@ -0,0 +1,5 @@ +set(CMAKE_C_COMPILER $ENV{TOOLCHAIN_PATH}/riscv64-unknown-elf-gcc) +set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN_PATH}/riscv64-unknown-elf-gcc) + +# Make CMake happy about those compilers +set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") diff --git a/src/drivers/xilinx_gpio.c b/src/drivers/xilinx_gpio.c new file mode 100644 index 0000000..0fec481 --- /dev/null +++ b/src/drivers/xilinx_gpio.c @@ -0,0 +1,35 @@ +#include "xilinx_gpio.h" + +sys_ret_t xilinx_gpio_init(xilinx_gpio_handle_t *handle) { + handle->instance->TRI = 0xFFFFFFFF; + return RET_OK; +} + +sys_ret_t xilinx_gpio_pinmode(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t output) { + if(output) { + handle->instance->TRI &= ~(1U << pin); + } + else { + handle->instance->TRI |= (1U << pin); + } + return RET_OK; +} + +sys_ret_t xilinx_gpio_write(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t value) { + if(value) { + handle->instance->DATA |= (1U << pin); + } + else { + handle->instance->DATA &= ~(1U << pin); + } + return RET_OK; +} + +uint8_t xilinx_gpio_read(xilinx_gpio_handle_t *handle, uint32_t pin) { + return (handle->instance->DATA & (1U << pin)) ? 1 : 0; +} + +sys_ret_t xilinx_gpio_toggle(xilinx_gpio_handle_t *handle, uint32_t pin) { + handle->instance->DATA ^= (1U << pin); + return RET_OK; +} \ No newline at end of file diff --git a/src/drivers/xilinx_timer.c b/src/drivers/xilinx_timer.c new file mode 100644 index 0000000..4ec13a3 --- /dev/null +++ b/src/drivers/xilinx_timer.c @@ -0,0 +1,2 @@ +#include "xilinx_timer.h" + diff --git a/src/drivers/xilinx_uartlite.c b/src/drivers/xilinx_uartlite.c new file mode 100644 index 0000000..396a961 --- /dev/null +++ b/src/drivers/xilinx_uartlite.c @@ -0,0 +1,27 @@ +#include "xilinx_uartlite.h" + +sys_ret_t xilinx_uartlite_init(xilinx_uartlite_handle_t *handle) { + handle->instance->CTRL |= 0x03; // Reset FIFO + + return RET_OK; +} + +sys_ret_t xilinx_uartlite_send(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len) { + for(uint32_t i = 0; i < len; i++) { + while(handle->instance->STAT & (1U << 0x03) || !(handle->instance->STAT & (1U << 0x02))) { // Check if TX FIFO is full + // TODO: Unless we figure out where systick should be. + } + handle->instance->TX_FIFO = data[i]; + } + return RET_OK; +} + +sys_ret_t xilinx_uartlite_receive(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len) { + for(uint32_t i = 0; i < len; i++) { + while((handle->instance->STAT & 0x01U) == 0) { // Check if RX FIFO is empty + // TODO: Unless we figure out where our systick should be. + } + data[i] = handle->instance->RX_FIFO & 0xFF; + } + return RET_OK; +} \ No newline at end of file diff --git a/src/flute_it.c b/src/flute_it.c new file mode 100644 index 0000000..5338a0a --- /dev/null +++ b/src/flute_it.c @@ -0,0 +1,22 @@ +#include "flute_system.h" +#include "soc_peripherals.h" + +void Timer_IRQHandler(void) { + SysTick++; + *(uint64_t *)(CLINT_BASE + 0x4000) = SYS_TICK_STEP; + *(uint64_t *)(CLINT_BASE + 0xBFF8) = 0ULL; +} + +__attribute__((interrupt)) void Exception_Handler(void) { + uint64_t mcause = 0; + + __csrr("mcause", mcause); + + switch(mcause) { + case 0x8000000000000007: // MTIME + Timer_IRQHandler(); + break; + default: + for(;;) {} + } +} \ No newline at end of file diff --git a/src/flute_system.c b/src/flute_system.c new file mode 100644 index 0000000..86969cd --- /dev/null +++ b/src/flute_system.c @@ -0,0 +1,23 @@ +#include "soc_peripherals.h" + +void __enable_irqs(void){ + // +} +void __enable_mcount(void) { + // +} + +void __read_mcycle(void) { + // +} + +void __enable_irqn(int IRQn) { + // +} + +void System_Delay(uint64_t ticks) { + uint64_t tick_start = SysTick; + while(SysTick < tick_start + ticks) { + // + } +} \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d7a1d60 --- /dev/null +++ b/src/main.c @@ -0,0 +1,52 @@ +#include + +#include "printf.h" + +#include "main.h" + +xilinx_uartlite_handle_t soc_uart; +xilinx_gpio_handle_t soc_gpio; + +void _print_arch_string(uint64_t misa); + +int main(int argc, char *argv[]) { + + printf("Running on a Bluespec flute core.\r\n"); + + uint64_t csr = 0; + __csrr("misa", csr); + + printf("MISA: 0x%016llx, this is a ", csr); + _print_arch_string(csr); + printf(" processor.\r\n"); + + printf("System clock frequency: %luHz\r\n", SYS_CLK_FREQ); + + for(;;) { + System_Delay(10000); + __csrr("mcycle", csr); + printf("mcycle: 0x%016llx\r\n", csr); + } + + return 0; +} + +void _print_arch_string(uint64_t misa) { + switch(misa >> 62) { + case 1: + printf("RV32"); + break; + case 2: + printf("RV64"); + break; + case 3: + printf("RV128"); + break; + } + + for(uint8_t i = 0; i < 26; i++) { + if(misa >> i & 0x01ULL) { + printf("%c", 'A' + i); + } + } +} \ No newline at end of file diff --git a/src/soc_peripherals.c b/src/soc_peripherals.c new file mode 100644 index 0000000..654e117 --- /dev/null +++ b/src/soc_peripherals.c @@ -0,0 +1,5 @@ +#include "soc_peripherals.h" + +__IO xilinx_uartlite_t *UART0 = (xilinx_uartlite_t *) UART0_BASE; +__IO xilinx_gpio_t *GPIO0 = (xilinx_gpio_t *) GPIO0_BASE; +__IO xilinx_timer_t *TIMER0 = (xilinx_timer_t *) TIMER0_BASE; \ No newline at end of file diff --git a/src/syscalls.c b/src/syscalls.c new file mode 100644 index 0000000..04d7a06 --- /dev/null +++ b/src/syscalls.c @@ -0,0 +1,34 @@ +#include +#include + +#include "main.h" + +extern int _heap_start; +extern int _heap_end; +static void *_old_heap = &_heap_start; + +int _write(int handle, char *data, int size) { + handle = handle; + xilinx_uartlite_send(&soc_uart, (uint8_t *)data, size); + return size; +} + +void *_sbrk(int nbytes) { + char *_old = _old_heap; + if(&_heap_start == &_heap_end) { + errno = -ENOMEM; + return (void *)-1; + } + if((_old + nbytes) < (char *)&_heap_end) { + _old += nbytes; + } else { + errno = -ENOMEM; + return (void *)-1; + } + + return _old_heap; +} + +void _putchar(char character) { + xilinx_uartlite_send(&soc_uart, (uint8_t *)&character, 0x01); +} \ No newline at end of file diff --git a/src/system_init.c b/src/system_init.c new file mode 100644 index 0000000..a9388f4 --- /dev/null +++ b/src/system_init.c @@ -0,0 +1,28 @@ +#include "main.h" + +__IO uint64_t SysTick; + +void System_Init(void) { + soc_uart.instance = UART0; + xilinx_uartlite_init(&soc_uart); + + soc_gpio.instance = GPIO0; + xilinx_gpio_init(&soc_gpio); + + xilinx_gpio_pinmode(&soc_gpio, 0, 1); + + // Setup interrupt system + uint64_t csr = 0ULL; + __csrw("mtvec", csr); + + SysTick = 0ULL; + + *(uint64_t *)(CLINT_BASE + 0x4000) = SYS_TICK_STEP; + *(uint64_t *)(CLINT_BASE + 0xBFF8) = 0ULL; + + csr = 1U << 7; // MTIE + __csrw("mie", csr); // Enable timer interrupt + + csr = 1U << 3; // MIE + __csrw("mstatus", csr); +} diff --git a/startup/flute_bram.ld b/startup/flute_bram.ld new file mode 100644 index 0000000..18d41d0 --- /dev/null +++ b/startup/flute_bram.ld @@ -0,0 +1,91 @@ +_entry_point = 0x1000; + +ENTRY(_entry_point) + +_estack = 0x00020000; +_minimum_stack_size = 0x1000; +_minimum_heap_size = 0x1000; + +MEMORY +{ + RO_CODE (rx) : ORIGIN = 0x00000000, LENGTH = 64K + RW_DATA (xrw) : ORIGIN = 0x00010000, LENGTH = 64K +} + +SECTIONS +{ + .isr_vectors : + { + . = ALIGN(8); + _vectors_start = .; + KEEP(*(.isr_vectors)) + _vectors_end = .; + . = ALIGN(8); + } >RO_CODE + + .text : + { + . = ALIGN(8); + *(.text) + *(.text*) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(8); + } >RO_CODE + + .data : + { + . = ALIGN(8); + _sdata = .; + __global_pointer$ = . + 0x800; + *(.data) + *(.data*) + *(.sdata) + *(.sdata*) + . = ALIGN(8); + _edata = .; + } >RW_DATA AT> RO_CODE + + _sidata = LOADADDR(.data); + + + .rodata : + { + . = ALIGN(8); + *(.rodata) + *(.rodata*) + . = ALIGN(8); + } >RO_CODE + + .bss : + { + . = ALIGN(8); + _sbss = .; + _bss_start = _sbss; + *(.bss) + *(.bss*) + *(.sbss) + *(.sbss*) + *(COMMON) + . = ALIGN(8); + _ebss = .; + _bss_end = _ebss; + } >RW_DATA + + ._heap_stack_space : + { + . = ALIGN(8); + _heap_start = .; + . = . + _minimum_heap_size; + _heap_end = .; + _end = .; + . = ALIGN(8); + . = . + _minimum_stack_size; + . = ALIGN(8); + } >RW_DATA + + .riscv.attributes 0 : + { + *(.riscv.attributes) + } +} \ No newline at end of file diff --git a/startup/startup.S b/startup/startup.S new file mode 100644 index 0000000..a71afbd --- /dev/null +++ b/startup/startup.S @@ -0,0 +1,90 @@ +.section .text + +.global Reset_Handler + +Reset_Handler: + mv x1, x0 + mv x2, x1 + mv x3, x1 + mv x4, x1 + mv x5, x1 + mv x6, x1 + mv x7, x1 + mv x8, x1 + mv x9, x1 + mv x10, x1 + mv x11, x1 + mv x12, x1 + mv x13, x1 + mv x14, x1 + mv x15, x1 + mv x16, x1 + mv x17, x1 + mv x18, x1 + mv x19, x1 + mv x20, x1 + mv x21, x1 + mv x22, x1 + mv x23, x1 + mv x24, x1 + mv x25, x1 + mv x26, x1 + mv x27, x1 + mv x28, x1 + mv x29, x1 + mv x30, x1 + mv x31, x1 + +.option push +.option norelax + la gp, __global_pointer$ +.option pop + + la sp, _estack + + la x25, _sidata + la x26, _sdata + la x27, _edata + + bge x26, x27, copy_data_end + +copy_data: + ld x24, 0(x25) + sd x24, 0(x26) + addi x25, x25, 8 + addi x26, x26, 8 + + blt x26, x27, copy_data + +copy_data_end: + +/* Zero .bss section */ + la x26, _sbss + la x27, _ebss + + bge x26, x27, zero_bss_end + +zero_bss: + sd x0, 0(x26) + addi x26, x26, 8 + blt x26, x27, zero_bss + +zero_bss_end: + jal x1, System_Init + + addi x10, x0, 0 + addi x11, x0, 0 + jal x1, main + +inf_loop: + jal x0, inf_loop + +/* ISR vector table */ +.section .isr_vectors, "ax" +.option norvc; + +.org 0x00 + jal x0, Exception_Handler + +.org 0x1000 + jal x0, Reset_Handler