diff --git a/software/bootldr/Makefile b/software/bootldr/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..277c9d97d504d26b6a3499d455039fd94f0202a0 --- /dev/null +++ b/software/bootldr/Makefile @@ -0,0 +1,42 @@ +#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: bootloader.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) $< + +refresh.o: refresh.s + $(CC) -c -o $@ $(CFLAGS) $< + +main: main.o crt0.o bootldr.ld + $(CC) -o $@ -nostartfiles $(CFLAGS) crt0.o main.o -T bootldr.ld + +main-text.bin: main + riscv32-elf-objcopy -j .text -j .loader -O binary $< $@ + +bootloader.hex: main-text.bin + riscv32-elf-objcopy -I binary -O ihex $< $@ + +clean: + rm main + rm main-text.* + rm bootloader.* diff --git a/software/bootldr/bootldr.ld b/software/bootldr/bootldr.ld new file mode 100644 index 0000000000000000000000000000000000000000..9f4c4897df4288b7aec1818bb38de530b1c396a1 --- /dev/null +++ b/software/bootldr/bootldr.ld @@ -0,0 +1,75 @@ +OUTPUT_FORMAT("elf32-littleriscv") +ENTRY(_start) + +MEMORY +{ + iram : ORIGIN = 0x00000000, LENGTH = 512 + ldr : ORIGIN = 0x00000200, LENGTH = 512 + dram : ORIGIN = 0x00010000, LENGTH = 64K + +} + + +SECTIONS +{ + + /* Begining of code and text segment */ + . = 0x00000000; + /* text: Program code section */ + .text : + { + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + + } > iram + .loader : + { + *(.launcher) + *(.launcher.*) + *(.launcher_call) + } > ldr + + /* 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) - 0x100); + +} diff --git a/software/bootldr/crt0.S b/software/bootldr/crt0.S new file mode 100644 index 0000000000000000000000000000000000000000..798083d7fa8dbc83f0999481e74d494d05aeef23 --- /dev/null +++ b/software/bootldr/crt0.S @@ -0,0 +1,81 @@ + .section .boot, "ax", @progbits + +.global _start +_start: + j _entry + +.org 0x8 + + + +_entry: + + + + 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 + + li t1, 0xffff +1: + + sw zero, 0(t0) + addi t0, t0, 4 + and t0, t0, t1 + bne t0, zero, 1b + lui t0, 0 + lui t1, 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 + + .data +_recov_data: .long 0 diff --git a/software/bootldr/main.c b/software/bootldr/main.c new file mode 100644 index 0000000000000000000000000000000000000000..bc3665b2c3384542dae33ae91a94657db67e3df8 --- /dev/null +++ b/software/bootldr/main.c @@ -0,0 +1,154 @@ +// TO DO: check integrity of the image before executing it + + +#include <stdio.h> +//#include <string.h> +#include "riscv.h" + +#define IRAM_SIZE 65536 +#define LOADER_SIZE 512 +#define APP_IMAGE_TEXT 0x60000000 +#define APP_IMAGE_DATA 0x60020000 +#define LOADER_IMAGE 0x60012200 + +#define print_line() print_char('\n');print_char('\r') + +typedef struct uart_reg { + uint32_t flags; + uint32_t buffer; +} uart_reg; + +void __attribute__((__section__(".launcher_call"))) print_string (char * str, unsigned char len) { + + for (char i=0; i < len; i++) + print_char(str[i]); + + +} + +void __attribute__((always_inline)) print_char (char c) { + volatile uart_reg * uart_tx = (uart_reg *) 0x82000000; + while (!uart_tx->flags); + uart_tx->buffer = c; + uart_tx->flags = 2; + +} + + +void __attribute__((__section__(".launcher_call"))) 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); + } + +} + + +uint32_t __attribute__((__section__(".launcher_call"))) envm_read (uint32_t * addr) { + + volatile uint32_t * wb_envm_dev = 0x87000000; + + while (wb_envm_dev[0] & 0x1); + wb_envm_dev[1] = addr; + while (*wb_envm_dev & 0x1); + + return wb_envm_dev[2]; +} + + +void __attribute__((__section__(".launcher"))) iram_write (uint32_t * addr, uint32_t data) { + + volatile uint32_t * wb_iram_dev = 0x87000010; + + + wb_iram_dev[0] = addr; + wb_iram_dev[1] = data; + asm ("nop"); + // asm("nop"); + // asm("nop"); + // asm("nop"); + +} + + + + +void load_image (); + + +void main(void) +{ + + + const char boot_logo [5] = {'b','o','o','t'}; + + + volatile char * p_wd = 0x81000000; + void (*func)(void) = IRAM_SIZE - LOADER_SIZE + (&load_image - 0x200) ; + uint32_t i, data = 0; + + + //print_line(); + print_string (boot_logo, 4); + print_line(); + + + + for (i=1024; i < (1<<16); i=i+4) + iram_write(i, 0); + + for (i=0; i < 1024; i=i+4) { + data = envm_read (LOADER_IMAGE + i); + iram_write(IRAM_SIZE-LOADER_SIZE+i, data); + } + + *p_wd = 1; + + (*func)(); // jump to (relocated) load_image() + + + + while(1); +// *p_wd = 1; //watchdog + + + +} + + +void __attribute__((__section__(".launcher"))) load_image () { + const char done [5] = {'D','o','n', 'e'}; + uint32_t i, data = 0; + uint32_t * dram = 0; + void (*func)(void) = 0 ; + + for (i=0; i < IRAM_SIZE-LOADER_SIZE; i=i+4) { + data = envm_read (APP_IMAGE_TEXT + i); + iram_write (i, data); + } + + for (i=0; i < (1<<16)-1024; i=i+4) { + data = envm_read (APP_IMAGE_DATA + i); + *dram++ = data; + } + print_string(done, 4); + + + (*func)(); // run app + + while(1); + + +} + diff --git a/software/bootldr/riscv.h b/software/bootldr/riscv.h new file mode 100644 index 0000000000000000000000000000000000000000..75d2ab9ef9274f111d9106b1797718e28e7c04e5 --- /dev/null +++ b/software/bootldr/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