Created
September 10, 2018 16:46
-
-
Save levex/57d4dcffa984a566d47d61bdb488aebc to your computer and use it in GitHub Desktop.
HiFive1 barebones OSdev
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = .); | |
.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 .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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stddef.h> | |
/* GPIO */ | |
#define GPIO_CTRL_ADDR 0x10012000UL | |
#define GPIO_IOF_EN 0x38 | |
#define GPIO_IOF_SEL 0x3C | |
#define IOF0_UART0_MASK 0x00030000UL | |
/* UART */ | |
#define UART0_CTRL_ADDR 0x10013000UL | |
#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 | |
/* PRCI */ | |
#define PRCI_CTRL_ADDR 0x10008000UL | |
#define PRCI_HFROSCCFG (0x0000) | |
#define PRCI_PLLCFG (0x0008) | |
#define ROSC_EN(x) (((x) & 0x1) << 30) | |
#define PLL_REFSEL(x) (((x) & 0x1) << 17) | |
#define PLL_BYPASS(x) (((x) & 0x1) << 18) | |
#define PLL_SEL(x) (((x) & 0x1) << 16) | |
static inline uint32_t | |
mmio_read_u32(unsigned long reg, unsigned int offset) | |
{ | |
return (*(volatile uint32_t *) ((reg) + (offset))); | |
} | |
static inline void | |
mmio_write_u8(unsigned long reg, unsigned int offset, uint8_t val) | |
{ | |
(*(volatile uint32_t *) ((reg) + (offset))) = val; | |
} | |
static inline void | |
mmio_write_u32(unsigned long reg, unsigned int offset, uint32_t val) | |
{ | |
(*(volatile uint32_t *) ((reg) + (offset))) = val; | |
} | |
static void uart_init(size_t baud_rate) | |
{ | |
mmio_write_u32(GPIO_CTRL_ADDR, | |
GPIO_IOF_SEL, | |
mmio_read_u32(GPIO_CTRL_ADDR, GPIO_IOF_SEL) | |
& ~IOF0_UART0_MASK); | |
mmio_write_u32(GPIO_CTRL_ADDR, | |
GPIO_IOF_EN, | |
mmio_read_u32(GPIO_CTRL_ADDR, GPIO_IOF_EN) | |
| IOF0_UART0_MASK); | |
mmio_write_u32(UART0_CTRL_ADDR, UART_REG_DIV, 138); | |
mmio_write_u32(UART0_CTRL_ADDR, | |
UART_REG_TXCTRL, | |
mmio_read_u32(UART0_CTRL_ADDR, UART_REG_TXCTRL) | |
| UART_TXEN); | |
/* busy loop until the line is asserted... */ | |
volatile int i = 0; | |
while(i++ < 1000000); | |
} | |
static void | |
__uart_write(uint8_t byte) | |
{ | |
/* wait for the UART to become ready */ | |
while (mmio_read_u32(UART0_CTRL_ADDR, UART_REG_TXFIFO) & 0x80000000) | |
; | |
/* write to the UART transmit FIFO */ | |
mmio_write_u8(UART0_CTRL_ADDR, UART_REG_TXFIFO, byte); | |
} | |
static void | |
uart_write(uint8_t *buf, size_t len) | |
{ | |
int i; | |
for (i = 0; i < len; i ++) { | |
__uart_write(buf[i]); | |
/* If an LF was written, also write a CR */ | |
if (buf[i] == '\n') { | |
__uart_write('\r'); | |
} | |
} | |
} | |
static size_t | |
strlen(char *str) | |
{ | |
int len = 0; | |
int i; | |
for (i = 0; str[i] != 0; i ++) | |
{ | |
len ++; | |
} | |
return len; | |
} | |
static void | |
uart_write_string(uint8_t *buf) | |
{ | |
uart_write(buf, strlen((char *) buf)); | |
} | |
static void | |
prci_init(void) | |
{ | |
// Make sure the HFROSC is on before the next line: | |
mmio_write_u32(PRCI_CTRL_ADDR, PRCI_HFROSCCFG, | |
mmio_read_u32(PRCI_CTRL_ADDR, PRCI_HFROSCCFG) | |
| ROSC_EN(1)); | |
// Run off 16 MHz Crystal for accuracy. Note that the | |
// first line is | |
mmio_write_u32(PRCI_CTRL_ADDR, PRCI_PLLCFG, | |
mmio_read_u32(PRCI_CTRL_ADDR, PRCI_PLLCFG) | |
| (PLL_REFSEL(1) | PLL_BYPASS(1))); | |
mmio_write_u32(PRCI_CTRL_ADDR, PRCI_PLLCFG, | |
mmio_read_u32(PRCI_CTRL_ADDR, PRCI_PLLCFG) | |
| (PLL_SEL(1))); | |
// Turn off HFROSC to save power | |
mmio_write_u32(PRCI_CTRL_ADDR, PRCI_HFROSCCFG, | |
mmio_read_u32(PRCI_CTRL_ADDR, PRCI_HFROSCCFG) | |
& ~(ROSC_EN(1))); | |
} | |
void | |
main(void) | |
{ | |
prci_init(); | |
uart_init(115200); | |
uart_write_string("Hello, world, this is myOS on the HiFive-1 Board!\n"); | |
/* For now, just halt */ | |
for (;;); | |
} | |
__attribute__((section(".init"))) | |
void | |
_start(void) | |
{ | |
main(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SDK=/home/lkurusa/dev/freedom-e-sdk | |
SDK_PREFIX=$(SDK)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/bin | |
CROSS=$(SDK_PREFIX)/riscv64-unknown-elf- | |
CFLAGS=-g \ | |
-march=rv32imac \ | |
-mabi=ilp32 \ | |
-mcmodel=medany | |
LINKER_SCRIPT=hifive1.lds | |
LDFLAGS=-T $(LINKER_SCRIPT) \ | |
-nostartfiles | |
main.img: main.c | |
$(CROSS)gcc $< $(CFLAGS) -o $@ $(LDFLAGS) | |
.PHONY: clean | |
clean: | |
rm -rf main.img | |
rm -rf main.o |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment