Compare commits

..

4 Commits

100 changed files with 5862 additions and 229 deletions

3
.gitignore vendored
View File

@ -151,6 +151,3 @@ compile_commands.json
CTestTestfile.cmake CTestTestfile.cmake
*.dump *.dump
.vscode/c_cpp_properties.json
semihosting_test/build/semihosting_test
semihosting_test/build/Makefile

7
.gitmodules vendored
View File

@ -1,6 +1,7 @@
[submodule "cm"]
path = benchmarks/coremark/cm
url = https://github.com/eembc/coremark.git
[submodule "benchmarks/coremark/cm"] [submodule "benchmarks/coremark/cm"]
path = benchmarks/coremark/cm path = benchmarks/coremark/cm
url = https://github.com/eembc/coremark.git url = https://github.com/eembc/coremark.git
[submodule "bare-metal-bsp"]
path = bare-metal-bsp
url = https://git.minres.com/Firmware/MNRS-BM-BSP.git

View File

@ -4,8 +4,15 @@ endif()
if (NOT DEFINED ISA) if (NOT DEFINED ISA)
set(ISA imc) set(ISA imc)
endif() endif()
message(STATUS "Building firmware using ${BOARD} board configuration and isa ${ISA}") add_custom_target(fw-hello-world ALL
add_custom_target(fw-common ALL COMMAND make -C ${riscvfw_SOURCE_DIR}/hello-world BOARD=${BOARD} ISA=${ISA}
COMMAND make -C hello-world BOARD=${BOARD} ISA=${ISA} && make -C benchmarks/dhrystone BOARD=${BOARD} ISA=${ISA} && make -C benchmarks/coremark BOARD=${BOARD} ISA=${ISA} USES_TERMINAL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(fw-dhrystone ALL
COMMAND make -C ${riscvfw_SOURCE_DIR}/benchmarks/dhrystone BOARD=${BOARD} ISA=${ISA}
USES_TERMINAL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(fw-coremark ALL
COMMAND make -C ${riscvfw_SOURCE_DIR}/benchmarks/coremark/cm PORT_DIR=../tgc BOARD=${BOARD} ISA=${ISA}
USES_TERMINAL USES_TERMINAL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

81
Jenkinsfile vendored
View File

@ -1,81 +0,0 @@
void checkout_project() {
checkout([
$class: 'GitSCM',
branches: [
[name: '*/main']
],
extensions: [
[$class: 'CleanBeforeCheckout'],
[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]
],
submoduleCfg: [],
userRemoteConfigs: [
[credentialsId: 'gitea-jenkins', url: 'https://git.minres.com/Firmware/Firmwares.git']
]
])
}
void checkout_develop() {
dir("bare-metal-bsp") {
withCredentials([usernamePassword(credentialsId: 'gitea-jenkins', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')]) {
sh ("git pull origin develop")
}
}
//sh("cd bare-metal-bsp && git checkout develop")
}
void make_hello(board) {
sh("make -C hello-world/ BOARD=${board}")
sh("make -C hello-world/ clean")
}
pipeline {
agent { docker {
image 'ubuntu-riscv'
args '-v $HOME/.m2:/root/.m2'
}}
options {
// using the Timestamper plugin we can add timestamps to the console log
timestamps()
skipStagesAfterUnstable()
}
stages {
/*stage('checkout repo') { steps{ checkout_project()}}
stage('checkout develop') { steps{ checkout_develop()}}
stage('make iss') {steps { make_hello("iss")}}
stage('make hifive1') {steps { make_hello("hifive1")}}
stage('make TGC5L') {steps { make_hello("TGC5L")}}
stage('make rtl') {steps { make_hello("rtl")}}
stage('make ehrenberg') {steps { make_hello("ehrenberg")}}
stage('make tgc_vp') {steps { make_hello("tgc_vp")}}*/
stage('make hello-world') {
matrix {
axes {
axis{
name 'BOARD'
values 'iss', 'hifive1', 'TGCP', 'ehrenberg', 'rtl', 'tgc_vp'
}
}
stages {
stage('Force sequential') {
options {
lock("One Board at a time")
}
stages {
stage("make") {
steps {
make_hello("${BOARD}")
}
}
}
}
}
}
}
}
post {
failure {
sh("make -C hello-world/ clean")
}
}
}

View File

@ -1,25 +1,2 @@
# MINRES Firmware Repository # Firmware
## Structure
This repository comes with several executables ready to be built, such as `hello-world` or `coremark` and `dhrystone` in the `benchmark` directory.
Creating the executables in the easiest way possible is done by calling `make`in the corresponding directory.
## Prerequisite
This repository requires `riscv64-unknown-elf-gcc` to be located in `$PATH`.
## How to Use
When compiling executables, the target platform needs to be specified using the 'BOARD' variable. When compiling for the TGC5C for example, use `make BOARD=tgc_vp`, when compiling for RTL `make BOARD=rtl`. The default value for the Board variable is 'iss'.
The arch can be set with the 'ISA' variable, the default value is 'imc'.
When compiling for the TGC5A VP for example, the call to create the correct binary is the following:
```
make BOARD=tgc_vp ISA=e
```
## Useful information
Using `bear -- <build-command>` will cause a compile_commands.json to be emitted. This allows using completion tools like clangd.
## Current Limitations
Currently, this repository only supports creation of 32-bit executables (Even when setting the `RISCV_ARCH` and `RISCV_ABI` manually).
Compiling for the 'e' extension / ISA together with any other extension (`ISA=emc` for example), requires setting the `RISCV_ABI=ilp32e` explicitly.
When switching ABI or ARCH ensure that object files in the corresponding 'env' dir in the 'bare-metal-bsp' submodule are removed, so they get created with the appropriate flags (namely the 'init.o' file).

@ -1 +0,0 @@
Subproject commit 87dc0ec2304adcb94a25b397a357aadae1304867

View File

@ -0,0 +1,163 @@
// See LICENSE for license details.
#include "sifive/devices/clic.h"
#include "clic/clic_driver.h"
#include "platform.h"
#include "encoding.h"
#include <string.h>
void volatile_memzero(uint8_t * base, unsigned int size) {
volatile uint8_t * ptr;
for (ptr = base; ptr < (base + size); ptr++){
*ptr = 0;
}
}
// Note that there are no assertions or bounds checking on these
// parameter values.
void clic_init (
clic_instance_t * this_clic,
uintptr_t hart_addr,
interrupt_function_ptr_t* vect_table,
interrupt_function_ptr_t default_handler,
uint32_t num_irq,
uint32_t num_config_bits
)
{
this_clic->hart_addr= hart_addr;
this_clic->vect_table= vect_table;
this_clic->num_config_bits= num_config_bits;
//initialize vector table
for(int i=0;i++;i<num_irq) {
this_clic->vect_table[i] = default_handler;
}
//set base vectors
write_csr(mtvt, vect_table);
//clear all interrupt enables and pending
volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIE), num_irq);
volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIP), num_irq);
//clear nlbits and nvbits; all interrupts trap to level 15
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG)=0;
}
void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler) {
this_clic->vect_table[source] = handler;
}
void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source) {
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 1;
}
void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 0;
}
void clic_set_pending(clic_instance_t * this_clic, uint32_t source){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 1;
}
void clic_clear_pending(clic_instance_t * this_clic, uint32_t source){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 0;
}
void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source) = intcfg;
}
uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source){
return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source);
}
void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG) = cfg;
}
uint8_t clic_get_cliccfg (clic_instance_t * this_clic){
return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG);
}
//sets an interrupt level based encoding of nmbits, nlbits
uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level) {
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
//shift level right to mask off unused bits
level = level>>((this_clic->num_config_bits)-nlbits); //plus this_clic->nmbits which is always 0 for now.
//shift level into correct bit position
level = level << (8-this_clic->num_config_bits) + (this_clic->num_config_bits - nlbits);
//write to clicintcfg
uint8_t current_intcfg = clic_get_intcfg(this_clic, source);
clic_set_intcfg(this_clic, source, (current_intcfg | level));
return level;
}
//gets an interrupt level based encoding of nmbits, nlbits
uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source) {
uint8_t level;
level = clic_get_intcfg(this_clic, source);
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
//shift level
level = level >> (8-(this_clic->num_config_bits));
//shift level right to mask off priority bits
level = level>>(this_clic->num_config_bits-nlbits); //this_clic->nmbits which is always 0 for now.
return level;
}
//sets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority) {
//priority bits = num_config_bits - nlbits
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
uint8_t priority_bits = this_clic->num_config_bits-nlbits;
if(priority_bits = 0) {
//no bits to set
return 0;
}
//mask off unused bits
priority = priority >> (8-priority_bits);
//shift into the correct bit position
priority = priority << (8-(this_clic->num_config_bits));
//write to clicintcfg
uint8_t current_intcfg = clic_get_intcfg(this_clic, source);
clic_set_intcfg(this_clic, source, (current_intcfg | priority));
return current_intcfg;
}
//gets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source) {
uint8_t priority;
priority = clic_get_intcfg(this_clic, source);
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
//shift left to mask off level bits
priority = priority << nlbits;
//shift priority
priority = priority >> (8-((this_clic->num_config_bits)+nlbits));
return priority;
}

View File

@ -0,0 +1,44 @@
// See LICENSE file for licence details
#ifndef PLIC_DRIVER_H
#define PLIC_DRIVER_H
__BEGIN_DECLS
#include "platform.h"
typedef void (*interrupt_function_ptr_t) (void);
typedef struct __clic_instance_t
{
uintptr_t hart_addr;
interrupt_function_ptr_t* vect_table;
uint32_t num_config_bits;
uint32_t num_sources;
} clic_instance_t;
// Note that there are no assertions or bounds checking on these
// parameter values.
void clic_init (clic_instance_t * this_clic, uintptr_t hart_addr, interrupt_function_ptr_t* vect_table, interrupt_function_ptr_t default_handler, uint32_t num_irq,uint32_t num_config_bits);
void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler);
void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source);
void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source);
void clic_set_pending(clic_instance_t * this_clic, uint32_t source);
void clic_clear_pending(clic_instance_t * this_clic, uint32_t source);
void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg);
uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source);
void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg);
uint8_t clic_get_cliccfg (clic_instance_t * this_clic);
//sets an interrupt level based encoding of nmbits, nlbits
uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level);
//get an interrupt level based encoding of nmbits, nlbits
uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source);
//sets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority);
//sets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source);
__END_DECLS
#endif

View File

