Commit 07a15a52 authored by Mattia Rizzi's avatar Mattia Rizzi

Simple app to perform a check of the SoC under radiation.

It's a ethernet echo loopback with some debug infos printed over ethernet
parent 05403a7b
#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
.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
#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;
}
#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
.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
#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;
}
}
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
}
.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
#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
#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);
}
}
#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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment