fw: wrote a simple little hello world app in C
This commit is contained in:
parent
e43f508e84
commit
e37b97bcf9
2
firmware/hello_world_c/.gitignore
vendored
Normal file
2
firmware/hello_world_c/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.elf
|
||||||
|
*.bin
|
17
firmware/hello_world_c/Makefile
Normal file
17
firmware/hello_world_c/Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
PREFIX := riscv64-unknown-elf-
|
||||||
|
CC := $(PREFIX)gcc
|
||||||
|
OBJCOPY := $(PREFIX)objcopy
|
||||||
|
|
||||||
|
ARGS := -mabi=ilp32 -march=rv32im -ffreestanding -nostdlib -Wl,-Bstatic,-T,memory.ld,--strip-debug
|
||||||
|
|
||||||
|
SOURCES := main.c
|
||||||
|
INCLUDES := uart.h
|
||||||
|
|
||||||
|
hello_world.bin: hello_world.elf
|
||||||
|
$(OBJCOPY) -S -O binary hello_world.elf hello_world.bin
|
||||||
|
|
||||||
|
hello_world.elf: $(SOURCES) $(INCLUDES)
|
||||||
|
$(CC) $(ARGS) $(SOURCES) -o hello_world.elf
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f hello_world.elf hello_world.bin
|
54
firmware/hello_world_c/main.c
Normal file
54
firmware/hello_world_c/main.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void write_cstring(const char* string);
|
||||||
|
void write_char(char c);
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
for (;;) {
|
||||||
|
write_char('H');
|
||||||
|
write_char('e');
|
||||||
|
write_char('l');
|
||||||
|
write_char('l');
|
||||||
|
write_char('o');
|
||||||
|
write_char(' ');
|
||||||
|
write_char('W');
|
||||||
|
write_char('o');
|
||||||
|
write_char('r');
|
||||||
|
write_char('l');
|
||||||
|
write_char('d');
|
||||||
|
write_char('!');
|
||||||
|
write_char('\n');
|
||||||
|
write_char('\r');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_char(char c) {
|
||||||
|
while (!UART0->TXEMPTY);
|
||||||
|
|
||||||
|
// Wait for room to clear up
|
||||||
|
if (!UART0->TXFULL) {
|
||||||
|
UART0->RXTX = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void write_cstring(const char* string) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Return at end of string
|
||||||
|
if (string[i] == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for room to clear up
|
||||||
|
if (!UART0->TXFULL) {
|
||||||
|
UART0->RXTX = string[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
firmware/hello_world_c/memory.ld
Normal file
64
firmware/hello_world_c/memory.ld
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* stolen from https://github.com/Obijuan/RISC-V-FPGA/blob/master/firmware/soc-demo/src-c/sections.lds */
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ROM (rx) : ORIGIN = 0x01000000, LENGTH = 0x1000 /* 4KiB */
|
||||||
|
RAM (xrw) : ORIGIN = 0x01001000, LENGTH = 0x1000 /* 4KiB */
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
/* The program code and other data goes into FLASH */
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.text) /* .text sections (code) */
|
||||||
|
*(.text*) /* .text* sections (code) */
|
||||||
|
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||||
|
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||||
|
*(.srodata) /* .rodata sections (constants, strings, etc.) */
|
||||||
|
*(.srodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||||
|
_etext = .; /* define a global symbol at end of code */
|
||||||
|
_sidata = _etext; /* This is used by the startup in order to initialize the .data secion */
|
||||||
|
} >ROM
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the initialized data section
|
||||||
|
The program executes knowing that the data is in the RAM
|
||||||
|
but the loader puts the initial values in the FLASH (inidata).
|
||||||
|
It is one task of the startup to copy the initial values from FLASH to RAM. */
|
||||||
|
.data : AT ( _sidata )
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
|
||||||
|
_ram_start = .; /* create a global symbol at ram start for garbage collector */
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.data) /* .data sections */
|
||||||
|
*(.data*) /* .data* sections */
|
||||||
|
*(.sdata) /* .sdata sections */
|
||||||
|
*(.sdata*) /* .sdata* sections */
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
/* Uninitialized data section */
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sbss = .; /* define a global symbol at bss start; used by startup code */
|
||||||
|
*(.bss)
|
||||||
|
*(.bss*)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss*)
|
||||||
|
*(COMMON)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = .; /* define a global symbol at bss end; used by startup code */
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
/* this is to define the start of the heap, and make sure we have a minimum size */
|
||||||
|
.heap :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_heap_start = .; /* define a global symbol at heap start */
|
||||||
|
} >RAM
|
||||||
|
}
|
21
firmware/hello_world_c/uart.h
Normal file
21
firmware/hello_world_c/uart.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef UART_H_
|
||||||
|
#define UART_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef
|
||||||
|
__attribute__((packed))
|
||||||
|
struct {
|
||||||
|
uint32_t RXTX;
|
||||||
|
uint32_t TXFULL;
|
||||||
|
uint32_t RXEMPTY;
|
||||||
|
uint32_t EV_STATUS;
|
||||||
|
uint32_t EV_PENDING;
|
||||||
|
uint32_t EV_ENABLE;
|
||||||
|
uint32_t TXEMPTY;
|
||||||
|
uint32_t RXFULL;
|
||||||
|
} LiteUART;
|
||||||
|
|
||||||
|
#define UART0 ((LiteUART*)0xF0003000)
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user