@ -0,0 +1,252 @@
// See LICENSE file for license details
#include "platform.h"
#ifdef PRCI_CTRL_ADDR
#include "fe300prci/fe300prci_driver.h"
#include <unistd.h>
#define rdmcycle(x) { \
uint32_t lo, hi, hi2; \
__asm__ __volatile__ ("1:\n\t" \
"csrr %0, mcycleh\n\t" \
"csrr %1, mcycle\n\t" \
"csrr %2, mcycleh\n\t" \
"bne %0, %2, 1b\n\t" \
: "=r" (hi), "=r" (lo), "=r" (hi2)) ; \
*(x) = lo | ((uint64_t) hi << 32); \
}
uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq)
{
uint32_t start_mtime = CLINT_REG(CLINT_MTIME);
uint32_t end_mtime = start_mtime + mtime_ticks + 1;
// Make sure we won't get rollover.
while (end_mtime < start_mtime){
start_mtime = CLINT_REG(CLINT_MTIME);
end_mtime = start_mtime + mtime_ticks + 1;
}
// Don't start measuring until mtime edge.
uint32_t tmp = start_mtime;
do {
start_mtime = CLINT_REG(CLINT_MTIME);
} while (start_mtime == tmp);
uint64_t start_mcycle;
rdmcycle(&start_mcycle);
while (CLINT_REG(CLINT_MTIME) < end_mtime) ;
uint64_t end_mcycle;
rdmcycle(&end_mcycle);
uint32_t difference = (uint32_t) (end_mcycle - start_mcycle);
uint64_t freq = ((uint64_t) difference * mtime_freq) / mtime_ticks;
return (uint32_t) freq & 0xFFFFFFFF;
}
void PRCI_use_hfrosc(int div, int trim)
{
// Make sure the HFROSC is running at its default setting
// It is OK to change this even if we are running off of it.
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);
}
void PRCI_use_pll(int refsel, int bypass,
int r, int f, int q, int finaldiv,
int hfroscdiv, int hfrosctrim)
{
// 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
PRCI_use_hfrosc(4, 16);
}
// Set PLL Source to be HFXOSC if desired.
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 {
// To overclock, use the hfrosc
if (hfrosctrim >= 0 && hfroscdiv >= 0) {
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
}
// Set DIV Settings for PLL
// (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:
if (finaldiv == 1){
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
} else {
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV(finaldiv-1));
}
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 = CLINT_REG(CLINT_MTIME);
while (CLINT_REG(CLINT_MTIME) - 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);
// If we're running off HFXOSC, turn off the HFROSC to
// save power.
if (refsel) {
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
}
}
void PRCI_use_default_clocks()
{
// Turn off the LFROSC
AON_REG(AON_LFROSC) &= ~ROSC_EN(1);
// Use HFROSC
PRCI_use_hfrosc(4, 16);
}
void PRCI_use_hfxosc(uint32_t finaldiv)
{
PRCI_use_pll(1, // Use HFXTAL
1, // Bypass = 1
0, // PLL settings don't matter
0, // PLL settings don't matter
0, // PLL settings don't matter
finaldiv,
-1,
-1);
}
// This is a generic function, which
// doesn't span the entire range of HFROSC settings.
// It only adjusts the trim, which can span a hundred MHz or so.
// This function does not check the legality of the PLL settings
// at all, and it is quite possible to configure invalid PLL settings
// this way.
// It returns the actual measured CPU frequency.
uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target )
{
uint32_t hfrosctrim = 0;
uint32_t hfroscdiv = 4;
uint32_t prev_trim = 0;
// In this function we use PLL settings which
// will give us a 32x multiplier from the output
// of the HFROSC source to the output of the
// PLL. We first measure our HFROSC to get the
// right trim, then finally use it as the PLL source.
// We should really check here that the f_cpu
// requested is something in the limit of the PLL. For
// now that is up to the user.
// This will undershoot for frequencies not divisible by 16.
uint32_t desired_hfrosc_freq = (f_cpu/ 16);
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
// Ignore the first run (for icache reasons)
uint32_t cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
uint32_t prev_freq = cpu_freq;
while ((cpu_freq < desired_hfrosc_freq) && (hfrosctrim < 0x1F)){
prev_trim = hfrosctrim;
prev_freq = cpu_freq;
hfrosctrim ++;
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
}
// We couldn't go low enough
if (prev_freq > desired_hfrosc_freq){
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}
// We couldn't go high enough
if (cpu_freq < desired_hfrosc_freq){
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}
// Check for over/undershoot
switch(target) {
case(PRCI_FREQ_CLOSEST):
if ((desired_hfrosc_freq - prev_freq) < (cpu_freq - desired_hfrosc_freq)) {
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
} else {
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, hfrosctrim);
}
break;
case(PRCI_FREQ_UNDERSHOOT):
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
break;
default:
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, hfrosctrim);
}
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}
#endif

View File

@ -0,0 +1,79 @@
// See LICENSE file for license details
#ifndef _FE300PRCI_DRIVER_H_
#define _FE300PRCI_DRIVER_H_
__BEGIN_DECLS
#include <unistd.h>
typedef enum prci_freq_target {
PRCI_FREQ_OVERSHOOT,
PRCI_FREQ_CLOSEST,
PRCI_FREQ_UNDERSHOOT
} PRCI_freq_target;
/* Measure and return the approximate frequency of the
* CPU, as given by measuring the mcycle counter against
* the mtime ticks.
*/
uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq);
/* Safely switch over to the HFROSC using the given div
* and trim settings.
*/
void PRCI_use_hfrosc(int div, int trim);
/* Safely switch over to the 16MHz HFXOSC,
* applying the finaldiv clock divider (1 is the lowest
* legal value).
*/
void PRCI_use_hfxosc(uint32_t finaldiv);
/* Safely switch over to the PLL using the given
* settings.
*
* Note that not all combinations of the inputs are actually
* legal, and this function does not check for their
* legality ("safely" means that this function won't turn off
* or glitch the clock the CPU is actually running off, but
* doesn't protect against you making it too fast or slow.)
*/
void PRCI_use_pll(int refsel, int bypass,
int r, int f, int q, int finaldiv,
int hfroscdiv, int hfrosctrim);
/* Use the default clocks configured at reset.
* This is ~16Mhz HFROSC and turns off the LFROSC
* (on the current FE310 Dev Platforms, an external LFROSC is
* used as it is more power efficient).
*/
void PRCI_use_default_clocks();
/* This routine will adjust the HFROSC trim
* while using HFROSC as the clock source,
* measure the resulting frequency, then
* use it as the PLL clock source,
* in an attempt to get over, under, or close to the
* requested frequency. It returns the actual measured
* frequency.
*
* Note that the requested frequency must be within the
* range supported by the PLL so not all values are
* achievable with this function, and not all
* are guaranteed to actually work. The PLL
* is rated higher than the hardware.
*
* There is no check on the desired f_cpu frequency, it
* is up to the user to specify something reasonable.
*/
uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target);
__END_DECLS
#endif

View File

@ -0,0 +1,127 @@
// See LICENSE for license details.
#include "sifive/devices/plic.h"
#include "plic/plic_driver.h"
#include "platform.h"
#include "encoding.h"
#include <string.h>
// Note that there are no assertions or bounds checking on these
// parameter values.
void volatile_memzero(uint8_t * base, unsigned int size)
{
volatile uint8_t * ptr;
for (ptr = base; ptr < (base + size); ptr++){
*ptr = 0;
}
}
void PLIC_init (
plic_instance_t * this_plic,
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
)
{
this_plic->base_addr = base_addr;
this_plic->num_sources = num_sources;
this_plic->num_priorities = num_priorities;
// Disable all interrupts (don't assume that these registers are reset).
unsigned long hart_id = read_csr(mhartid);
volatile_memzero((uint8_t*) (this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
(num_sources + 8) / 8);
// Set all priorities to 0 (equal priority -- don't assume that these are reset).
volatile_memzero ((uint8_t *)(this_plic->base_addr +
PLIC_PRIORITY_OFFSET),
(num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);
// Set the threshold to 0.
volatile plic_threshold* threshold = (plic_threshold*)
(this_plic->base_addr +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold = 0;
}
void PLIC_set_threshold (plic_instance_t * this_plic,
plic_threshold threshold){
unsigned long hart_id = read_csr(mhartid);
volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold_ptr = threshold;
}
void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
unsigned long hart_id = read_csr(mhartid);
volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
(source >> 3));
uint8_t current = *current_ptr;
current = current | ( 1 << (source & 0x7));
*current_ptr = current;
}
void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){
unsigned long hart_id = read_csr(mhartid);
volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
(source >> 3));
uint8_t current = *current_ptr;
current = current & ~(( 1 << (source & 0x7)));
*current_ptr = current;
}
void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority){
if (this_plic->num_priorities > 0) {
volatile plic_priority * priority_ptr = (volatile plic_priority *)
(this_plic->base_addr +
PLIC_PRIORITY_OFFSET +
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
*priority_ptr = priority;
}
}
plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
unsigned long hart_id = read_csr(mhartid);
volatile plic_source * claim_addr = (volatile plic_source * )
(this_plic->base_addr +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
return *claim_addr;
}
void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){
unsigned long hart_id = read_csr(mhartid);
volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
*claim_addr = source;
}

View File

@ -0,0 +1,51 @@
// See LICENSE file for licence details
#ifndef PLIC_DRIVER_H
#define PLIC_DRIVER_H
__BEGIN_DECLS
#include "platform.h"
typedef struct __plic_instance_t
{
uintptr_t base_addr;
uint32_t num_sources;
uint32_t num_priorities;
} plic_instance_t;
typedef uint32_t plic_source;
typedef uint32_t plic_priority;
typedef uint32_t plic_threshold;
void PLIC_init (
plic_instance_t * this_plic,
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
);
void PLIC_set_threshold (plic_instance_t * this_plic,
plic_threshold threshold);
void PLIC_enable_interrupt (plic_instance_t * this_plic,
plic_source source);
void PLIC_disable_interrupt (plic_instance_t * this_plic,
plic_source source);
void PLIC_set_priority (plic_instance_t * this_plic,
plic_source source,
plic_priority priority);
plic_source PLIC_claim_interrupt(plic_instance_t * this_plic);
void PLIC_complete_interrupt(plic_instance_t * this_plic,
plic_source source);
__END_DECLS
#endif

1
bare-metal-bsp/env/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.o

1
bare-metal-bsp/env/TGC5L/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.o

121
bare-metal-bsp/env/TGC5L/init.c vendored Normal file
View File

