From 4057f5239e73aa27b9574561d6a0ae752968eff2 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sat, 6 Jul 2024 19:15:41 +0200 Subject: [PATCH] sw: Add bootrom --- sw/bootrom/.gitignore | 4 ++ sw/bootrom/boot.ld | 45 ++++++++++++++++++++++ sw/bootrom/build.sh | 8 ++++ sw/bootrom/main.c | 87 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 sw/bootrom/.gitignore create mode 100644 sw/bootrom/boot.ld create mode 100755 sw/bootrom/build.sh create mode 100644 sw/bootrom/main.c diff --git a/sw/bootrom/.gitignore b/sw/bootrom/.gitignore new file mode 100644 index 0000000..6bbf4d8 --- /dev/null +++ b/sw/bootrom/.gitignore @@ -0,0 +1,4 @@ +*.bin +*.elf +*.hex +*.vhex diff --git a/sw/bootrom/boot.ld b/sw/bootrom/boot.ld new file mode 100644 index 0000000..78416a1 --- /dev/null +++ b/sw/bootrom/boot.ld @@ -0,0 +1,45 @@ +__heap_size = 0x80; +__stack_size = 0x80; + +MEMORY +{ + ROM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x100 + RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x400 +} +SECTIONS +{ + .text : + { + *(.boot) + *(.text) + *(.text) + *(.rodata*) + } > ROM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM +} diff --git a/sw/bootrom/build.sh b/sw/bootrom/build.sh new file mode 100755 index 0000000..248cd38 --- /dev/null +++ b/sw/bootrom/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +riscv64-elf-gcc -mabi=ilp32 -march=rv32i -nostdlib -nostartfiles -ffreestanding -T boot.ld -Os -o bootrom.elf main.c +#riscv64-elf-objdump -D bootrom.elf +riscv64-elf-objcopy -O binary bootrom.elf bootrom.bin +od --endian=little -vtx4 -An -w4 bootrom.bin | tr -d ' ' > bootrom.vhex +r2 -A -c 'pdf @ sym._start' -q bootrom.elf diff --git a/sw/bootrom/main.c b/sw/bootrom/main.c new file mode 100644 index 0000000..b636f69 --- /dev/null +++ b/sw/bootrom/main.c @@ -0,0 +1,87 @@ +#include + +#define UART0_BASE 0x81000000 +#define UART0_SR (*((volatile uint32_t *) (UART0_BASE + 0x00))) +#define UART0_DR (*((volatile uint32_t *) (UART0_BASE + 0x04))) + +#define UART0_SR_RX_DATA_EMPTY (1 << 0) +#define UART0_SR_TX_FULL (1 << 1) + +/* +// Set up stack pointer +asm("_start:\ + xor sp, sp, sp;\ + lui sp, 0x80100;\ + j main;\ +"); +*/ + +__attribute__((noreturn)) void _start() { + uint8_t state = 0; + uint8_t c; + uint8_t opcode; + uint8_t *ptr; + uint32_t length; + + /*while (1) { + while (UART0_SR & UART0_SR_RX_DATA_EMPTY); + c = UART0_DR; + while (UART0_SR & UART0_SR_TX_FULL); + UART0_DR = c; + }*/ + + while (1) { + while (UART0_SR & UART0_SR_RX_DATA_EMPTY); + c = UART0_DR; + state++; + switch (state) { + case 1: // Opcode + opcode = c; + ptr = 0; + length = 0; + if (c == 0) // NOP + state = 0; + break; + case 2: // Address + case 3: + case 4: + case 5: + ptr = (uint8_t*)(((uint32_t)ptr << 8) | c); + if (state != 5) + break; + if (opcode == 3) { // Jump + //((void (*)()) ptr)(); + asm("jalr %0" : : "r"(ptr)); // Not sure why, but the jump above causes GCC to save variables to the stack at the beginning of this function + __builtin_unreachable(); + } + break; + case 6: // Length + case 7: + case 8: + case 9: + length = (length << 8) | c; + if (state != 9) + break; + if (opcode == 2) { // Read + for (; length > 0; length--) { + while (UART0_SR & UART0_SR_TX_FULL); + UART0_DR = *(ptr); + ptr++; + } + state = 0; + } + break; + case 10: // Write byte by byte + *(ptr++) = c; + if (--length == 0) { + state = 0; + } else { + state--; // Stay in this state + } + break; + default: + break; + } + } + __builtin_unreachable(); +}