From 07a15a522e046abca4387fabbe84907d44677a64 Mon Sep 17 00:00:00 2001 From: Mattia Rizzi <mattia.rizzi@cern.ch> Date: Sat, 23 Jan 2021 16:56:41 +0100 Subject: [PATCH] Simple app to perform a check of the SoC under radiation. It's a ethernet echo loopback with some debug infos printed over ethernet --- software/app/Makefile | 53 ++++++++++++ software/app/crt0.S | 128 +++++++++++++++++++++++++++ software/app/eth_config.c | 177 ++++++++++++++++++++++++++++++++++++++ software/app/eth_config.h | 27 ++++++ software/app/irq.S | 129 +++++++++++++++++++++++++++ software/app/main.c | 129 +++++++++++++++++++++++++++ software/app/powerlink.ld | 72 ++++++++++++++++ software/app/refresh.s | 73 ++++++++++++++++ software/app/riscv.h | 37 ++++++++ software/app/uart.c | 46 ++++++++++ software/app/uart.h | 16 ++++ 11 files changed, 887 insertions(+) create mode 100644 software/app/Makefile create mode 100644 software/app/crt0.S create mode 100644 software/app/eth_config.c create mode 100644 software/app/eth_config.h create mode 100644 software/app/irq.S create mode 100644 software/app/main.c create mode 100644 software/app/powerlink.ld create mode 100644 software/app/refresh.s create mode 100644 software/app/riscv.h create mode 100644 software/app/uart.c create mode 100644 software/app/uart.h diff --git a/software/app/Makefile b/software/app/Makefile new file mode 100644 index 0000000..85e777b --- /dev/null +++ b/software/app/Makefile @@ -0,0 +1,53 @@ +#CROSS_COMPILE_TARGET ?= /home/mattia/riscv-toolchain/riscv/bin/riscv32-elf- + +CROSS_COMPILE_TARGET ?= /home/mattia/riscv32-nanolib/gnu-mcu-eclipse/riscv-none-gcc/8.1.0-2-20181019-0952/bin/riscv-none-embed- +CFLAGS += -mabi=ilp32 -march=rv32im -Os -ffunction-sections -fdata-sections --specs=nano.specs --specs=nosys.specs -lgcc -lc -Wl,--gc-sections + + +CC = $(CROSS_COMPILE_TARGET)gcc +LD = $(CROSS_COMPILE_TARGET)ld +OBJDUMP = $(CROSS_COMPILE_TARGET)objdump +OBJCOPY = $(CROSS_COMPILE_TARGET)objcopy +SIZE = $(CROSS_COMPILE_TARGET)size +STRIP = $(CROSS_COMPILE_TARGET)strip + + + +all: main-text.hex main-data.hex + +crt0.o: crt0.S + $(CC) -c -o $@ $(CFLAGS) $< + +irq.o: irq.S + $(CC) -c -o $@ $(CFLAGS) $< + +eth_config.o: eth_config.c + $(CC) -c -o $@ $(CFLAGS) $< + +uart.o: uart.c + $(CC) -c -o $@ $(CFLAGS) $< + +refresh.o: refresh.s + $(CC) -c -o $@ $(CFLAGS) $< + +main: main.o crt0.o powerlink.ld irq.o eth_config.o refresh.o uart.o + $(CC) -o $@ -nostartfiles $(CFLAGS) crt0.o main.o irq.o eth_config.o refresh.o uart.o -T powerlink.ld + +main-text.bin: main + riscv32-elf-objcopy -j .text -O binary $< $@ + +main-data.bin: main + riscv32-elf-objcopy -j .data -O binary $< $@ + +main-text.hex: main-text.bin + riscv32-elf-objcopy -I binary -O ihex $< $@ + +main-data.hex: main-data.bin + riscv32-elf-objcopy -I binary -O ihex $< $@ + +clean: + rm main + rm *.o + rm *.bin + rm *.hex + diff --git a/software/app/crt0.S b/software/app/crt0.S new file mode 100644 index 0000000..11bdc95 --- /dev/null +++ b/software/app/crt0.S @@ -0,0 +1,128 @@ + .section .boot, "ax", @progbits + +.global _start +_start: + j _entry + +.org 0x8 + +.extern trap_entry +_exception_entry: + j trap_entry + + +_entry: + + lui t0,%hi(0x86000000) + lw t0,%lo(0x86000000)(t0) + and t0, t0, 1 + bnez t0, _recovery + lui t0,%hi(0x86000000) + li t1, 1 + sw t1, 0(t0) + + lui ra, 0 + lui sp, 0 + lui gp, 0 + lui tp, 0 + lui s0, 0 + lui s1, 0 + lui s2, 0 + lui s3, 0 + lui s4, 0 + lui s5, 0 + lui s6, 0 + lui s7, 0 + lui s8, 0 + lui s9, 0 + lui s10, 0 + lui s11, 0 + lui t0, 0 + lui t1, 0 + lui t2, 0 + lui t3, 0 + lui t4, 0 + lui t5, 0 + lui t6, 0 + lui a0, 0 + lui a1, 0 + lui a2, 0 + lui a3, 0 + lui a4, 0 + lui a5, 0 + lui a6, 0 + lui a7, 0 + la gp, _gp /* Initialize global pointer */ + la sp, _fstack + +/* la t0, _fexception_stack + csrrw t0, mscratch, t0 */ + + /* clear the bss segment */ + la t0, _fbss + la t1, _end +1: +#ifdef __riscv64 + sd zero,0(t0) + addi t0, t0, 8 +#else + sw zero,0(t0) + addi t0, t0, 4 +#endif + bltu t0, t1, 1b + call main +1: + j 1b + +_recovery: + la t0, _recov_data + sw ra, 0(t0) # x1 + lw ra, 0(t0) + sw sp, 0(t0) # x2 + lw sp, 0(t0) + sw gp, 0(t0) # x3 + lw gp, 0(t0) + sw tp, 0(t0) # x4 + lw tp, 0(t0) + li t1, 0 # x6 + li t2, 0 # x7 + sw s0, 0(t0) # x8 + lw s0, 0(t0) + sw s1, 0(t0) # x9 + lw s1, 0(t0) + li a0, 0 # x10 + li a1, 0 # x11 + li a2, 0 # x12 + li a3, 0 # x13 + li a4, 0 + li a5, 0 + li a6, 0 + li a7, 0 # x17 + sw s2, 0(t0) # x18 + lw s2, 0(t0) + sw s3, 0(t0) # x19 + lw s3, 0(t0) + sw s4, 0(t0) # x20 + lw s4, 0(t0) + sw s5, 0(t0) # x21 + lw s5, 0(t0) + sw s6, 0(t0) # x22 + lw s6, 0(t0) + sw s7, 0(t0) # x23 + lw s7, 0(t0) + sw s8, 0(t0) # x24 + lw s8, 0(t0) + sw s9, 0(t0) # x25 + lw s9, 0(t0) + sw s10, 0(t0) # x26 + lw s10, 0(t0) + sw s11, 0(t0) # x27 + lw s11, 0(t0) + li t3, 0 # x28 + li t4, 0 # x29 + li t5, 0 # x30 + li t6, 0 # x31 + li t0, 0 + ret + .data +_recov_data: .long 0 diff --git a/software/app/eth_config.c b/software/app/eth_config.c new file mode 100644 index 0000000..7b94e6f --- /dev/null +++ b/software/app/eth_config.c @@ -0,0 +1,177 @@ +#include <stdio.h> +#include <string.h> +#include "eth_config.h" +#include "uart.h" + + + + + +void eth_send_frame(uint16_t len); + +void __attribute__((optimize("O0"))) delay_us(uint16_t us) { + uint32_t istrs = ((uint16_t) us ) << 5; + while (istrs > 0) + istrs--; + +} + + + +volatile uint32_t __attribute__((section (".dma"))) rx_buf0[1516/4]; +volatile uint32_t __attribute__((section (".dma"))) rx_buf1[1516/4]; + + +volatile uint32_t tx_buf[1516/4]; + +static volatile eth_descriptor * rx_descriptor0 = (volatile void *) MAC_REG_RXDESCRIPTOR0; +static volatile eth_descriptor * rx_descriptor1 = (volatile void *) MAC_REG_RXDESCRIPTOR1; +static volatile eth_descriptor * tx_descriptor = (volatile void *) MAC_REG_TXDESCRIPTOR; +static volatile uint32_t * mac_config = (volatile void *) MAC_REG_CONFIG; + +volatile uint32_t * miim_config = (volatile uint32_t *) MAC_REG_MIICONFIG; +volatile uint32_t * miim_reg = (volatile uint32_t *) MAC_REG_MII; + +void reset_phy (void) { + + *mac_config = 0x10; + delay_us(175); + *mac_config = 0x8; + delay_us(100); +} + +void disable_irq () { + unsigned t; + asm volatile ("csrrci %0, mstatus, %1" : "=r"(t) : "i"(1 << 3)); +} + +void enable_irq () { + unsigned t; + asm volatile ("csrrsi %0, mstatus, %1" : "=r"(t) : "i"(1 << 3)); +} + +void init_mac (void) { + + + disable_irq(); + + *mac_config = MAC_RESET; + delay_us(1); + *mac_config = MAC_INIT_CONFIG; + + rx_descriptor0->busy = 1; + rx_descriptor1->busy = 1; + tx_descriptor->busy = 0; + + *mac_config = MAC_ENABLE_TX | MAC_ENABLE_RX; + + enable_irq(); + + print_string("mac init done\n"); + +} + + +uint32_t link_status = 0; + +void link_check (void) { +uint8_t result; + + + + *miim_config = 1; + while(! (*miim_reg & 0x80000000)); + + if (*miim_reg & 0x700) + return; + + if ( (*miim_reg & 0x4)) + result = 1; + else + result = 0; + + if (result == 1 && link_status == 0) { + init_mac(); + print_string("link up\n"); + + link_status = result; + } + + if (result == 0 && link_status == 1) { + print_string("link dn\n"); + //*mac_config = 0; + + link_status = result; + reset_phy(); + } + + + + +} + + + +volatile uint32_t int_phy_reset = 0; +volatile uint32_t int_tx_done = 0; + +uint8_t eth_loop () +{ + link_check(); +} + + +uint32_t packets_sent = 0; + +void eth_send_frame (uint16_t len) { + + int i = 0; + tx_descriptor->len = len; + tx_descriptor->addr = 0xffff & (uint32_t)tx_buf; + tx_descriptor->busy = 1; + + packets_sent++; + + +} + + +void irq_handler(void) +{ + uint16_t len = 0; + volatile eth_descriptor * irq_descriptor; + + + + if (tx_descriptor->irq) { + asm("nop"); + int_tx_done = 1; + } + + if (rx_descriptor0->irq) + irq_descriptor = rx_descriptor0; + else if (rx_descriptor1->irq) + irq_descriptor = rx_descriptor1; + + len = irq_descriptor->len - 4; + if (len > 1512) while(1) print_word(0xBADBAD00); + + + memcpy ((void *) tx_buf, (void *) irq_descriptor->addr, len); + + + if (len > 10) + eth_send_frame (len); + + irq_descriptor->busy = 1; + + + + + +} + + + + + diff --git a/software/app/eth_config.h b/software/app/eth_config.h new file mode 100644 index 0000000..9a5f526 --- /dev/null +++ b/software/app/eth_config.h @@ -0,0 +1,27 @@ +#define MAC_REGS_BASE 0x84000000 +#define MAC_REG_RXDESCRIPTOR0 0x84000000 +#define MAC_REG_RXDESCRIPTOR1 0x84000004 +#define MAC_REG_TXDESCRIPTOR 0x84000008 +#define MAC_REG_CONFIG 0x8400000c +#define MAC_REG_MIICONFIG 0x84000010 +#define MAC_REG_MII 0x84000014 + + +//#define MII_BUSY ((ETH_REGS->MIISTATUS & 0x02) != 0) + +typedef struct +{ + uint8_t busy : 1; + const uint8_t fifo_flow_err : 1; + const uint8_t irq : 1; + uint16_t len : 13; + uint16_t addr; +} eth_descriptor; + + +#define MAC_ENABLE_RX 0x1 +#define MAC_ENABLE_TX 0x2 +#define MAC_RESET 0x8 + +#define MAC_INIT_CONFIG 0 + diff --git a/software/app/irq.S b/software/app/irq.S new file mode 100644 index 0000000..520185c --- /dev/null +++ b/software/app/irq.S @@ -0,0 +1,129 @@ +.section .text + +.global trap_entry +trap_entry: +# csrrw sp,mscratch,sp + addi sp,sp,-320 + sw ra,4(sp) + sw gp,12(sp) + sw tp,16(sp) + sw t0,20(sp) + sw t1,24(sp) + sw t2,28(sp) + sw s0,32(sp) + sw s1,36(sp) + sw a0,40(sp) + sw a1,44(sp) + sw a2,48(sp) + sw a3,52(sp) + sw a4,56(sp) + sw a5,60(sp) + sw a6,64(sp) + sw a7,68(sp) + sw s2,72(sp) + sw s3,76(sp) + sw s4,80(sp) + sw s5,84(sp) + sw s6,88(sp) + sw s7,92(sp) + sw s8,96(sp) + sw s9,100(sp) + sw s10,104(sp) + sw s11,108(sp) + sw t3,112(sp) + sw t4,116(sp) + sw t5,120(sp) + sw t6,124(sp) + csrr t0,mscratch + csrr s0,mstatus + csrr t1,mepc + csrr t2,mbadaddr + csrr t3,mcause + sw t0,8(sp) + sw s0,128(sp) + sw t1,132(sp) + sw t2,136(sp) + sw t3,140(sp) + li t0,-1 + sw t0,144(sp) + mv a0,sp + + bgez t3, .Lexcept + jal irq_handler + j .Lret + +.Lexcept: + la t0, jump_table + sll t3, t3, 2 + add t0, t0, t3 + lw t0, 0(t0) + jalr t0 + +.Lret: + mv a0,sp + lw t1,128(a0) + lw t2,132(a0) + addi sp,sp,320 +# csrw mscratch,sp + csrw mepc,t2 + lw ra,4(a0) +# lw sp,8(a0) #### + lw gp,12(a0) + lw tp,16(a0) + lw t0,20(a0) + lw t1,24(a0) + lw t2,28(a0) + lw s0,32(a0) + lw s1,36(a0) + lw a1,44(a0) + lw a2,48(a0) + lw a3,52(a0) + lw a4,56(a0) + lw a5,60(a0) + lw a6,64(a0) + lw a7,68(a0) + lw s2,72(a0) + lw s3,76(a0) + lw s4,80(a0) + lw s5,84(a0) + lw s6,88(a0) + lw s7,92(a0) + lw s8,96(a0) + lw s9,100(a0) + lw s10,104(a0) + lw s11,108(a0) + lw t3,112(a0) + lw t4,116(a0) + lw t5,120(a0) + lw t6,124(a0) + lw a0,40(a0) + mret + + .text + + .weak undefined_handler +undefined_handler: + j undefined_handler + + .weak undefined_insn_handler +undefined_insn_handler: + j undefined_insn_handler + + .data +jump_table: + .word undefined_handler # 0: Insn address misaligned + .word undefined_handler + .word undefined_insn_handler # 2: Illegal insn + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler + .word undefined_handler diff --git a/software/app/main.c b/software/app/main.c new file mode 100644 index 0000000..3f6b4c8 --- /dev/null +++ b/software/app/main.c @@ -0,0 +1,129 @@ +#include <stdio.h> +#include "riscv.h" +#include "eth_config.h" +#include "uart.h" +#include "string.h" + + + +uint32_t memtest_buffer [4096]; + +unsigned int memtest () { + int i = 0; + unsigned int res = 0; + + while (i < sizeof(memtest_buffer) >> 2) { + res = res ^ memtest_buffer [i]; + memtest_buffer[i++] = 0xAAAAAAAA; + } + + return res; + + +} + + + + + + +unsigned int cnt; + + +char * startup = "Fresh startup!\n"; + +void main(void) +{ +unsigned int proc_counter,counter = 0; + +volatile int * p_seu = (void*) 0x83000000; +volatile char * p_wd = (void*) 0x81000000; +volatile uint32_t * supervisor = (volatile) (uint32_t *) 0x86000000; + +int bert_started = 0; +uint32_t bert_counter = 0; + +print_string("\n\n\n\n"); + +print_string(startup); +print_line(); + +// in case of random PC reset, change content of heap memory to show it +startup[0] = 'R'; +startup[1] = 'R'; +startup[2] = 'R'; + + +print_string("M2S090\n"); +print_line(); +print_string(__DATE__); +print_line(); +print_string(__TIME__); +print_line(); + + +reset_phy(); +init_mac(); + +unsigned t; +asm volatile ("csrrci %0, mstatus, %1" : "=r"(t) : "i"(1 << 3)); + + +// Enable irq: set mie.meie +asm volatile ("csrrs %0, mie, %1" : "=r"(t) : "r"(1 << 11)); +asm volatile ("csrrsi %0, mstatus, %1" : "=r"(t) : "i"(1 << 3)); + +*p_wd = 1; //watchdog + + + + + +while (1) + +{ + uint32_t seu; + counter++; + + if (counter & 0x8000) { + counter = 0; + proc_counter++; + + seu = *p_seu++; + print_string("cnt: "); + print_word(proc_counter); + print_string(" seu iram: "); + print_word(seu); + + seu = *p_seu; + print_string(" seu dram: "); + print_word(seu); + + print_string(" mem: "); + print_word(memtest()); + print_line(); + + } + + + + eth_loop (); + refresh (); + uint32_t cpu_status = (*supervisor >> 16) & 0x7; + if (cpu_status != 7) { + print_string ("cpu not aligned!\n"); + asm volatile ("csrrci %0, mstatus, %1" : "=r"(t) : "i"(1 << 3)); + *supervisor = 2; // recovery + asm volatile ("csrrsi %0, mstatus, %1" : "=r"(t) : "i"(1 << 3)); + asm volatile ("csrrs %0, mie, %1" : "=r"(t) : "r"(1 << 11)); + } + + + + + *p_wd = 1; + +} + + +} diff --git a/software/app/powerlink.ld b/software/app/powerlink.ld new file mode 100644 index 0000000..0400ec1 --- /dev/null +++ b/software/app/powerlink.ld @@ -0,0 +1,72 @@ +OUTPUT_FORMAT("elf32-littleriscv") +ENTRY(_start) + +MEMORY +{ + iram : ORIGIN = 0x00000000, LENGTH = 32K + dram : ORIGIN = 0x00010000, LENGTH = 29K + dma : ORIGIN = 0x00010000 + 29K, LENGTH = 3K +} + + +SECTIONS +{ + + /* Begining of code and text segment */ + . = 0x00000000; + /* text: Program code section */ + .text : + { + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } > iram + + /* rodata: Read-only data */ + .data : + { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.data) + *(.data.*) + + *(.gnu.linkonce.d.*) + _edata = .; + + /* Have _gp point to middle of sdata/sbss to maximize displacement range */ + . = ALIGN(16); + _gp = . + 0x800; + + *(.sdata) + *(.sdata.*) + *(.srodata.*) + *(.gnu.linkonce.s.*) + + . = ALIGN(8); + _fbss = .; + + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + + _bss_start = .; + + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + _end = ALIGN(8); + } > dram + + PROVIDE(_fstack = ORIGIN(dram) + LENGTH(dram) - 4 - 0x1000); + + .dma : + { + *(.dma) + *(.dma.*) + } > dma +} diff --git a/software/app/refresh.s b/software/app/refresh.s new file mode 100644 index 0000000..c49df94 --- /dev/null +++ b/software/app/refresh.s @@ -0,0 +1,73 @@ +.section .text + +.global refresh +refresh: + + + addi sp,sp,-320 + sw ra,4(sp) + sw sp,8(sp) + sw gp,12(sp) + sw tp,16(sp) + sw t0,20(sp) + sw t1,24(sp) + sw t2,28(sp) + sw s0,32(sp) + sw s1,36(sp) + sw a0,40(sp) + sw a1,44(sp) + sw a2,48(sp) + sw a3,52(sp) + sw a4,56(sp) + sw a5,60(sp) + sw a6,64(sp) + sw a7,68(sp) + sw s2,72(sp) + sw s3,76(sp) + sw s4,80(sp) + sw s5,84(sp) + sw s6,88(sp) + sw s7,92(sp) + sw s8,96(sp) + sw s9,100(sp) + sw s10,104(sp) + sw s11,108(sp) + sw t3,112(sp) + sw t4,116(sp) + sw t5,120(sp) + sw t6,124(sp) + + lw ra,4(sp) + lw sp,8(sp) #### + lw gp,12(sp) + lw tp,16(sp) + lw t0,20(sp) + lw t1,24(sp) + lw t2,28(sp) + lw s0,32(sp) + lw s1,36(sp) + lw a1,44(sp) + lw a2,48(sp) + lw a3,52(sp) + lw a4,56(sp) + lw a5,60(sp) + lw a6,64(sp) + lw a7,68(sp) + lw s2,72(sp) + lw s3,76(sp) + lw s4,80(sp) + lw s5,84(sp) + lw s6,88(sp) + lw s7,92(sp) + lw s8,96(sp) + lw s9,100(sp) + lw s10,104(sp) + lw s11,108(sp) + lw t3,112(sp) + lw t4,116(sp) + lw t5,120(sp) + lw t6,124(sp) + lw a0,40(sp) + addi sp,sp,320 + ret + diff --git a/software/app/riscv.h b/software/app/riscv.h new file mode 100644 index 0000000..75d2ab9 --- /dev/null +++ b/software/app/riscv.h @@ -0,0 +1,37 @@ +#ifndef __RISCV_H +#define __RISCV_H + +#ifdef __GNUC__ + +#define riscv_read_csr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define riscv_write_csr(reg, val) \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)) + +#define riscv_swap_csr(reg, val) ({ long __tmp; \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + __tmp; }) + +#define riscv_set_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (bit) < 32) \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define riscv_clear_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (bit) < 32) \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define riscv_rdtime() riscv_read_csr(time) +#define riscv_rdcycle() riscv_read_csr(cycle) +#define riscv_rdinstret() riscv_read_csr(instret) + +#endif + +#endif diff --git a/software/app/uart.c b/software/app/uart.c new file mode 100644 index 0000000..aa5654f --- /dev/null +++ b/software/app/uart.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include "uart.h" +#include "string.h" + +void print_line (void) +{ + print_char('\n'); +} + +void print_char (char c) { + volatile uart_reg * uart_tx = (uart_reg *) UART_REGS_BASE; + while (!uart_tx->flags); + uart_tx->buffer = c; + uart_tx->flags = 2; + +} + +void print_string (char * str) { + uint8_t len = strlen(str); + for (char i=0; i < len; i++) + print_char(str[i]); + + +} + + + + +void print_word (uint32_t word) { + int8_t i; + uint8_t disp; + uint32_t temp; + char c; + + for (i=7; i >= 0; i--) { + + disp = ((word >> (i<<2)) & 0xf); + if (disp <= 9 ) + c = '0'+ disp; + else + c = 'A' + disp - 10; + + print_char (c); + } + +} diff --git a/software/app/uart.h b/software/app/uart.h new file mode 100644 index 0000000..04ded05 --- /dev/null +++ b/software/app/uart.h @@ -0,0 +1,16 @@ +#ifndef __UART_H + +#define __UART_H +#define UART_REGS_BASE 0x82000000 + +void print_line (void); +void print_char (char c) ; +void print_word (uint32_t word); +void print_string (char * str); + +typedef struct uart_reg { + uint32_t flags; + uint32_t buffer; +} uart_reg; + +#endif -- GitLab