@ -0,0 +1,121 @@
#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)
{
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()
{
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 10000000;
}
void init_pll(void){
}
#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 {
char* result = "trap 0\n";
result[5]=(mcause&0xff)+'0';
//write(1, "trap\n", 5);
write(1, result, 7);
_exit(1 + mcause);
}
return epc;
}
void _init()
{
#ifndef NO_INIT
init_pll();
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()
{
}
int is_uart_ready(int uart_id){
return 1;
}
int try_write_uart_char(int uart_id, char c){
*((char*)0x10000000) = c;
return 1;
}
void write_uart_char(int uart_id, char c){
*((char*)0x10000000) = c;
}

174
bare-metal-bsp/env/TGC5L/link.lds vendored Normal file
View File

@ -0,0 +1,174 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x00000000, LENGTH = 256M
ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 1M
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram 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
.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
.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 = . );
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 = 0xfffffff0 );
PROVIDE( fromhost = 0xfffffff8 );
}

32
bare-metal-bsp/env/TGC5L/platform.h vendored Normal file
View File

@ -0,0 +1,32 @@
// See LICENSE for license details.
#ifndef _ISS_PLATFORM_H
#define _ISS_PLATFORM_H
// Some things missing from the official encoding.h
#define MCAUSE_INT 0x80000000
#define MCAUSE_CAUSE 0x7FFFFFFF
#include "rtl/const.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
#define MEM_BASE_ADDR _AC(0x00000000,UL)
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
// Misc
#include <stdint.h>
void init_pll(void);
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
int is_uart_ready(int uart_id);
int try_write_uart_char(int uart_id, char);
void write_uart_char(int uart_id, char);
#endif /* _ISS_PLATFORM_H */

72
bare-metal-bsp/env/common-clang.mk vendored Normal file
View File

@ -0,0 +1,72 @@
# See LICENSE for license details.
ifndef _SIFIVE_MK_COMMON
_SIFIVE_MK_COMMON := # defined
.PHONY: all
all: $(TARGET)
include $(BSP_BASE)/libwrap/libwrap.mk
ENV_DIR = $(BSP_BASE)/env
PLATFORM_DIR = $(ENV_DIR)/$(BOARD)
ASM_SRCS += $(ENV_DIR)/start.S
ASM_SRCS += $(ENV_DIR)/entry.S
C_SRCS += $(PLATFORM_DIR)/init.c
LINKER_SCRIPT := $(PLATFORM_DIR)/$(LINK_TARGET).lds
INCLUDES += -I$(BSP_BASE)/include
INCLUDES += -I$(BSP_BASE)/drivers/
INCLUDES += -I$(ENV_DIR)
INCLUDES += -I$(PLATFORM_DIR)
TOOL_DIR ?= $(BSP_BASE)/../toolchain/bin/
LDFLAGS += -T $(LINKER_SCRIPT) -nostartfiles
LDFLAGS += -L$(ENV_DIR) --specs=nano.specs
ASM_OBJS := $(ASM_SRCS:.S=.o)
C_OBJS := $(C_SRCS:.c=.o)
CXX_OBJS := $(CXX_SRCS:.cpp=.o)
LINK_OBJS += $(ASM_OBJS) $(C_OBJS) $(CXX_OBJS)
LINK_DEPS += $(LINKER_SCRIPT)
CLEAN_OBJS += $(TARGET) $(LINK_OBJS)
CFLAGS += -march=$(RISCV_ARCH)
CFLAGS += -mabi=$(RISCV_ABI)
CFLAGS += -mcmodel=medany
TRIPLET?=riscv32
CXX=$(LLVM_TOOL_DIR)clang++ --target=$(TRIPLET) -isystem $(TOOL_DIR)/../$(TRIPLET)/include
CC=$(LLVM_TOOL_DIR)clang --target=$(TRIPLET) -isystem $(TOOL_DIR)/../$(TRIPLET)/include
LD=$(TOOL_DIR)$(TRIPLET)-gcc
AR=$(TOOL_DIR)$(TRIPLET)-ar
OBJDUMP := $(TOOL_DIR)/$(TRIPLET)-objdump
$(TARGET): $(LINK_OBJS) $(LINK_DEPS)
$(LD) $(LINK_OBJS) $(LDFLAGS) $(LIBWRAP) -o $@
$(OBJDUMP) -d -S $(TARGET) > $(TARGET).dis
$(ASM_OBJS): %.o: %.S $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
$(C_OBJS): %.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $<
$(CXX_OBJS): %.o: %.cpp $(HEADERS)
$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $<
.PHONY: clean
clean:
rm -f $(TARGET) $(LINK_OBJS)
.PHONY: clean-all
clean-all:
rm -f $(CLEAN_OBJS) $(LIBWRAP)
endif

74
bare-metal-bsp/env/common-gcc.mk vendored Normal file
View File

@ -0,0 +1,74 @@
ifndef _MK_COMMON
_MK_COMMON := # defined
.PHONY: all
all: $(TARGET)
include $(BSP_BASE)/libwrap/libwrap.mk
BOARD?=iss
ENV_DIR = $(BSP_BASE)/env
PLATFORM_DIR = $(ENV_DIR)/$(BOARD)
ASM_SRCS += $(ENV_DIR)/start.S
ASM_SRCS += $(ENV_DIR)/entry.S
C_SRCS += $(PLATFORM_DIR)/init.c
LINKER_SCRIPT := $(PLATFORM_DIR)/$(LINK_TARGET).lds
INCLUDES += -I$(BSP_BASE)/include
INCLUDES += -I$(BSP_BASE)/drivers/
INCLUDES += -I$(ENV_DIR)
INCLUDES += -I$(PLATFORM_DIR)
TOOL_DIR ?= $(BSP_BASE)/../toolchain/bin/
LDFLAGS += -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI)
LDFLAGS += -T $(LINKER_SCRIPT) -Wl,-Map=$(TARGET).map -nostartfiles
LDFLAGS += -L$(ENV_DIR)
# --specs=nano.specs
ASM_OBJS := $(ASM_SRCS:.S=.o)
C_OBJS := $(C_SRCS:.c=.o)
CXX_OBJS := $(CXX_SRCS:.cpp=.o)
LINK_OBJS += $(ASM_OBJS) $(C_OBJS) $(CXX_OBJS)
LINK_DEPS += $(LINKER_SCRIPT)
CLEAN_OBJS += $(TARGET) $(LINK_OBJS)
GCCVERSION = $(shell $(CC) --version | grep gcc | awk '{print($NF);}')
ifeq ($(GCCVERSION),9.2)
CFLAGS += -march=$(RISCV_ARCH)
else
CFLAGS += -march=$(RISCV_ARCH)_zicsr_zifencei
endif
CFLAGS += -mabi=$(RISCV_ABI)
CFLAGS += -mcmodel=medany
TRIPLET?=riscv64-unknown-elf
CXX=$(TOOL_DIR)$(TRIPLET)-c++
CC=$(TOOL_DIR)$(TRIPLET)-gcc
LD=$(TOOL_DIR)$(TRIPLET)-gcc
AR=$(TOOL_DIR)$(TRIPLET)-ar
OBJDUMP := $(TOOL_DIR)$(TRIPLET)-objdump
$(TARGET): $(LINK_OBJS) $(LINK_DEPS)
$(LD) $(LINK_OBJS) $(LDFLAGS) -o $@
$(OBJDUMP) -d -S $(TARGET) > $(TARGET).dis
$(ASM_OBJS): %.o: %.S $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
$(C_OBJS): %.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $<
$(CXX_OBJS): %.o: %.cpp $(HEADERS)
$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $<
.PHONY: clean
clean:
rm -f $(CLEAN_OBJS) $(LIBWRAP)
endif

1313
bare-metal-bsp/env/encoding.h vendored Normal file

File diff suppressed because it is too large Load Diff

99
bare-metal-bsp/env/entry.S vendored Normal file
View File

@ -0,0 +1,99 @@
// See LICENSE for license details
#ifndef ENTRY_S
#define ENTRY_S
#include "encoding.h"
#include "rtl/bits.h"
.section .text.entry
.align 2
.global trap_entry
trap_entry:
addi sp, sp, -32*REGBYTES
STORE x1, 1*REGBYTES(sp)
STORE x2, 2*REGBYTES(sp)
STORE x3, 3*REGBYTES(sp)
STORE x4, 4*REGBYTES(sp)
STORE x5, 5*REGBYTES(sp)
STORE x6, 6*REGBYTES(sp)
STORE x7, 7*REGBYTES(sp)
STORE x8, 8*REGBYTES(sp)
STORE x9, 9*REGBYTES(sp)
STORE x10, 10*REGBYTES(sp)
STORE x11, 11*REGBYTES(sp)
STORE x12, 12*REGBYTES(sp)
STORE x13, 13*REGBYTES(sp)
STORE x14, 14*REGBYTES(sp)
STORE x15, 15*REGBYTES(sp)
#ifndef __riscv_abi_rve
STORE x16, 16*REGBYTES(sp)
STORE x17, 17*REGBYTES(sp)
STORE x18, 18*REGBYTES(sp)
STORE x19, 19*REGBYTES(sp)
STORE x20, 20*REGBYTES(sp)
STORE x21, 21*REGBYTES(sp)
STORE x22, 22*REGBYTES(sp)
STORE x23, 23*REGBYTES(sp)
STORE x24, 24*REGBYTES(sp)
STORE x25, 25*REGBYTES(sp)
STORE x26, 26*REGBYTES(sp)
STORE x27, 27*REGBYTES(sp)
STORE x28, 28*REGBYTES(sp)
STORE x29, 29*REGBYTES(sp)
STORE x30, 30*REGBYTES(sp)
STORE x31, 31*REGBYTES(sp)
#endif
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call handle_trap
csrw mepc, a0
# Remain in M-mode after mret
li t0, MSTATUS_MPP
csrs mstatus, t0
LOAD x1, 1*REGBYTES(sp)
LOAD x2, 2*REGBYTES(sp)
LOAD x3, 3*REGBYTES(sp)
LOAD x4, 4*REGBYTES(sp)
LOAD x5, 5*REGBYTES(sp)
LOAD x6, 6*REGBYTES(sp)
LOAD x7, 7*REGBYTES(sp)
LOAD x8, 8*REGBYTES(sp)
LOAD x9, 9*REGBYTES(sp)
LOAD x10, 10*REGBYTES(sp)
LOAD x11, 11*REGBYTES(sp)
LOAD x12, 12*REGBYTES(sp)
LOAD x13, 13*REGBYTES(sp)
LOAD x14, 14*REGBYTES(sp)
LOAD x15, 15*REGBYTES(sp)
#ifndef __riscv_abi_rve
LOAD x16, 16*REGBYTES(sp)
LOAD x17, 17*REGBYTES(sp)
LOAD x18, 18*REGBYTES(sp)
LOAD x19, 19*REGBYTES(sp)
LOAD x20, 20*REGBYTES(sp)
LOAD x21, 21*REGBYTES(sp)
LOAD x22, 22*REGBYTES(sp)
LOAD x23, 23*REGBYTES(sp)
LOAD x24, 24*REGBYTES(sp)
LOAD x25, 25*REGBYTES(sp)
LOAD x26, 26*REGBYTES(sp)
LOAD x27, 27*REGBYTES(sp)
LOAD x28, 28*REGBYTES(sp)
LOAD x29, 29*REGBYTES(sp)
LOAD x30, 30*REGBYTES(sp)
LOAD x31, 31*REGBYTES(sp)
#endif
addi sp, sp, 32*REGBYTES
mret
.weak handle_trap
handle_trap:
1:
j 1b
#endif

