Merge branch 'cmake_flow' into develop
This commit is contained in:
3
env/common-gcc.mk
vendored
3
env/common-gcc.mk
vendored
@ -16,6 +16,8 @@ BOARD?=iss
|
||||
|
||||
ASM_SRCS += $(ENV_DIR)/start.S $(ENV_DIR)/entry.S
|
||||
C_SRCS += $(PLATFORM_DIR)/init.c
|
||||
C_SRCS += $(PLATFORM_DIR)/bsp_write.c $(PLATFORM_DIR)/bsp_read.c
|
||||
|
||||
|
||||
LINKER_SCRIPT ?= $(PLATFORM_DIR)/$(LINK_TARGET).lds
|
||||
|
||||
@ -23,6 +25,7 @@ INCLUDES += -I$(BSP_BASE)/include
|
||||
INCLUDES += -I$(BSP_BASE)/drivers/
|
||||
INCLUDES += -I$(ENV_DIR)
|
||||
INCLUDES += -I$(PLATFORM_DIR)
|
||||
INCLUDES += -I$(BSP_BASE)/libwrap/sys/
|
||||
|
||||
LDFLAGS += -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI)
|
||||
LDFLAGS += -L$(ENV_DIR)
|
||||
|
81
env/hifive1.h
vendored
81
env/hifive1.h
vendored
@ -1,81 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef _SIFIVE_HIFIVE1_H
|
||||
#define _SIFIVE_HIFIVE1_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* GPIO Connections
|
||||
*****************************************************************************/
|
||||
|
||||
// These are the GPIO bit offsets for the RGB LED on HiFive1 Board.
|
||||
// These are also mapped to RGB LEDs on the Freedom E300 Arty
|
||||
// FPGA
|
||||
// Dev Kit.
|
||||
|
||||
#define RED_LED_OFFSET 22
|
||||
#define GREEN_LED_OFFSET 19
|
||||
#define BLUE_LED_OFFSET 21
|
||||
|
||||
// These are the GPIO bit offsets for the differen digital pins
|
||||
// on the headers for both the HiFive1 Board and the Freedom E300 Arty FPGA Dev Kit.
|
||||
#define PIN_0_OFFSET 16
|
||||
#define PIN_1_OFFSET 17
|
||||
#define PIN_2_OFFSET 18
|
||||
#define PIN_3_OFFSET 19
|
||||
#define PIN_4_OFFSET 20
|
||||
#define PIN_5_OFFSET 21
|
||||
#define PIN_6_OFFSET 22
|
||||
#define PIN_7_OFFSET 23
|
||||
#define PIN_8_OFFSET 0
|
||||
#define PIN_9_OFFSET 1
|
||||
#define PIN_10_OFFSET 2
|
||||
#define PIN_11_OFFSET 3
|
||||
#define PIN_12_OFFSET 4
|
||||
#define PIN_13_OFFSET 5
|
||||
//#define PIN_14_OFFSET 8 //This pin is not connected on either board.
|
||||
#define PIN_15_OFFSET 9
|
||||
#define PIN_16_OFFSET 10
|
||||
#define PIN_17_OFFSET 11
|
||||
#define PIN_18_OFFSET 12
|
||||
#define PIN_19_OFFSET 13
|
||||
|
||||
// These are *PIN* numbers, not
|
||||
// GPIO Offset Numbers.
|
||||
#define PIN_SPI1_SCK (13u)
|
||||
#define PIN_SPI1_MISO (12u)
|
||||
#define PIN_SPI1_MOSI (11u)
|
||||
#define PIN_SPI1_SS0 (10u)
|
||||
#define PIN_SPI1_SS1 (14u)
|
||||
#define PIN_SPI1_SS2 (15u)
|
||||
#define PIN_SPI1_SS3 (16u)
|
||||
|
||||
#define SS_PIN_TO_CS_ID(x) \
|
||||
((x==PIN_SPI1_SS0 ? 0 : \
|
||||
(x==PIN_SPI1_SS1 ? 1 : \
|
||||
(x==PIN_SPI1_SS2 ? 2 : \
|
||||
(x==PIN_SPI1_SS3 ? 3 : \
|
||||
-1)))))
|
||||
|
||||
|
||||
// These buttons are present only on the Freedom E300 Arty Dev Kit.
|
||||
#ifdef HAS_BOARD_BUTTONS
|
||||
#define BUTTON_0_OFFSET 15
|
||||
#define BUTTON_1_OFFSET 30
|
||||
#define BUTTON_2_OFFSET 31
|
||||
|
||||
#define INT_DEVICE_BUTTON_0 (INT_GPIO_BASE + BUTTON_0_OFFSET)
|
||||
#define INT_DEVICE_BUTTON_1 (INT_GPIO_BASE + BUTTON_1_OFFSET)
|
||||
#define INT_DEVICE_BUTTON_2 (INT_GPIO_BASE + BUTTON_2_OFFSET)
|
||||
|
||||
#endif
|
||||
|
||||
#define HAS_HFXOSC 1
|
||||
#define HAS_LFROSC_BYPASS 1
|
||||
|
||||
#define RTC_FREQ 32768
|
||||
|
||||
void write_hex(int fd, unsigned long int hex);
|
||||
|
||||
#endif /* _SIFIVE_HIFIVE1_H */
|
157
env/hifive1/dhrystone.lds
vendored
157
env/hifive1/dhrystone.lds
vendored
@ -1,157 +0,0 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
|
||||
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
flash PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
||||
|
||||
.init :
|
||||
{
|
||||
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 = .);
|
||||
|
||||
. = 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
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.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);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
|
||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
}
|
238
env/hifive1/init.c
vendored
238
env/hifive1/init.c
vendored
@ -1,238 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "encoding.h"
|
||||
|
||||
extern int main(int argc, char** argv);
|
||||
extern void trap_entry();
|
||||
|
||||
static unsigned long mtime_lo(void)
|
||||
{
|
||||
return *(volatile unsigned long *)(CLINT_CTRL_ADDR + CLINT_MTIME);
|
||||
}
|
||||
|
||||
#ifdef __riscv32
|
||||
|
||||
static uint32_t mtime_hi(void)
|
||||
{
|
||||
return *(volatile uint32_t *)(CLINT_CTRL_ADDR + CLINT_MTIME + 4);
|
||||
}
|
||||
|
||||
uint64_t get_timer_value()
|
||||
{
|
||||
while (1) {
|
||||
uint32_t hi = mtime_hi();
|
||||
uint32_t lo = mtime_lo();
|
||||
if (hi == mtime_hi())
|
||||
return ((uint64_t)hi << 32) | lo;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* __riscv32 */
|
||||
|
||||
uint64_t get_timer_value()
|
||||
{
|
||||
return mtime_lo();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned long get_timer_freq()
|
||||
{
|
||||
return 32768;
|
||||
}
|
||||
|
||||
static void use_hfrosc(int div, int trim)
|
||||
{
|
||||
// Make sure the HFROSC is running at its default setting
|
||||
PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1));
|
||||
while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0) ;
|
||||
PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1);
|
||||
}
|
||||
|
||||
static void use_pll(int refsel, int bypass, int r, int f, int q)
|
||||
{
|
||||
// Ensure that we aren't running off the PLL before we mess with it.
|
||||
if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) {
|
||||
// Make sure the HFROSC is running at its default setting
|
||||
use_hfrosc(4, 16);
|
||||
}
|
||||
|
||||
// Set PLL Source to be HFXOSC if available.
|
||||
uint32_t config_value = 0;
|
||||
|
||||
config_value |= PLL_REFSEL(refsel);
|
||||
|
||||
if (bypass) {
|
||||
// Bypass
|
||||
config_value |= PLL_BYPASS(1);
|
||||
|
||||
PRCI_REG(PRCI_PLLCFG) = config_value;
|
||||
|
||||
// If we don't have an HFXTAL, this doesn't really matter.
|
||||
// Set our Final output divide to divide-by-1:
|
||||
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
|
||||
} else {
|
||||
// In case we are executing from QSPI,
|
||||
// (which is quite likely) we need to
|
||||
// set the QSPI clock divider appropriately
|
||||
// before boosting the clock frequency.
|
||||
|
||||
// Div = f_sck/2
|
||||
SPI0_REG(SPI_REG_SCKDIV) = 8;
|
||||
|
||||
// Set DIV Settings for PLL
|
||||
// Both HFROSC and HFXOSC are modeled as ideal
|
||||
// 16MHz sources (assuming dividers are set properly for
|
||||
// HFROSC).
|
||||
// (Legal values of f_REF are 6-48MHz)
|
||||
|
||||
// Set DIVR to divide-by-2 to get 8MHz frequency
|
||||
// (legal values of f_R are 6-12 MHz)
|
||||
|
||||
config_value |= PLL_BYPASS(1);
|
||||
config_value |= PLL_R(r);
|
||||
|
||||
// Set DIVF to get 512Mhz frequncy
|
||||
// There is an implied multiply-by-2, 16Mhz.
|
||||
// So need to write 32-1
|
||||
// (legal values of f_F are 384-768 MHz)
|
||||
config_value |= PLL_F(f);
|
||||
|
||||
// Set DIVQ to divide-by-2 to get 256 MHz frequency
|
||||
// (legal values of f_Q are 50-400Mhz)
|
||||
config_value |= PLL_Q(q);
|
||||
|
||||
// Set our Final output divide to divide-by-1:
|
||||
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
|
||||
|
||||
PRCI_REG(PRCI_PLLCFG) = config_value;
|
||||
|
||||
// Un-Bypass the PLL.
|
||||
PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1);
|
||||
|
||||
// Wait for PLL Lock
|
||||
// Note that the Lock signal can be glitchy.
|
||||
// Need to wait 100 us
|
||||
// RTC is running at 32kHz.
|
||||
// So wait 4 ticks of RTC.
|
||||
uint32_t now = mtime_lo();
|
||||
while (mtime_lo() - now < 4) ;
|
||||
|
||||
// Now it is safe to check for PLL Lock
|
||||
while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0) ;
|
||||
}
|
||||
|
||||
// Switch over to PLL Clock source
|
||||
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);
|
||||
}
|
||||
|
||||
static void use_default_clocks()
|
||||
{
|
||||
// Turn off the LFROSC
|
||||
AON_REG(AON_LFROSC) &= ~ROSC_EN(1);
|
||||
|
||||
// Use HFROSC
|
||||
use_hfrosc(4, 16);
|
||||
}
|
||||
|
||||
static unsigned long __attribute__((noinline)) measure_cpu_freq(size_t n)
|
||||
{
|
||||
unsigned long start_mtime, delta_mtime;
|
||||
unsigned long mtime_freq = get_timer_freq();
|
||||
|
||||
// Don't start measuruing until we see an mtime tick
|
||||
unsigned long tmp = mtime_lo();
|
||||
do {
|
||||
start_mtime = mtime_lo();
|
||||
} while (start_mtime == tmp);
|
||||
|
||||
unsigned long start_mcycle = read_csr(mcycle);
|
||||
|
||||
do {
|
||||
delta_mtime = mtime_lo() - start_mtime;
|
||||
} while (delta_mtime < n);
|
||||
|
||||
unsigned long delta_mcycle = read_csr(mcycle) - start_mcycle;
|
||||
|
||||
return (delta_mcycle / delta_mtime) * mtime_freq
|
||||
+ ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
|
||||
}
|
||||
|
||||
unsigned long get_cpu_freq()
|
||||
{
|
||||
static uint32_t cpu_freq;
|
||||
|
||||
if (!cpu_freq) {
|
||||
// warm up I$
|
||||
measure_cpu_freq(1);
|
||||
// measure for real
|
||||
cpu_freq = measure_cpu_freq(10);
|
||||
}
|
||||
|
||||
return cpu_freq;
|
||||
}
|
||||
|
||||
static void uart_init(size_t baud_rate)
|
||||
{
|
||||
GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK;
|
||||
GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK;
|
||||
UART0_REG(UART_REG_DIV) = get_cpu_freq() / baud_rate - 1;
|
||||
UART0_REG(UART_REG_TXCTRL) |= UART_TXEN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef USE_PLIC
|
||||
extern void handle_m_ext_interrupt();
|
||||
#endif
|
||||
|
||||
#ifdef USE_M_TIME
|
||||
extern void handle_m_time_interrupt();
|
||||
#endif
|
||||
|
||||
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
|
||||
{
|
||||
if (0){
|
||||
#ifdef USE_PLIC
|
||||
// External Machine-Level interrupt from PLIC
|
||||
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {
|
||||
handle_m_ext_interrupt();
|
||||
#endif
|
||||
#ifdef USE_M_TIME
|
||||
// External Machine-Level interrupt from PLIC
|
||||
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){
|
||||
handle_m_time_interrupt();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
write(1, "trap\n", 5);
|
||||
_exit(1 + mcause);
|
||||
}
|
||||
return epc;
|
||||
}
|
||||
|
||||
void _init()
|
||||
{
|
||||
|
||||
#ifndef NO_INIT
|
||||
use_default_clocks();
|
||||
use_pll(0, 0, 1, 31, 1);
|
||||
uart_init(115200);
|
||||
|
||||
printf("core freq at %d 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
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void _fini()
|
||||
{
|
||||
}
|
166
env/hifive1/link.lds
vendored
166
env/hifive1/link.lds
vendored
@ -1,166 +0,0 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
|
||||
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 512K
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
flash PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
||||
|
||||
.init :
|
||||
{
|
||||
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
|
||||
|
||||
.except :
|
||||
{
|
||||
*(.gcc_except_table.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.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);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
|
||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
}
|
34
env/hifive1/openocd.cfg
vendored
34
env/hifive1/openocd.cfg
vendored
@ -1,34 +0,0 @@
|
||||
adapter_khz 10000
|
||||
|
||||
interface ftdi
|
||||
ftdi_device_desc "Dual RS232-HS"
|
||||
ftdi_vid_pid 0x0403 0x6010
|
||||
|
||||
ftdi_layout_init 0x0008 0x001b
|
||||
ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020
|
||||
|
||||
#Reset Stretcher logic on FE310 is ~1 second long
|
||||
#This doesn't apply if you use
|
||||
# ftdi_set_signal, but still good to document
|
||||
#adapter_nsrst_delay 1500
|
||||
|
||||
set _CHIPNAME riscv
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||
$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
|
||||
|
||||
flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME
|
||||
init
|
||||
#reset -- This type of reset is not implemented yet
|
||||
if {[ info exists pulse_srst]} {
|
||||
ftdi_set_signal nSRST 0
|
||||
ftdi_set_signal nSRST z
|
||||
#Wait for the reset stretcher
|
||||
#It will work without this, but
|
||||
#will incur lots of delays for later commands.
|
||||
sleep 1500
|
||||
}
|
||||
halt
|
||||
#flash protect 0 64 last off
|
133
env/hifive1/platform.h
vendored
133
env/hifive1/platform.h
vendored
@ -1,133 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef _SIFIVE_PLATFORM_H
|
||||
#define _SIFIVE_PLATFORM_H
|
||||
|
||||
// Some things missing from the official encoding.h
|
||||
#define MCAUSE_INT 0x80000000
|
||||
#define MCAUSE_CAUSE 0x7FFFFFFF
|
||||
|
||||
#include "bits.h"
|
||||
#include "sifive/devices/aon.h"
|
||||
#include "sifive/devices/clint.h"
|
||||
#include "sifive/devices/gpio.h"
|
||||
#include "sifive/devices/otp.h"
|
||||
#include "sifive/devices/plic.h"
|
||||
#include "sifive/devices/prci.h"
|
||||
#include "sifive/devices/pwm.h"
|
||||
#include "sifive/devices/spi.h"
|
||||
#include "sifive/devices/uart.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Platform definitions
|
||||
*****************************************************************************/
|
||||
|
||||
// Memory map
|
||||
#define MASKROM_MEM_ADDR _AC(0x00001000,UL)
|
||||
#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL)
|
||||
#define OTP_MEM_ADDR _AC(0x00020000,UL)
|
||||
#define CLINT_CTRL_ADDR _AC(0x02000000,UL)
|
||||
#define PLIC_CTRL_ADDR _AC(0x0C000000,UL)
|
||||
#define AON_CTRL_ADDR _AC(0x10000000,UL)
|
||||
#define PRCI_CTRL_ADDR _AC(0x10008000,UL)
|
||||
#define OTP_CTRL_ADDR _AC(0x10010000,UL)
|
||||
#define GPIO_CTRL_ADDR _AC(0x10012000,UL)
|
||||
#define UART0_CTRL_ADDR _AC(0x10013000,UL)
|
||||
#define SPI0_CTRL_ADDR _AC(0x10014000,UL)
|
||||
#define PWM0_CTRL_ADDR _AC(0x10015000,UL)
|
||||
#define UART1_CTRL_ADDR _AC(0x10023000,UL)
|
||||
#define SPI1_CTRL_ADDR _AC(0x10024000,UL)
|
||||
#define PWM1_CTRL_ADDR _AC(0x10025000,UL)
|
||||
#define SPI2_CTRL_ADDR _AC(0x10034000,UL)
|
||||
#define PWM2_CTRL_ADDR _AC(0x10035000,UL)
|
||||
#define SPI0_MEM_ADDR _AC(0x20000000,UL)
|
||||
#define MEM_CTRL_ADDR _AC(0x80000000,UL)
|
||||
|
||||
// IOF masks
|
||||
#define IOF0_SPI1_MASK _AC(0x000007FC,UL)
|
||||
#define SPI11_NUM_SS (4)
|
||||
#define IOF_SPI1_SS0 (2u)
|
||||
#define IOF_SPI1_SS1 (8u)
|
||||
#define IOF_SPI1_SS2 (9u)
|
||||
#define IOF_SPI1_SS3 (10u)
|
||||
#define IOF_SPI1_MOSI (3u)
|
||||
#define IOF_SPI1_MISO (4u)
|
||||
#define IOF_SPI1_SCK (5u)
|
||||
#define IOF_SPI1_DQ0 (3u)
|
||||
#define IOF_SPI1_DQ1 (4u)
|
||||
#define IOF_SPI1_DQ2 (6u)
|
||||
#define IOF_SPI1_DQ3 (7u)
|
||||
|
||||
#define IOF0_SPI2_MASK _AC(0xFC000000,UL)
|
||||
#define SPI2_NUM_SS (1)
|
||||
#define IOF_SPI2_SS0 (26u)
|
||||
#define IOF_SPI2_MOSI (27u)
|
||||
#define IOF_SPI2_MISO (28u)
|
||||
#define IOF_SPI2_SCK (29u)
|
||||
#define IOF_SPI2_DQ0 (27u)
|
||||
#define IOF_SPI2_DQ1 (28u)
|
||||
#define IOF_SPI2_DQ2 (30u)
|
||||
#define IOF_SPI2_DQ3 (31u)
|
||||
|
||||
//#define IOF0_I2C_MASK _AC(0x00003000,UL)
|
||||
|
||||
#define IOF0_UART0_MASK _AC(0x00030000, UL)
|
||||
#define IOF_UART0_RX (16u)
|
||||
#define IOF_UART0_TX (17u)
|
||||
|
||||
#define IOF0_UART1_MASK _AC(0x03000000, UL)
|
||||
#define IOF_UART1_RX (24u)
|
||||
#define IOF_UART1_TX (25u)
|
||||
|
||||
#define IOF1_PWM0_MASK _AC(0x0000000F, UL)
|
||||
#define IOF1_PWM1_MASK _AC(0x00780000, UL)
|
||||
#define IOF1_PWM2_MASK _AC(0x00003C00, UL)
|
||||
|
||||
// Interrupt numbers
|
||||
#define INT_RESERVED 0
|
||||
#define INT_WDOGCMP 1
|
||||
#define INT_RTCCMP 2
|
||||
#define INT_UART0_BASE 3
|
||||
#define INT_UART1_BASE 4
|
||||
#define INT_SPI0_BASE 5
|
||||
#define INT_SPI1_BASE 6
|
||||
#define INT_SPI2_BASE 7
|
||||
#define INT_GPIO_BASE 8
|
||||
#define INT_PWM0_BASE 40
|
||||
#define INT_PWM1_BASE 44
|
||||
#define INT_PWM2_BASE 48
|
||||
|
||||
// Helper functions
|
||||
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
|
||||
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
|
||||
#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset)
|
||||
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
|
||||
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
|
||||
#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset)
|
||||
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
|
||||
#define PRCI_REG(offset) _REG32(PRCI_CTRL_ADDR, offset)
|
||||
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
|
||||
#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset)
|
||||
#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset)
|
||||
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
|
||||
#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset)
|
||||
#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset)
|
||||
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
|
||||
#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset)
|
||||
|
||||
// Misc
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NUM_GPIO 32
|
||||
|
||||
#define PLIC_NUM_INTERRUPTS 52
|
||||
#define PLIC_NUM_PRIORITIES 7
|
||||
|
||||
#include "hifive1.h"
|
||||
|
||||
unsigned long get_cpu_freq(void);
|
||||
unsigned long get_timer_freq(void);
|
||||
uint64_t get_timer_value(void);
|
||||
|
||||
#endif /* _SIFIVE_PLATFORM_H */
|
3
env/hifive1/settings.mk
vendored
3
env/hifive1/settings.mk
vendored
@ -1,3 +0,0 @@
|
||||
# Describes the CPU on this board to the rest of the SDK.
|
||||
RISCV_ARCH := rv32imac
|
||||
RISCV_ABI := ilp32
|
6
env/iss/bsp_read.c
vendored
Normal file
6
env/iss/bsp_read.c
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
ssize_t _bsp_read(int fd, void *ptr, size_t len) { return EOF; }
|
25
env/iss/bsp_write.c
vendored
Normal file
25
env/iss/bsp_write.c
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/* See LICENSE of license details. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern volatile uint64_t tohost;
|
||||
|
||||
ssize_t _bsp_write(int fd, const void *ptr, size_t len) {
|
||||
|
||||
if (isatty(fd)) {
|
||||
volatile uint64_t payload[8];
|
||||
memset((void *)payload, 0, 8 * sizeof(uint64_t));
|
||||
payload[0] = 64;
|
||||
payload[2] = (uintptr_t)ptr;
|
||||
payload[3] = len;
|
||||
tohost = (uintptr_t)payload;
|
||||
return len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
26
env/iss/link.lds
vendored
26
env/iss/link.lds
vendored
@ -13,6 +13,7 @@ PHDRS
|
||||
flash PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@ -123,22 +124,30 @@ SECTIONS
|
||||
*(.gnu.linkonce.d.*)
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
|
||||
|
||||
.sdata :
|
||||
{
|
||||
|
||||
__SDATA_BEGIN__ = .;
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
|
||||
.srodata :
|
||||
{
|
||||
|
||||
PROVIDE( _gp = . + 0x800 );
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
.sdata :
|
||||
{
|
||||
__SDATA_BEGIN__ = .;
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
@ -169,6 +178,7 @@ SECTIONS
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
|
||||
PROVIDE( tohost = 0xfffffff0 );
|
||||
PROVIDE( fromhost = 0xfffffff8 );
|
||||
PROVIDE( tohost = . );
|
||||
PROVIDE( fromhost = . + 8 );
|
||||
}
|
||||
|
||||
|
3
env/iss/platform.h
vendored
3
env/iss/platform.h
vendored
@ -22,6 +22,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern volatile uintptr_t tohost;
|
||||
extern volatile uintptr_t fromhost;
|
||||
|
||||
void init_pll(void);
|
||||
unsigned long get_cpu_freq(void);
|
||||
unsigned long get_timer_freq(void);
|
||||
|
21
env/moonlight/bsp_read.c
vendored
Normal file
21
env/moonlight/bsp_read.c
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
#include "platform.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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;
|
||||
}
|
21
env/moonlight/bsp_write.c
vendored
Normal file
21
env/moonlight/bsp_write.c
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/* See LICENSE of license details. */
|
||||
|
||||
#include "platform.h"
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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;
|
||||
}
|
@ -176,6 +176,8 @@ SECTIONS
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
|
||||
PROVIDE( tohost = 0xfffffff0 );
|
||||
PROVIDE( fromhost = 0xfffffff8 );
|
||||
|
||||
|
||||
PROVIDE( tohost = . );
|
||||
PROVIDE( fromhost = . + 8 );
|
||||
}
|
@ -13,41 +13,33 @@
|
||||
|
||||
#define APB_BUS
|
||||
|
||||
#include "ehrenberg/devices/aclint.h"
|
||||
#include "ehrenberg/devices/camera.h"
|
||||
#include "ehrenberg/devices/dma.h"
|
||||
#include "ehrenberg/devices/gen/sysctrl.h"
|
||||
#include "ehrenberg/devices/gpio.h"
|
||||
#include "ehrenberg/devices/i2s.h"
|
||||
#include "ehrenberg/devices/msg_if.h"
|
||||
#include "ehrenberg/devices/qspi.h"
|
||||
#include "ehrenberg/devices/timer.h"
|
||||
#include "ehrenberg/devices/uart.h"
|
||||
#include "minres/devices/aclint.h"
|
||||
#include "minres/devices/camera.h"
|
||||
#include "minres/devices/dma.h"
|
||||
#include "minres/devices/gpio.h"
|
||||
#include "minres/devices/i2s.h"
|
||||
#include "minres/devices/msg_if.h"
|
||||
#include "minres/devices/qspi.h"
|
||||
#include "minres/devices/timer.h"
|
||||
#include "minres/devices/uart.h"
|
||||
|
||||
#define PERIPH(TYPE, ADDR) ((volatile TYPE *)(ADDR))
|
||||
|
||||
#define APB_BASE 0xF0000000
|
||||
|
||||
#define gpio PERIPH(gpio_t, APB_BASE + 0x0000)
|
||||
#define uart PERIPH(uart_t, APB_BASE + 0x01000)
|
||||
#define uart PERIPH(uart_t, APB_BASE + 0x1000)
|
||||
#define timer PERIPH(timercounter_t, APB_BASE + 0x20000)
|
||||
#define aclint PERIPH(aclint_t, APB_BASE + 0x30000)
|
||||
#define sysctrl PERIPH(sysctrl_t, APB_BASE + 0x40000)
|
||||
#define irq PERIPH(irq_t, APB_BASE + 0x40000)
|
||||
#define qspi PERIPH(qspi_t, APB_BASE + 0x50000)
|
||||
#define i2s PERIPH(i2s_t, APB_BASE + 0x90000)
|
||||
#define camera PERIPH(camera_t, APB_BASE + 0xA0000)
|
||||
#define dma PERIPH(dma_t, APB_BASE + 0xB0000)
|
||||
#define msgif PERIPH(mkcontrolclusterstreamcontroller_t, APB_BASE + 0xC0000)
|
||||
#define msgif PERIPH(msgif_t, APB_BASE + 0xC0000)
|
||||
|
||||
#include "ehrenberg/devices/fki_cluster_info.h"
|
||||
#include "ehrenberg/devices/flexki_messages.h"
|
||||
|
||||
#ifndef XIP_START_LOC
|
||||
#define XIP_START_LOC 0xE0000000
|
||||
#endif
|
||||
#ifndef RAM_START_LOC
|
||||
#define RAM_START_LOC 0xC0000000
|
||||
#endif
|
||||
#define XIP_START_LOC 0xE0040000
|
||||
#define RAM_START_LOC 0x80000000
|
||||
|
||||
// Misc
|
||||
|
195
env/semihosting.c
vendored
Normal file
195
env/semihosting.c
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "semihosting.h"
|
||||
|
||||
#define SEMIHOSTING_SYS_OPEN 0x01
|
||||
#define SEMIHOSTING_SYS_CLOSE 0x02
|
||||
#define SEMIHOSTING_SYS_WRITEC 0x03
|
||||
#define SEMIHOSTING_SYS_WRITE0 0x04
|
||||
#define SEMIHOSTING_SYS_WRITE 0x05
|
||||
#define SEMIHOSTING_SYS_READ 0x06
|
||||
#define SEMIHOSTING_SYS_READC 0x07
|
||||
#define SEMIHOSTING_SYS_ISERROR 0x08
|
||||
#define SEMIHOSTING_SYS_ISTTY 0x09
|
||||
#define SEMIHOSTING_SYS_SEEK 0x0A
|
||||
#define SEMIHOSTING_SYS_FLEN 0x0C
|
||||
#define SEMIHOSTING_SYS_TMPNAM 0x0D
|
||||
#define SEMIHOSTING_SYS_REMOVE 0x0E
|
||||
#define SEMIHOSTING_SYS_RENAME 0x0F
|
||||
#define SEMIHOSTING_SYS_CLOCK 0x10
|
||||
#define SEMIHOSTING_SYS_TIME 0x11
|
||||
#define SEMIHOSTING_SYS_SYSTEM 0x12
|
||||
#define SEMIHOSTING_SYS_ERRNO 0x13
|
||||
#define SEMIHOSTING_SYS_GET_CMDLINE 0x15
|
||||
#define SEMIHOSTING_SYS_HEAPINFO 0x16
|
||||
#define SEMIHOSTING_EnterSVC 0x17
|
||||
#define SEMIHOSTING_SYS_EXIT 0x18
|
||||
#define SEMIHOSTING_SYS_EXIT_EXTENDED 0x20
|
||||
#define SEMIHOSTING_SYS_ELAPSED 0x30
|
||||
#define SEMIHOSTING_SYS_TICKFREQ 0x31
|
||||
|
||||
#define RISCV_SEMIHOSTING_CALL_NUMBER 7
|
||||
|
||||
typedef struct {
|
||||
char *str;
|
||||
int mode;
|
||||
size_t length;
|
||||
} OpenVector;
|
||||
|
||||
typedef struct {
|
||||
char *old;
|
||||
int old_len;
|
||||
char *new;
|
||||
int new_len;
|
||||
} RenameVector;
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
size_t len;
|
||||
} RemoveVector;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
off_t pos;
|
||||
} SeekVector;
|
||||
|
||||
static inline int __attribute__((always_inline))
|
||||
call_host(int reason, void *arg) {
|
||||
#if 1
|
||||
// This must always be set back to 0 to cover the case where a host wasn't
|
||||
// initially present, but only connected while the program was already up and
|
||||
// running. In that case, trap() suddenly won't be called anymore, so we have
|
||||
// to clear this variable *before* EBREAK is called.
|
||||
sh_missing_host = 0;
|
||||
|
||||
register int value asm("a0") = reason;
|
||||
register void *ptr asm("a1") = arg;
|
||||
asm volatile(
|
||||
// Workaround for RISC-V lack of multiple EBREAKs.
|
||||
" .option push \n"
|
||||
" .option norvc \n"
|
||||
// Force 16-byte alignment to make sure that the 3 instruction fall
|
||||
// within the same virtual page. If you the instruction straddle a page
|
||||
// boundary the debugger fetching the instructions could lead to a page
|
||||
// fault. Note: align 4 means, align by 2 to the power of 4!
|
||||
" .align 4 \n"
|
||||
" slli x0, x0, 0x1f \n"
|
||||
" ebreak \n"
|
||||
" srai x0, x0, 0x07 \n"
|
||||
" .option pop \n"
|
||||
|
||||
: "=r"(value) /* Outputs */
|
||||
: "0"(value),
|
||||
"r"(ptr), [swi] "i"(RISCV_SEMIHOSTING_CALL_NUMBER) /* Inputs */
|
||||
: "memory" /* Clobbers */
|
||||
);
|
||||
return value;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int sh_errno(void) { return call_host(SEMIHOSTING_SYS_ERRNO, (void *)NULL); }
|
||||
|
||||
int sh_time(void) { return call_host(SEMIHOSTING_SYS_TIME, (void *)NULL); }
|
||||
|
||||
int sh_remove(char *path) {
|
||||
size_t len = strlen(path);
|
||||
RemoveVector vec = {path, len};
|
||||
return call_host(SEMIHOSTING_SYS_REMOVE, &vec);
|
||||
}
|
||||
|
||||
void sh_seek(int file_handle, off_t pos) {
|
||||
SeekVector vec = {file_handle, pos};
|
||||
call_host(SEMIHOSTING_SYS_SEEK, &vec);
|
||||
return;
|
||||
}
|
||||
|
||||
void sh_write(char *str, int file_handle) {
|
||||
size_t length = strlen(str);
|
||||
OpenVector vec = {str, file_handle, length};
|
||||
call_host(SEMIHOSTING_SYS_WRITE, &vec);
|
||||
return;
|
||||
}
|
||||
|
||||
int sh_close(int file_handle) {
|
||||
return call_host(SEMIHOSTING_SYS_CLOSE, file_handle);
|
||||
}
|
||||
|
||||
void sh_exit(void) {
|
||||
call_host(SEMIHOSTING_SYS_EXIT, (void *)NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void sh_exit_extended(void) {
|
||||
call_host(SEMIHOSTING_SYS_EXIT_EXTENDED, (void *)NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
int sh_flen(int file_handle) {
|
||||
return call_host(SEMIHOSTING_SYS_FLEN, file_handle);
|
||||
}
|
||||
|
||||
int sh_iserror(int num) { return call_host(SEMIHOSTING_SYS_ISERROR, num); }
|
||||
|
||||
int sh_istty(int file_handle) {
|
||||
return call_host(SEMIHOSTING_SYS_ISTTY, file_handle);
|
||||
}
|
||||
/*
|
||||
int sh_remove(char* path) {
|
||||
size_t len = strlen(path);
|
||||
RemoveVector vec = {path, len};
|
||||
return call_host(SEMIHOSTING_SYS_REMOVE, &vec);
|
||||
}*/
|
||||
|
||||
void sh_rename(char *old, char *new) {
|
||||
int old_len = strlen(old);
|
||||
int new_len = strlen(new);
|
||||
RenameVector vec = {old, old_len, new, new_len};
|
||||
call_host(SEMIHOSTING_SYS_RENAME, &vec);
|
||||
return;
|
||||
}
|
||||
|
||||
void sh_write0(const char *buf) {
|
||||
// Print zero-terminated string
|
||||
call_host(SEMIHOSTING_SYS_WRITE0, (void *)buf);
|
||||
}
|
||||
|
||||
void sh_writec(char c) {
|
||||
// Print single character
|
||||
call_host(SEMIHOSTING_SYS_WRITEC, (void *)&c);
|
||||
}
|
||||
|
||||
char sh_readc(void) {
|
||||
// Read character from keyboard. (Blocking operation!)
|
||||
char c = call_host(SEMIHOSTING_SYS_READC, (void *)NULL);
|
||||
return c;
|
||||
}
|
||||
|
||||
int sh_open(char *str, int mode) {
|
||||
// mode = 0;
|
||||
// int length = 44;
|
||||
size_t length = strlen(str);
|
||||
OpenVector vec = {str, mode, length};
|
||||
return call_host(SEMIHOSTING_SYS_OPEN, &vec);
|
||||
}
|
||||
|
||||
int sh_read(char *buf, int file_handle, size_t length) {
|
||||
OpenVector vec = {buf, file_handle, length};
|
||||
int i = call_host(SEMIHOSTING_SYS_READ, &vec);
|
||||
return i;
|
||||
}
|
||||
|
||||
int sh_clock(void) {
|
||||
int clock = call_host(SEMIHOSTING_SYS_CLOCK, (void *)NULL);
|
||||
return clock;
|
||||
}
|
||||
|
||||
/*
|
||||
void sh_write(char* str, int file_handle) {
|
||||
return;
|
||||
}*/
|
1
env/start.S
vendored
1
env/start.S
vendored
@ -1,3 +1,4 @@
|
||||
#include "encoding.h"
|
||||
// See LICENSE for license details.
|
||||
|
||||
.section .init
|
||||
|
19
env/testbench/rtl/bsp_read.c
vendored
Normal file
19
env/testbench/rtl/bsp_read.c
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
ssize_t _bsp_read(int fd, void *ptr, size_t len) {
|
||||
uint8_t *current = (uint8_t *)ptr;
|
||||
volatile uint32_t *uart_rx = (uint32_t *)0xFFFF0000;
|
||||
ssize_t result = 0;
|
||||
if (isatty(fd)) {
|
||||
for (current = (uint8_t *)ptr; (current < ((uint8_t *)ptr) + len);
|
||||
current++) {
|
||||
*current = *uart_rx;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return EOF;
|
||||
}
|
18
env/testbench/rtl/bsp_write.c
vendored
Normal file
18
env/testbench/rtl/bsp_write.c
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/* See LICENSE of license details. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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++) {
|
||||
*((uint32_t *)0xFFFF0000) = current[jj];
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
2
env/tgc_vp
vendored
2
env/tgc_vp
vendored
@ -1 +1 @@
|
||||
ehrenberg
|
||||
moonlight/
|
60
env/trap.c
vendored
Normal file
60
env/trap.c
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#if defined(SEMIHOSTING)
|
||||
#define EBREAK_OPCODE 0x00100073
|
||||
#define EBREAK_MCAUSE 0x00000003
|
||||
|
||||
#define SLLI_X0_X0_0X1F_OPCODE 0x01f01013
|
||||
#define SRAI_X0_X0_0X07_OPCODE 0x40705013
|
||||
|
||||
int sh_missing_host = 0;
|
||||
|
||||
void trap() { // ToDo: Check why macro CSR_MEPC and others are not
|
||||
// resolved
|
||||
uint32_t mepc = read_csr(0x341); // Address of trap
|
||||
uint32_t mtval = read_csr(0x343); // Instruction value of trap
|
||||
uint32_t mcause = read_csr(0x342); // Reason for the trap
|
||||
|
||||
if (mcause == EBREAK_MCAUSE && mtval == EBREAK_OPCODE) {
|
||||
// This trap was caused by an EBREAK...
|
||||
|
||||
int aligned = ((mepc - 4) & 0x0f) == 0;
|
||||
if (aligned && *(uint32_t *)mepc == EBREAK_OPCODE &&
|
||||
*(uint32_t *)(mepc - 4) == SLLI_X0_X0_0X1F_OPCODE &&
|
||||
*(uint32_t *)(mepc + 4) == SRAI_X0_X0_0X07_OPCODE) {
|
||||
// The EBREAK was part of the semihosting call. (See semihosting.c)
|
||||
//
|
||||
// If a debugger were connected, this would have resulted in a CPU halt,
|
||||
// and the debugger would have serviced the the semihosting call.
|
||||
//
|
||||
// However, the semihosting function was called without a debugger being
|
||||
// attached. The best course of action is to simply return from the trap
|
||||
// and let the semihosting function continue after the call to EBREAK to
|
||||
// prevent the CPU from hanging in the trap handler.
|
||||
write_csr(mepc, mepc + 4);
|
||||
|
||||
// Set a global variable to tell the semihosting code the the semihosting
|
||||
// call
|
||||
// didn't execute on the host.
|
||||
sh_missing_host = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// EBREAK was not part of a semihosting call. This should not have happened.
|
||||
// Hang forever.
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Trap was issued for another reason than an EBREAK.
|
||||
// Replace the code below with whatever trap handler you'd normally use. (e.g.
|
||||
// interrupt processing.)
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user