81
bare-metal-bsp/env/hifive1.h vendored Normal file
View File

@ -0,0 +1,81 @@
// 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
bare-metal-bsp/env/hifive1/dhrystone.lds vendored Normal file
View File

@ -0,0 +1,157 @@
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
bare-metal-bsp/env/hifive1/init.c vendored Normal file
View File

@ -0,0 +1,238 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "../hifive1/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()
{
}

169
bare-metal-bsp/env/hifive1/link.lds vendored Normal file
View File

@ -0,0 +1,169 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 1M
}
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
PROVIDE( tohost = 0xfffffff0 );
PROVIDE( fromhost = 0xfffffff8 );
}

34
bare-metal-bsp/env/hifive1/openocd.cfg vendored Normal file
View File

@ -0,0 +1,34 @@
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
bare-metal-bsp/env/hifive1/platform.h vendored Normal file
View File

@ -0,0 +1,133 @@
// 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 "sifive/const.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 */

View File

@ -0,0 +1,3 @@
# Describes the CPU on this board to the rest of the SDK.
RISCV_ARCH := rv32imac
RISCV_ABI := ilp32

1
bare-metal-bsp/env/iss/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.o

107
bare-metal-bsp/env/iss/init.c vendored Normal file
View File

@ -0,0 +1,107 @@
#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)
{
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()
{
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 10000000;
}
void init_pll(void){
}
#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
init_pll();
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()
{
}

174
bare-metal-bsp/env/iss/link.lds vendored Normal file
View File

@ -0,0 +1,174 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x00000020, LENGTH = 1M
ram (wxa!ri) : ORIGIN = 0x10000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram 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
.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
.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 = . );
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 = 0xfffffff0 );
PROVIDE( fromhost = 0xfffffff8 );
}

31
bare-metal-bsp/env/iss/platform.h vendored Normal file
View File

@ -0,0 +1,31 @@
// See LICENSE for license details.
#ifndef _ISS_PLATFORM_H
#define _ISS_PLATFORM_H
// Some things missing from the official encoding.h
#define MCAUSE_INT 0x80000000
#define MCAUSE_CAUSE 0x7FFFFFFF
#define USE_TOHOST 1
#include "rtl/const.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
#define MEM_BASE_ADDR _AC(0x00000000,UL)
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
// Misc
#include <stdint.h>
void init_pll(void);
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
#endif /* _ISS_PLATFORM_H */

1
bare-metal-bsp/env/rtl/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.o

107
bare-metal-bsp/env/rtl/init.c vendored Normal file
View File

@ -0,0 +1,107 @@
#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)
{
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()
{
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 10000000;
}
void init_pll(void){
}
#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
init_pll();
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()
{
}

175
bare-metal-bsp/env/rtl/link.lds vendored Normal file
View File

@ -0,0 +1,175 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x00000000, LENGTH = 1M
ram (wxa!ri) : ORIGIN = 0x10000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram 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
.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
.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 = . );
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 = 0x00018000 );
PROVIDE( tohost = 0xfffffff0 );
PROVIDE( fromhost = 0xfffffff8 );
}

30
bare-metal-bsp/env/rtl/platform.h vendored Normal file
View File

@ -0,0 +1,30 @@
// See LICENSE for license details.
#ifndef _ISS_PLATFORM_H
#define _ISS_PLATFORM_H
// Some things missing from the official encoding.h
#define MCAUSE_INT 0x80000000
#define MCAUSE_CAUSE 0x7FFFFFFF
#include "rtl/const.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
#define MEM_BASE_ADDR _AC(0x00000000,UL)
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
// Misc
#include <stdint.h>
void init_pll(void);
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
#endif /* _ISS_PLATFORM_H */

60
bare-metal-bsp/env/start.S vendored Normal file
View File

@ -0,0 +1,60 @@
// See LICENSE for license details.
.section .init
.globl _start
.type _start,@function
_start:
la gp, trap_entry
csrw mtvec, gp
.option push
.option norelax
la gp, __global_pointer$
.option pop
la sp, _sp
/* Load data section */
la a0, _data_lma
la a1, _data
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
addi a0, a0, 4
sw t0, (a1)
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Clear bss section */
la a0, __bss_start
la a1, _end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
/* Call global constructors */
//#ifdef HAVE_INIT_FINI
la a0, __libc_fini_array
call atexit
call __libc_init_array
//#endif
#ifndef __riscv_float_abi_soft
/* Enable FPU */
li t0, MSTATUS_FS
csrs mstatus, t0
csrr t1, mstatus
and t1, t1, t0
beqz t1, 1f
fssr x0
1:
#endif
/* argc = argv = 0 */
li a0, 0
li a1, 0
call main
tail _exit

View File

@ -0,0 +1,22 @@
/*
* bsp.h
*
* Created on: 30.07.2018
* Author: eyck
*/
#ifndef BSP_H_
#define BSP_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <fe300prci/fe300prci_driver.h>
#include <platform.h>
#include <encoding.h>
extern void trap_entry();
#ifdef __cplusplus
}
#endif
#endif /* BSP_H_ */

View File

@ -0,0 +1,35 @@
#ifndef _RISCV_BITS_H
#define _RISCV_BITS_H
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
#define ROUNDDOWN(a, b) ((a)/(b)*(b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
#define STR(x) XSTR(x)
#define XSTR(x) #x
#ifdef __riscv64
# define SLL32 sllw
# define STORE sd
# define LOAD ld
# define LWU lwu
# define LOG_REGBYTES 3
#else
# define SLL32 sll
# define STORE sw
# define LOAD lw
# define LWU lw
# define LOG_REGBYTES 2
#endif
#define REGBYTES (1 << LOG_REGBYTES)
#endif

View File

@ -0,0 +1,27 @@
#ifndef _RTL_CONST_H
#define _RTL_CONST_H
#ifdef __ASSEMBLER__
#define _AC(X,Y) X
#define _AT(T,X) X
#else
#define _AC(X,Y) (X##Y)
#define _AT(T,X) ((T)(X))
#endif /* !__ASSEMBLER__*/
#define _BITUL(x) (_AC(1,UL) << (x))
#define _BITULL(x) (_AC(1,ULL) << (x))
#define UART0_BASE_ADDR 0xffff0000ULL
#define UART_REG_TXFIFO 0x00
#define UART_REG_RXFIFO 0x04
#define UART_REG_TXCTRL 0x08
#define UART_REG_RXCTRL 0x0c
#define UART_REG_IE 0x10
#define UART_REG_IP 0x14
#define UART_REG_DIV 0x18
#define UART_TXEN 0x1
#define UART0_REG(ADDR) *((volatile uint32_t*) (UART0_BASE_ADDR + ADDR))
#endif /* _RTL_CONST_H */

View File

@ -0,0 +1,16 @@
#ifndef _SECTIONS_H
#define _SECTIONS_H
extern unsigned char _rom[];
extern unsigned char _rom_end[];
extern unsigned char _ram[];
extern unsigned char _ram_end[];
extern unsigned char _ftext[];
extern unsigned char _etext[];
extern unsigned char _fbss[];
extern unsigned char _ebss[];
extern unsigned char _end[];
#endif /* _SECTIONS_H */

View File

@ -0,0 +1,36 @@
// See LICENSE for license details.
#ifndef _RISCV_BITS_H
#define _RISCV_BITS_H
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
#define ROUNDDOWN(a, b) ((a)/(b)*(b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
#define STR(x) XSTR(x)
#define XSTR(x) #x
#if __riscv_xlen == 64
# define SLL32 sllw
# define STORE sd
# define LOAD ld
# define LWU lwu
# define LOG_REGBYTES 3
#else
# define SLL32 sll
# define STORE sw
# define LOAD lw
# define LWU lw
# define LOG_REGBYTES 2
#endif
#define REGBYTES (1 << LOG_REGBYTES)
#endif

View File

@ -0,0 +1,18 @@
// See LICENSE for license details.
/* Derived from <linux/const.h> */
#ifndef _SIFIVE_CONST_H
#define _SIFIVE_CONST_H
#ifdef __ASSEMBLER__
#define _AC(X,Y) X
#define _AT(T,X) X
#else
#define _AC(X,Y) (X##Y)
#define _AT(T,X) ((T)(X))
#endif /* !__ASSEMBLER__*/
#define _BITUL(x) (_AC(1,UL) << (x))
#define _BITULL(x) (_AC(1,ULL) << (x))
#endif /* _SIFIVE_CONST_H */

View File

@ -0,0 +1,88 @@
// See LICENSE for license details.
#ifndef _SIFIVE_AON_H
#define _SIFIVE_AON_H
/* Register offsets */
#define AON_WDOGCFG 0x000
#define AON_WDOGCOUNT 0x008
#define AON_WDOGS 0x010
#define AON_WDOGFEED 0x018
#define AON_WDOGKEY 0x01C
#define AON_WDOGCMP 0x020
#define AON_RTCCFG 0x040
#define AON_RTCLO 0x048
#define AON_RTCHI 0x04C
#define AON_RTCS 0x050
#define AON_RTCCMP 0x060
#define AON_BACKUP0 0x080
#define AON_BACKUP1 0x084
#define AON_BACKUP2 0x088
#define AON_BACKUP3 0x08C
#define AON_BACKUP4 0x090
#define AON_BACKUP5 0x094
#define AON_BACKUP6 0x098
#define AON_BACKUP7 0x09C
#define AON_BACKUP8 0x0A0
#define AON_BACKUP9 0x0A4
#define AON_BACKUP10 0x0A8
#define AON_BACKUP11 0x0AC
#define AON_BACKUP12 0x0B0
#define AON_BACKUP13 0x0B4
#define AON_BACKUP14 0x0B8
#define AON_BACKUP15 0x0BC
#define AON_PMUWAKEUPI0 0x100
#define AON_PMUWAKEUPI1 0x104
#define AON_PMUWAKEUPI2 0x108
#define AON_PMUWAKEUPI3 0x10C
#define AON_PMUWAKEUPI4 0x110
#define AON_PMUWAKEUPI5 0x114
#define AON_PMUWAKEUPI6 0x118
#define AON_PMUWAKEUPI7 0x11C
#define AON_PMUSLEEPI0 0x120
#define AON_PMUSLEEPI1 0x124
#define AON_PMUSLEEPI2 0x128
#define AON_PMUSLEEPI3 0x12C
#define AON_PMUSLEEPI4 0x130
#define AON_PMUSLEEPI5 0x134
#define AON_PMUSLEEPI6 0x138
#define AON_PMUSLEEPI7 0x13C
#define AON_PMUIE 0x140
#define AON_PMUCAUSE 0x144
#define AON_PMUSLEEP 0x148
#define AON_PMUKEY 0x14C
#define AON_LFROSC 0x070
/* Constants */
#define AON_WDOGKEY_VALUE 0x51F15E
#define AON_WDOGFEED_VALUE 0xD09F00D
#define AON_WDOGCFG_SCALE 0x0000000F
#define AON_WDOGCFG_RSTEN 0x00000100
#define AON_WDOGCFG_ZEROCMP 0x00000200
#define AON_WDOGCFG_ENALWAYS 0x00001000
#define AON_WDOGCFG_ENCOREAWAKE 0x00002000
#define AON_WDOGCFG_CMPIP 0x10000000
#define AON_RTCCFG_SCALE 0x0000000F
#define AON_RTCCFG_ENALWAYS 0x00001000
#define AON_RTCCFG_CMPIP 0x10000000
#define AON_WAKEUPCAUSE_RESET 0x00
#define AON_WAKEUPCAUSE_RTC 0x01
#define AON_WAKEUPCAUSE_DWAKEUP 0x02
#define AON_WAKEUPCAUSE_AWAKEUP 0x03
#define AON_RESETCAUSE_POWERON 0x0000
#define AON_RESETCAUSE_EXTERNAL 0x0100
#define AON_RESETCAUSE_WATCHDOG 0x0200
#define AON_PMUCAUSE_WAKEUPCAUSE 0x00FF
#define AON_PMUCAUSE_RESETCAUSE 0xFF00
#endif /* _SIFIVE_AON_H */

View File

@ -0,0 +1,30 @@
// See LICENSE for license details.
#ifndef _SIFIVE_CLIC_H
#define _SIFIVE_CLIC_H
#define CLIC_HART0 0x00800000
#define CLIC_MSIP 0x0000
#define CLIC_MSIP_size 0x4
#define CLIC_MTIMECMP 0x4000
#define CLIC_MTIMECMP_size 0x8
#define CLIC_MTIME 0xBFF8
#define CLIC_MTIME_size 0x8
#define CLIC_INTIP 0x000
#define CLIC_INTIE 0x400
#define CLIC_INTCFG 0x800
#define CLIC_CFG 0xc00
// These interrupt IDs are consistent across old and new mtvec modes
#define SSIPID 1
#define MSIPID 3
#define STIPID 5
#define MTIPID 7
#define SEIPID 9
#define MEIPID 11
#define CSIPID 12
#define LOCALINTIDBASE 16
#endif /* _SIFIVE_CLIC_H */

View File

@ -0,0 +1,14 @@
// See LICENSE for license details
#ifndef _SIFIVE_CLINT_H
#define _SIFIVE_CLINT_H
#define CLINT_MSIP 0x0000
#define CLINT_MSIP_size 0x4
#define CLINT_MTIMECMP 0x4000
#define CLINT_MTIMECMP_size 0x8
#define CLINT_MTIME 0xBFF8
#define CLINT_MTIME_size 0x8
#endif /* _SIFIVE_CLINT_H */

View File

@ -0,0 +1,24 @@
// See LICENSE for license details.
#ifndef _SIFIVE_GPIO_H
#define _SIFIVE_GPIO_H
#define GPIO_INPUT_VAL (0x00)
#define GPIO_INPUT_EN (0x04)
#define GPIO_OUTPUT_EN (0x08)
#define GPIO_OUTPUT_VAL (0x0C)
#define GPIO_PULLUP_EN (0x10)
#define GPIO_DRIVE (0x14)
#define GPIO_RISE_IE (0x18)
#define GPIO_RISE_IP (0x1C)
#define GPIO_FALL_IE (0x20)
#define GPIO_FALL_IP (0x24)
#define GPIO_HIGH_IE (0x28)
#define GPIO_HIGH_IP (0x2C)
#define GPIO_LOW_IE (0x30)
#define GPIO_LOW_IP (0x34)
#define GPIO_IOF_EN (0x38)
#define GPIO_IOF_SEL (0x3C)
#define GPIO_OUTPUT_XOR (0x40)
#endif /* _SIFIVE_GPIO_H */

View File

@ -0,0 +1,23 @@
// See LICENSE for license details.
#ifndef _SIFIVE_OTP_H
#define _SIFIVE_OTP_H
/* Register offsets */
#define OTP_LOCK 0x00
#define OTP_CK 0x04
#define OTP_OE 0x08
#define OTP_SEL 0x0C
#define OTP_WE 0x10
#define OTP_MR 0x14
#define OTP_MRR 0x18
#define OTP_MPP 0x1C
#define OTP_VRREN 0x20
#define OTP_VPPEN 0x24
#define OTP_A 0x28
#define OTP_D 0x2C
#define OTP_Q 0x30
#define OTP_READ_TIMINGS 0x34
#endif

View File

@ -0,0 +1,31 @@
// See LICENSE for license details.
#ifndef PLIC_H
#define PLIC_H
#include <sifive/const.h>
// 32 bits per source
#define PLIC_PRIORITY_OFFSET _AC(0x0000,UL)
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
// 1 bit per source (1 address)
#define PLIC_PENDING_OFFSET _AC(0x1000,UL)
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
//0x80 per target
#define PLIC_ENABLE_OFFSET _AC(0x2000,UL)
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
#define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL)
#define PLIC_CLAIM_OFFSET _AC(0x200004,UL)
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
#define PLIC_MAX_SOURCE 1023
#define PLIC_SOURCE_MASK 0x3FF
#define PLIC_MAX_TARGET 15871
#define PLIC_TARGET_MASK 0x3FFF
#endif /* PLIC_H */

View File

@ -0,0 +1,56 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PRCI_H
#define _SIFIVE_PRCI_H
/* Register offsets */
#define PRCI_HFROSCCFG (0x0000)
#define PRCI_HFXOSCCFG (0x0004)
#define PRCI_PLLCFG (0x0008)
#define PRCI_PLLDIV (0x000C)
#define PRCI_PROCMONCFG (0x00F0)
/* Fields */
#define ROSC_DIV(x) (((x) & 0x2F) << 0 )
#define ROSC_TRIM(x) (((x) & 0x1F) << 16)
#define ROSC_EN(x) (((x) & 0x1 ) << 30)
#define ROSC_RDY(x) (((x) & 0x1 ) << 31)
#define XOSC_EN(x) (((x) & 0x1) << 30)
#define XOSC_RDY(x) (((x) & 0x1) << 31)
#define PLL_R(x) (((x) & 0x7) << 0)
// single reserved bit for F LSB.
#define PLL_F(x) (((x) & 0x3F) << 4)
#define PLL_Q(x) (((x) & 0x3) << 10)
#define PLL_SEL(x) (((x) & 0x1) << 16)
#define PLL_REFSEL(x) (((x) & 0x1) << 17)
#define PLL_BYPASS(x) (((x) & 0x1) << 18)
#define PLL_LOCK(x) (((x) & 0x1) << 31)
#define PLL_R_default 0x1
#define PLL_F_default 0x1F
#define PLL_Q_default 0x3
#define PLL_REFSEL_HFROSC 0x0
#define PLL_REFSEL_HFXOSC 0x1
#define PLL_SEL_HFROSC 0x0
#define PLL_SEL_PLL 0x1
#define PLL_FINAL_DIV(x) (((x) & 0x3F) << 0)
#define PLL_FINAL_DIV_BY_1(x) (((x) & 0x1 ) << 8)
#define PROCMON_DIV(x) (((x) & 0x1F) << 0)
#define PROCMON_TRIM(x) (((x) & 0x1F) << 8)
#define PROCMON_EN(x) (((x) & 0x1) << 16)
#define PROCMON_SEL(x) (((x) & 0x3) << 24)
#define PROCMON_NT_EN(x) (((x) & 0x1) << 28)
#define PROCMON_SEL_HFCLK 0
#define PROCMON_SEL_HFXOSCIN 1
#define PROCMON_SEL_PLLOUTDIV 2
#define PROCMON_SEL_PROCMON 3
#endif // _SIFIVE_PRCI_H

View File

@ -0,0 +1,37 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PWM_H
#define _SIFIVE_PWM_H
/* Register offsets */
#define PWM_CFG 0x00
#define PWM_COUNT 0x08
#define PWM_S 0x10
#define PWM_CMP0 0x20
#define PWM_CMP1 0x24
#define PWM_CMP2 0x28
#define PWM_CMP3 0x2C
/* Constants */
#define PWM_CFG_SCALE 0x0000000F
#define PWM_CFG_STICKY 0x00000100
#define PWM_CFG_ZEROCMP 0x00000200
#define PWM_CFG_DEGLITCH 0x00000400
#define PWM_CFG_ENALWAYS 0x00001000
#define PWM_CFG_ONESHOT 0x00002000
#define PWM_CFG_CMP0CENTER 0x00010000
#define PWM_CFG_CMP1CENTER 0x00020000
#define PWM_CFG_CMP2CENTER 0x00040000
#define PWM_CFG_CMP3CENTER 0x00080000
#define PWM_CFG_CMP0GANG 0x01000000
#define PWM_CFG_CMP1GANG 0x02000000
#define PWM_CFG_CMP2GANG 0x04000000
#define PWM_CFG_CMP3GANG 0x08000000
#define PWM_CFG_CMP0IP 0x10000000
#define PWM_CFG_CMP1IP 0x20000000
#define PWM_CFG_CMP2IP 0x40000000
#define PWM_CFG_CMP3IP 0x80000000
#endif /* _SIFIVE_PWM_H */

View File

@ -0,0 +1,80 @@
// See LICENSE for license details.
#ifndef _SIFIVE_SPI_H
#define _SIFIVE_SPI_H
/* Register offsets */
#define SPI_REG_SCKDIV 0x00
#define SPI_REG_SCKMODE 0x04
#define SPI_REG_CSID 0x10
#define SPI_REG_CSDEF 0x14
#define SPI_REG_CSMODE 0x18
#define SPI_REG_DCSSCK 0x28
#define SPI_REG_DSCKCS 0x2a
#define SPI_REG_DINTERCS 0x2c
#define SPI_REG_DINTERXFR 0x2e
#define SPI_REG_FMT 0x40
#define SPI_REG_TXFIFO 0x48
#define SPI_REG_RXFIFO 0x4c
#define SPI_REG_TXCTRL 0x50
#define SPI_REG_RXCTRL 0x54
#define SPI_REG_FCTRL 0x60
#define SPI_REG_FFMT 0x64
#define SPI_REG_IE 0x70
#define SPI_REG_IP 0x74
/* Fields */
#define SPI_SCK_PHA 0x1
#define SPI_SCK_POL 0x2
#define SPI_FMT_PROTO(x) ((x) & 0x3)
#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
#define SPI_FMT_DIR(x) (((x) & 0x1) << 3)
#define SPI_FMT_LEN(x) (((x) & 0xf) << 16)
/* TXCTRL register */
#define SPI_TXWM(x) ((x) & 0xffff)
/* RXCTRL register */
#define SPI_RXWM(x) ((x) & 0xffff)
#define SPI_IP_TXWM 0x1
#define SPI_IP_RXWM 0x2
#define SPI_FCTRL_EN 0x1
#define SPI_INSN_CMD_EN 0x1
#define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
#define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
#define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
#define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
#define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
#define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
#define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
#define SPI_TXFIFO_FULL (1 << 31)
#define SPI_RXFIFO_EMPTY (1 << 31)
/* Values */
#define SPI_CSMODE_AUTO 0
#define SPI_CSMODE_HOLD 2
#define SPI_CSMODE_OFF 3
#define SPI_DIR_RX 0
#define SPI_DIR_TX 1
#define SPI_PROTO_S 0
#define SPI_PROTO_D 1
#define SPI_PROTO_Q 2
#define SPI_ENDIAN_MSB 0
#define SPI_ENDIAN_LSB 1
#endif /* _SIFIVE_SPI_H */

View File

@ -0,0 +1,27 @@
// See LICENSE for license details.
#ifndef _SIFIVE_UART_H
#define _SIFIVE_UART_H
/* Register offsets */
#define UART_REG_TXFIFO 0x00
#define UART_REG_RXFIFO 0x04
#define UART_REG_TXCTRL 0x08
#define UART_REG_RXCTRL 0x0c
#define UART_REG_IE 0x10
#define UART_REG_IP 0x14
#define UART_REG_DIV 0x18
/* TXCTRL register */
#define UART_TXEN 0x1
#define UART_TXWM(x) (((x) & 0xffff) << 16)
/* RXCTRL register */
#define UART_RXEN 0x1
#define UART_RXWM(x) (((x) & 0xffff) << 16)
/* IP register */
#define UART_IP_TXWM 0x1
#define UART_IP_RXWM 0x2
#endif /* _SIFIVE_UART_H */

View File

@ -0,0 +1,17 @@
// See LICENSE for license details.
#ifndef _SECTIONS_H
#define _SECTIONS_H
extern unsigned char _rom[];
extern unsigned char _rom_end[];
extern unsigned char _ram[];
extern unsigned char _ram_end[];
extern unsigned char _ftext[];
extern unsigned char _etext[];
extern unsigned char _fbss[];
extern unsigned char _ebss[];
extern unsigned char _end[];
#endif /* _SECTIONS_H */

View File

@ -0,0 +1,65 @@
#ifndef SIFIVE_SMP
#define SIFIVE_SMP
// The maximum number of HARTs this code supports
#ifndef MAX_HARTS
#define MAX_HARTS 32
#endif
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4)
// The hart that non-SMP tests should run on
#ifndef NONSMP_HART
#define NONSMP_HART 0
#endif
/* If your test cannot handle multiple-threads, use this:
* smp_disable(reg1)
*/
#define smp_disable(reg1, reg2) \
csrr reg1, mhartid ;\
li reg2, NONSMP_HART ;\
beq reg1, reg2, hart0_entry ;\
42: ;\
wfi ;\
j 42b ;\
hart0_entry:
/* If your test needs to temporarily block multiple-threads, do this:
* smp_pause(reg1, reg2)
* ... single-threaded work ...
* smp_resume(reg1, reg2)
* ... multi-threaded work ...
*/
#define smp_pause(reg1, reg2) \
li reg2, 0x8 ;\
csrw mie, reg2 ;\
csrr reg2, mhartid ;\
bnez reg2, 42f
#define smp_resume(reg1, reg2) \
li reg1, CLINT_CTRL_ADDR ;\
41: ;\
li reg2, 1 ;\
sw reg2, 0(reg1) ;\
addi reg1, reg1, 4 ;\
li reg2, CLINT_END_HART_IPI ;\
blt reg1, reg2, 41b ;\
42: ;\
wfi ;\
csrr reg2, mip ;\
andi reg2, reg2, 0x8 ;\
beqz reg2, 42b ;\
li reg1, CLINT_CTRL_ADDR ;\
csrr reg2, mhartid ;\
slli reg2, reg2, 2 ;\
add reg2, reg2, reg1 ;\
sw zero, 0(reg2) ;\
41: ;\
lw reg2, 0(reg1) ;\
bnez reg2, 41b ;\
addi reg1, reg1, 4 ;\
li reg2, CLINT_END_HART_IPI ;\
blt reg1, reg2, 41b
#endif

View File

@ -0,0 +1,72 @@
ifndef _MK_LIBWRAP
_MK_LIBWRAP := # defined
LIBWRAP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
LIBWRAP_DIR := $(LIBWRAP_DIR:/=)
LIBWRAP_SRCS := \
stdlib/malloc.c \
sys/open.c \
sys/lseek.c \
sys/read.c \
sys/write.c \
sys/fstat.c \
sys/stat.c \
sys/close.c \
sys/link.c \
sys/unlink.c \
sys/execve.c \
sys/fork.c \
sys/getpid.c \
sys/kill.c \
sys/wait.c \
sys/isatty.c \
sys/times.c \
sys/sbrk.c \
sys/_exit.c \
sys/puts.c \
misc/write_hex.c \
sys/printf.c
LIBWRAP_SRCS := $(foreach f,$(LIBWRAP_SRCS),$(LIBWRAP_DIR)/$(f))
LIBWRAP_OBJS := $(LIBWRAP_SRCS:.c=.o)
LIBWRAP_SYMS := \
open \
lseek _lseek\
read _read\
write _write\
fstat _fstat\
stat \
close _close\
link \
unlink \
execve \
fork \
getpid \
kill \
wait \
isatty \
times \
sbrk _sbrk\
_exit \
puts _puts\
printf \
sprintf
LIBWRAP := libwrap.a
LINK_DEPS += $(LIBWRAP)
LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=$(s))
LDFLAGS += -L. -Wl,--start-group -lwrap -lc -Wl,--end-group
CLEAN_OBJS += $(LIBWRAP_OBJS)
$(LIBWRAP_OBJS): %.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
$(LIBWRAP): $(LIBWRAP_OBJS)
$(AR) rcs $@ $^
endif # _MK_LIBWRAP

View File

@ -0,0 +1 @@
/*.o

View File

@ -0,0 +1,19 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <unistd.h>
#include "platform.h"
void write_hex(int fd, uint32_t hex)
{
uint8_t ii;
uint8_t jj;
char towrite;
write(fd , "0x", 2);
for (ii = 8 ; ii > 0; ii--) {
jj = ii - 1;
uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4));
towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA));
write(fd, &towrite, 1);
}
}

View File

@ -0,0 +1 @@
/*.o

View File

@ -0,0 +1,17 @@
/* See LICENSE for license details. */
/* These functions are intended for embedded RV32 systems and are
obviously incorrect in general. */
void* __wrap_malloc(unsigned long sz)
{
extern void* sbrk(long);
void* res = sbrk(sz);
if ((long)res == -1)
return 0;
return res;
}
void __wrap_free(void* ptr)
{
}

1
bare-metal-bsp/libwrap/sys/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.o

View File

@ -0,0 +1,24 @@
/* See LICENSE of license details. */
#include <unistd.h>
#include "platform.h"
extern volatile uint32_t tohost;
extern volatile uint32_t fromhost;
void write_hex(int fd, uint32_t hex);
void __wrap__exit(int code)
{
//volatile uint32_t* leds = (uint32_t*) (GPIO_BASE_ADDR + GPIO_OUT_OFFSET);
const char message[] = "\nProgam has exited with code:";
//*leds = (~(code));
write(STDERR_FILENO, message, sizeof(message) - 1);
write_hex(STDERR_FILENO, code);
write(STDERR_FILENO, "\n", 1);
#ifdef USE_TOHOST
tohost = code+1;
#endif
write(STDERR_FILENO, "\x04", 1);
for (;;);
}

View File

@ -0,0 +1,13 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_close(int fd)
{
return _stub(EBADF);
}
weak_under_alias(close);

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int __wrap_execve(const char* name, char* const argv[], char* const env[])
{
return _stub(ENOMEM);
}

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int fork(void)
{
return _stub(EAGAIN);
}

View File

@ -0,0 +1,19 @@
/* See LICENSE of license details. */
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_fstat(int fd, struct stat* st)
{
if (isatty(fd)) {
st->st_mode = S_IFCHR;
return 0;
}
return _stub(EBADF);
}
weak_under_alias(fstat);

View File

@ -0,0 +1,6 @@
/* See LICENSE of license details. */
int __wrap_getpid(void)
{
return 1;
}

View File

@ -0,0 +1,11 @@
/* See LICENSE of license details. */
#include <unistd.h>
int __wrap_isatty(int fd)
{
if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
return 1;
return 0;
}

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int __wrap_kill(int pid, int sig)
{
return _stub(EINVAL);
}

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int __wrap_link(const char *old_name, const char *new_name)
{
return _stub(EMLINK);
}

View File

@ -0,0 +1,18 @@
/* See LICENSE of license details. */
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "stub.h"
#include "weak_under_alias.h"
off_t __wrap_lseek(int fd, off_t ptr, int dir)
{
if (isatty(fd))
return 0;
return _stub(EBADF);
}
weak_under_alias(lseek);

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int __wrap_open(const char* name, int flags, int mode)
{
return _stub(ENOENT);
}

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int __wrap_openat(int dirfd, const char* name, int flags, int mode)
{
return _stub(ENOENT);
}

View File

@ -0,0 +1,278 @@
/* The functions in this file are only meant to support Dhrystone on an
* embedded RV32 system and are obviously incorrect in general. */
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#undef putchar
int putchar(int ch)
{
return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1;
}
size_t strnlen (const char *str, size_t n)
{
const char *start = str;
while (n-- > 0 && *str) str++;
return str - start;
}
static void sprintf_putch(int ch, void** data)
{
char** pstr = (char**)data;
**pstr = ch;
(*pstr)++;
}
static unsigned long getuint(va_list *ap, int lflag)
{
if (lflag)
return va_arg(*ap, unsigned long);
else
return va_arg(*ap, unsigned int);
}
static long getint(va_list *ap, int lflag)
{
if (lflag)
return va_arg(*ap, long);
else
return va_arg(*ap, int);
}
static inline void printnum(void (*putch)(int, void**), void **putdat,
unsigned long num, unsigned base, int width, int padc)
{
unsigned digs[sizeof(num)*8];
int pos = 0;
while (1)
{
digs[pos++] = num % base;
if (num < base)
break;
num /= base;
}
while (width-- > pos)
putch(padc, putdat);
while (pos-- > 0)
putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat);
}
static inline void print_double(void (*putch)(int, void**), void **putdat,
double num, int width, int prec)
{
union {
double d;
uint64_t u;
} u;
u.d = num;
if (u.u & (1ULL << 63)) {
putch('-', putdat);
u.u &= ~(1ULL << 63);
}
for (int i = 0; i < prec; i++)
u.d *= 10;
char buf[32], *pbuf = buf;
printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0);
if (prec > 0) {
for (int i = 0; i < prec; i++) {
pbuf[-i] = pbuf[-i-1];
}
pbuf[-prec] = '.';
pbuf++;
}
for (char* p = buf; p < pbuf; p++)
putch(*p, putdat);
}
static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
{
register const char* p;
const char* last_fmt;
register int ch, err;
unsigned long num;
int base, lflag, width, precision, altflag;
char padc;
while (1) {
while ((ch = *(unsigned char *) fmt) != '%') {
if (ch == '\0')
return;
fmt++;
putch(ch, putdat);
}
fmt++;
// Process a %-escape sequence
last_fmt = fmt;
padc = ' ';
width = -1;
precision = -1;
lflag = 0;
altflag = 0;
reswitch:
switch (ch = *(unsigned char *) fmt++) {
// flag to pad on the right
case '-':
padc = '-';
goto reswitch;
// flag to pad with 0's instead of spaces
case '0':
padc = '0';
goto reswitch;
// width field
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (precision = 0; ; ++fmt) {
precision = precision * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
goto process_precision;
case '*':
precision = va_arg(ap, int);
goto process_precision;
case '.':
if (width < 0)
width = 0;
goto reswitch;
case '#':
altflag = 1;
goto reswitch;
process_precision:
if (width < 0)
width = precision, precision = -1;
goto reswitch;
// long flag
case 'l':
if (lflag)
goto bad;
goto reswitch;
// character
case 'c':
putch(va_arg(ap, int), putdat);
break;
// double
case 'f':
print_double(putch, putdat, va_arg(ap, double), width, precision);
break;
// string
case 's':
if ((p = va_arg(ap, char *)) == NULL)
p = "(null)";
if (width > 0 && padc != '-')
for (width -= strnlen(p, precision); width > 0; width--)
putch(padc, putdat);
for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) {
putch(ch, putdat);
p++;
}
for (; width > 0; width--)
putch(' ', putdat);
break;
// (signed) decimal
case 'd':
num = getint(&ap, lflag);
if ((long) num < 0) {
putch('-', putdat);
num = -(long) num;
}
base = 10;
goto signed_number;
// unsigned decimal
case 'u':
base = 10;
goto unsigned_number;
// (unsigned) octal
case 'o':
// should do something with padding so it's always 3 octits
base = 8;
goto unsigned_number;
// pointer
case 'p':
lflag = 1;
putch('0', putdat);
putch('x', putdat);
/* fall through to 'x' */
// (unsigned) hexadecimal
case 'x':
base = 16;
unsigned_number:
num = getuint(&ap, lflag);
signed_number:
printnum(putch, putdat, num, base, width, padc);
break;
// escaped '%' character
case '%':
putch(ch, putdat);
break;
// unrecognized escape sequence - just print it literally
default:
bad:
putch('%', putdat);
fmt = last_fmt;
break;
}
}
}
int __wrap_printf(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintfmt((void*)putchar, 0, fmt, ap);
va_end(ap);
return 0; // incorrect return value, but who cares, anyway?
}
int __wrap_sprintf(char* str, const char* fmt, ...)
{
va_list ap;
char* str0 = str;
va_start(ap, fmt);
vprintfmt(sprintf_putch, (void**)&str, fmt, ap);
*str = 0;
va_end(ap);
return str - str0;
}

View File

@ -0,0 +1,28 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "platform.h"
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_puts(const char *s)
{
while (*s != '\0') {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = *s;
if (*s == '\n') {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = '\r';
}
++s;
}
return 0;
}
weak_under_alias(puts);

View File

@ -0,0 +1,32 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "platform.h"
#include "stub.h"
#include "weak_under_alias.h"
ssize_t __wrap_read(int fd, void* ptr, size_t len)
{
uint8_t * current = (uint8_t *)ptr;
volatile uint32_t * uart_rx = (uint32_t *)(UART0_CTRL_ADDR + UART_REG_RXFIFO);
volatile uint8_t * uart_rx_cnt = (uint8_t *)(UART0_CTRL_ADDR + UART_REG_RXCTRL + 2);
ssize_t result = 0;
if (isatty(fd)) {
for (current = (uint8_t *)ptr;
(current < ((uint8_t *)ptr) + len) && (*uart_rx_cnt > 0);
current ++) {
*current = *uart_rx;
result++;
}
return result;
}
return _stub(EBADF);
}
weak_under_alias(read);

View File

@ -0,0 +1,19 @@
/* See LICENSE of license details. */
#include <stddef.h>
#include "weak_under_alias.h"
void *__wrap_sbrk(ptrdiff_t incr)
{
extern char _end[];
extern char _heap_end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
return NULL - 1;
curbrk += incr;
return curbrk - incr;
}
weak_under_alias(sbrk);

View File

@ -0,0 +1,10 @@
/* See LICENSE of license details. */
#include <errno.h>
#include <sys/stat.h>
#include "stub.h"
int __wrap_stat(const char* file, struct stat* st)
{
return _stub(EACCES);
}

View File

@ -0,0 +1,10 @@
/* See LICENSE of license details. */
#ifndef _SIFIVE_SYS_STUB_H
#define _SIFIVE_SYS_STUB_H
static inline int _stub(int err)
{
return -1;
}
#endif /* _SIFIVE_SYS_STUB_H */

View File

@ -0,0 +1,10 @@
/* See LICENSE of license details. */
#include <errno.h>
#include <sys/times.h>
#include "stub.h"
clock_t __wrap_times(struct tms* buf)
{
return _stub(EACCES);
}

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int __wrap_unlink(const char* name)
{
return _stub(ENOENT);
}

View File

@ -0,0 +1,9 @@
/* See LICENSE of license details. */
#include <errno.h>
#include "stub.h"
int wait(int* status)
{
return _stub(ECHILD);
}

View File

@ -0,0 +1,7 @@
#ifndef _BSP_LIBWRAP_WEAK_UNDER_ALIAS_H
#define _BSP_LIBWRAP_WEAK_UNDER_ALIAS_H
#define weak_under_alias(name) \
extern __typeof (__wrap_##name) __wrap__##name __attribute__ ((weak, alias ("__wrap_"#name)))
#endif

View File

@ -0,0 +1,31 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "platform.h"
#include "stub.h"
#include "weak_under_alias.h"
ssize_t __wrap_write(int fd, const void* ptr, size_t len)
{
const uint8_t * current = (const char *)ptr;
if (isatty(fd)) {
for (size_t jj = 0; jj < len; jj++) {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = current[jj];
if (current[jj] == '\n') {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = '\r';
}
}
return len;
}
return _stub(EBADF);
}
weak_under_alias(write);

View File

@ -1,4 +0,0 @@
*.o
*.elf
*.log
/coremark.*

View File

@ -1,33 +0,0 @@
TARGET := coremark
ISA?=imc
ITERATIONS?=600 # 300 for TGC
ASM_SRCS :=
C_SRCS := core_list_join.c core_main.c core_matrix.c core_state.c core_util.c core_portme.c ee_printf.c
HEADERS := cm/coremark.h
vpath %.c cm
BOARD?=iss
LINK_TARGET=link
RISCV_ARCH:=rv32$(ISA)
ifeq ($(ISA),e)
RISCV_ABI:=ilp32e
else
RISCV_ABI:=ilp32
endif
PORT_CFLAGS = -DPERFORMANCE_RUN=1 -DCLOCKS_PER_SEC=10000000 -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast
PORT_CFLAGS+= -g -O3 -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-crossjumping -freorder-blocks-and-partition
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
CFLAGS = $(PORT_CFLAGS) -I. -Icm -DFLAGS_STR=\"$(FLAGS_STR)\"
CFLAGS += -DITERATIONS=$(ITERATIONS)
LDFLAGS := -g -Wl,--wrap=scanf -Wl,--wrap=printf -Wl,--wrap=exit -lgcc -lm
TOOL_DIR=$(dir $(compiler))
BSP_BASE = ../../bare-metal-bsp
include $(BSP_BASE)/env/common-gcc.mk

View File

@ -186,7 +186,6 @@ portable_init(core_portable *p, int *argc, char *argv[])
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
} }
p->portable_id = 1; p->portable_id = 1;
ee_printf("portable_init finished.\n");
} }
/* Function : portable_fini /* Function : portable_fini
Target specific final code Target specific final code

View File

@ -0,0 +1,94 @@
# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Original Author: Shay Gal-on
#File : core_portme.mak
ISA?=imc
RISCV_ARCH:=rv32$(ISA)
RISCV_ABI:=ilp32
# Flag : OUTFLAG
# Use this flag to define how to to get an executable (e.g -o)
OUTFLAG= -o
# Flag : CC
# Use this flag to define compiler to use
CC = riscv32-unknown-elf-gcc
# Flag : LD
# Use this flag to define compiler to use
LD = riscv32-unknown-elf-gcc
# Flag : AS
# Use this flag to define compiler to use
AS = riscv32-unknown-elf-as
# Flag : CFLAGS
# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
PORT_CFLAGS = -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -O3 -DCLOCKS_PER_SEC=10000000 -nostdlib -nostartfiles -nodefaultlibs \
-funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -flto
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"
#Flag : LFLAGS_END
# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
# Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
SEPARATE_COMPILE=1
# Flag : SEPARATE_COMPILE
# You must also define below how to create an object file, and how to link.
OBJOUT = -o
LFLAGS =
#--specs=nano.specs -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI)
ASFLAGS =
OFLAG = -o
COUT = -c
LFLAGS_END =
# Flag : PORT_SRCS
# Port specific source files can be added here
# You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c
vpath %.c $(PORT_DIR)
vpath %.s $(PORT_DIR)
PORT_OBJS = core_portme.o ee_printf.o
# Flag : LOAD
# For a simple port, we assume self hosted compile and run, no load needed.
# Flag : RUN
# For a simple port, we assume self hosted compile and run, simple invocation of the executable
LOAD = echo ""
RUN = echo ""
OEXT = .o
EXE = .elf
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
$(OPATH)%$(OEXT) : %.c
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
$(AS) $(ASFLAGS) $< $(OBJOUT) $@
# Target : port_pre% and port_post%
# For the purpose of this simple port, no pre or post steps needed.
.PHONY : port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload
port_pre% port_post% :
# FLAG : OPATH
# Path to the output folder. Default - current folder.
OPATH = ./
MKDIR = mkdir -p
dist-clean: clean
rm -f *.o

View File

@ -659,28 +659,24 @@ ee_vsprintf(char *buf, const char *fmt, va_list args)
return str - buf; return str - buf;
} }
#include <platform.h> #define UART0_BASE_ADDR 0xffff0000ULL
#define UART_REG_TXFIFO 0x00
#define UART_REG_RXFIFO 0x04
#define UART_REG_TXCTRL 0x08
#define UART_REG_RXCTRL 0x0c
#define UART_REG_IE 0x10
#define UART_REG_IP 0x14
#define UART_REG_DIV 0x18
#define UART_TXEN 0x1
#define UART0_REG(ADDR) *((ee_u32*) (UART0_BASE_ADDR + ADDR))
void void
uart_send_char(char c) uart_send_char(char c)
{ {
#if defined(BOARD_ehrenberg) while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
while (get_uart_rx_tx_reg_tx_free(uart)==0) ; UART0_REG(UART_REG_TXFIFO) = (unsigned char)c;
uart_write(uart, c);
if (c == '\n') {
while (get_uart_rx_tx_reg_tx_free(uart)==0) ;
uart_write(uart, '\r');
}
#elif defined(BOARD_iss)
*((uint32_t*) 0xFFFF0000) = c;
#else
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = c;
if (c == '\n') {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = '\r';
}
#endif
} }
int int

View File

@ -0,0 +1,241 @@
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
OUTPUT_ARCH(riscv)
MEMORY
{
RAM (rwx) : ORIGIN = 0x0, LENGTH = 128M
}
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
.rela.plt :
{
*(.rela.plt)
}
.plt : { *(.plt) }
.iplt : { *(.iplt) }
.init :
{
KEEP (*(SORT_NONE(.init)))
*crt0.o(.text .text.*)
} > RAM
.text :
{
*(.text.init)
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 :
{
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
}
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
/* Thread Local Storage sections */
.tdata :
{
PROVIDE_HIDDEN (__tdata_start = .);
*(.tdata .tdata.* .gnu.linkonce.td.*)
}
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.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 = .);
}
.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 = .);
}
.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))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.data :
{
__DATA_BEGIN__ = .;
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
__SDATA_BEGIN__ = .;
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.sbss :
{
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we do not
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
__BSS_END__ = .;
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.debug_addr 0 : { *(.debug_addr) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}

View File

@ -14,7 +14,7 @@
</extensions> </extensions>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.cross.base.574338120" name="Default" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.emptycfg"> <configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.cross.base.574338120" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.574338120.193230058" name="/" resourcePath=""> <folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.574338120.193230058" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1380433779" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base"> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1380433779" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
<option id="cdt.managedbuild.option.gnu.cross.prefix.1116043753" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/> <option id="cdt.managedbuild.option.gnu.cross.prefix.1116043753" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
@ -57,7 +57,6 @@
<buildTargets> <buildTargets>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget> <buildTarget>all</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
@ -65,27 +64,12 @@
</target> </target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget> <buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders> <runAllBuilders>true</runAllBuilders>
</target> </target>
<target name="all BOARD=tgc-vp" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all BOARD=tgc-vp</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all BOARD=iss" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all BOARD=iss</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets> </buildTargets>
</storageModule> </storageModule>
</cproject> </cproject>

View File

@ -3,7 +3,7 @@
<name>dhrystone</name> <name>dhrystone</name>
<comment></comment> <comment></comment>
<projects> <projects>
<project>bare-metal-bsp</project> <project>bsp</project>
</projects> </projects>
<buildSpec> <buildSpec>
<buildCommand> <buildCommand>

View File

@ -1,12 +1,11 @@
TARGET := dhrystone TARGET := dhrystone
ISA?=imc ISA?=imc
ITERATIONS?=50000 # 20000 for TGC
ASM_SRCS := ASM_SRCS :=
C_SRCS := dhry_stubs.c dhry_1.c dhry_2.c C_SRCS := dhry_stubs.c dhry_printf.c dhry_1.c dhry_2.c
HEADERS := dhry.h HEADERS := dhry.h
BOARD?=iss BOARD=iss
LINK_TARGET=link LINK_TARGET=link
RISCV_ARCH:=rv32$(ISA) RISCV_ARCH:=rv32$(ISA)
ifeq ($(ISA),e) ifeq ($(ISA),e)
@ -15,10 +14,12 @@ else
RISCV_ABI:=ilp32 RISCV_ABI:=ilp32
endif endif
# '-lgcc -lm' are needed to add softfloat routines # '-lgcc -lm' are needed to add softfloat routines
CFLAGS := -g -O3 -DITERATIONS=$(ITERATIONS) -DHZ=32768 -DTIME -DNO_INIT -fno-inline -fno-builtin-printf -fno-common -Wno-implicit \ CFLAGS := -g -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=medlow -O3 -DHZ=32768 -DTIME -DNO_INIT -fno-inline -fno-builtin-printf -fno-common -Wno-implicit \
-funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las
LDFLAGS := -g -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=medlow -Wl,--wrap=scanf -Wl,--wrap=printf -Wl,--wrap=exit -lgcc -lm
TOOL_DIR=$(dir $(compiler)) TOOL_DIR=$(dir $(compiler))
TRIPLET=riscv32-unknown-elf
BSP_BASE = ../../bare-metal-bsp BSP_BASE = ../../bare-metal-bsp
include $(BSP_BASE)/env/common-gcc.mk include $(BSP_BASE)/env/common-gcc.mk

View File

@ -0,0 +1,15 @@
/* The functions in this file are only meant to support Dhrystone on an
* embedded RV32 system and are obviously incorrect in general. */
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
//#undef putchar
//int putchar(int ch)
//{
// return write(1, &ch, 1) == 1 ? ch : -1;
//}

View File

@ -1,7 +1,4 @@
#include "platform.h" #include "platform.h"
#ifndef ITERATIONS
#define ITERATIONS 20000
#endif
/* The functions in this file are only meant to support Dhrystone on an /* The functions in this file are only meant to support Dhrystone on an
* embedded RV32 system and are obviously incorrect in general. */ * embedded RV32 system and are obviously incorrect in general. */
@ -14,12 +11,12 @@ long time(void)
// set the number of dhrystone iterations // set the number of dhrystone iterations
void __wrap_scanf(const char* fmt, int* n) void __wrap_scanf(const char* fmt, int* n)
{ {
*n = ITERATIONS; *n = 200000;
} }
extern volatile uint32_t tohost; extern volatile uint32_t tohost;
void exit(int n){ void __wrap_exit(int n){
tohost = 0x1; tohost = 0x1;
for (;;); for (;;);
} }

View File

@ -57,6 +57,7 @@
<buildTargets> <buildTargets>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget> <buildTarget>all</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
@ -64,27 +65,12 @@
</target> </target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget> <buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders> <runAllBuilders>true</runAllBuilders>
</target> </target>
<target name="clean all BOARD=tgc-vp" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean all BOARD=tgc-vp</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean all BOARD=iss" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean all BOARD=iss</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets> </buildTargets>
</storageModule> </storageModule>
</cproject> </cproject>

View File

@ -1,26 +1,19 @@
TARGET = hello TARGET = hello
ISA?=imc
C_SRCS = $(wildcard *.c) C_SRCS = $(wildcard *.c)
HEADERS = $(wildcard *.h) HEADERS = $(wildcard *.h)
OPT ?= -O2 CFLAGS += -O2 -g
CFLAGS += $(OPT) -g
BOARD=iss BOARD=iss
LINK_TARGET=link LINK_TARGET=link
RISCV_ARCH:=rv32$(ISA) RISCV_ARCH:=rv32i
ifeq ($(ISA),e) RISCV_ABI:=ilp32
RISCV_ABI:=ilp32e
else
RISCV_ABI:=ilp32
endif
LDFLAGS += -g -Wl,--wrap=printf LDFLAGS += -g -Wl,--wrap=printf
compiler := $(shell which riscv64-unknown-elf-gcc) compiler := $(shell which riscv32-unknown-elf-gcc)
TOOL_DIR=$(dir $(compiler)) TOOL_DIR=$(dir $(compiler))
TRIPLET=riscv64-unknown-elf TRIPLET=riscv32-unknown-elf
BSP_BASE = ../bare-metal-bsp BSP_BASE = ../bare-metal-bsp
include $(BSP_BASE)/env/common-gcc.mk include $(BSP_BASE)/env/common-gcc.mk

15
hello-world/wrap_stubs.c Normal file
View File

@ -0,0 +1,15 @@
#include "platform.h"
/* The functions in this file are only meant to support Dhrystone on an
* embedded RV32 system and are obviously incorrect in general. */
long time(void)
{
return get_timer_value() / get_timer_freq();
}
// set the number of dhrystone iterations
void __wrap_scanf(const char* fmt, int* n)
{
*n = 100000000;
}