From 7e0ba7151b6af1f6e557016cbeb8ecb52eeb51fc Mon Sep 17 00:00:00 2001 From: R Date: Fri, 12 Apr 2024 18:07:43 +0100 Subject: [PATCH] Copy minimal example to make bootloader --- .gdbinit | 2 ++ Makefile | 25 +++++++++++++ bootloader.c | 27 ++++++++++++++ linker.lds | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ startup.S | 77 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+) create mode 100644 .gdbinit create mode 100644 Makefile create mode 100644 bootloader.c create mode 100644 linker.lds create mode 100644 startup.S diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..cefc7d4 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,2 @@ +tar ext localhost:3333 +load diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3e2c8f1 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +.PHONY: all clean + +RV_ARCH = rv32imacxw + +CC = riscv-none-elf-gcc +OBJDUMP = riscv-none-elf-objdump +CFLAGS = -ggdb3 -Os -march=$(RV_ARCH) -ffunction-sections -fdata-sections +LDFLAGS = -ggdb3 -march=$(RV_ARCH) -Wl,--gc-sections --specs=nosys.specs + +all: bootloader.elf + +bootloader.elf: startup.o bootloader.o + +%.elf: linker.lds + $(CC) -Xlinker -Map=$(@:.elf=.map) -Wl,--script=linker.lds -nostartfiles -o $@ $(filter-out linker.lds,$+) + $(OBJDUMP) -xdsS $@ >$(@:.elf=.dump) + +%.o: %.S + $(CC) $(CFLAGS) -c -o $@ $< + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f *.o *.elf *.map *.dump diff --git a/bootloader.c b/bootloader.c new file mode 100644 index 0000000..31e6c07 --- /dev/null +++ b/bootloader.c @@ -0,0 +1,27 @@ +#include + +#pragma GCC diagnostic ignored "-Wprio-ctor-dtor" +__attribute__((constructor(0))) static void setup_qingke() { + asm volatile( + // Undocumented "Configure pipelining and instruction prediction" + "li t0, 0x1f\n" + "csrw 0xbc0, t0\n" + ); +} + +#define R32_RCC_APB2PCENR (*(volatile uint32_t*)0x40021018) +#define R32_GPIOA_CFGLR (*(volatile uint32_t*)0x40010800) +#define R32_GPIOA_BSHR (*(volatile uint32_t*)0x40010810) + +int main(void) { + R32_RCC_APB2PCENR |= 1 << 2; + R32_GPIOA_CFGLR = (R32_GPIOA_CFGLR & ~0xf) | (0b0010 << 0); + while (1) { + R32_GPIOA_BSHR = 1 << 0; + for (int i = 0; i < 500000; i++) + asm volatile(""); + R32_GPIOA_BSHR = 1 << 16; + for (int i = 0; i < 500000; i++) + asm volatile(""); + } +} diff --git a/linker.lds b/linker.lds new file mode 100644 index 0000000..fc3ea8d --- /dev/null +++ b/linker.lds @@ -0,0 +1,99 @@ +ENTRY( _start ) + +__stack_size = 512; +PROVIDE( _stack_size = __stack_size ); + +MEMORY +{ + /* CH32V20x_D6 -> 10 KB SRAM */ + /* allow full flash (incl. non-zero-wait) */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 224K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 10K +} + +SECTIONS +{ + .vector : + { + *(.vector); + . = ALIGN(4); + } >FLASH + + .text : + { + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + PROVIDE(_data_lma = .); + + .data : + { + PROVIDE(_data_vma = .); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(4); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + . = ALIGN(4); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM + + PROVIDE( _end = _ebss); + + .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : + { + PROVIDE( _heap_end = . ); + PROVIDE( _susrstack = . ); + . = . + __stack_size; + PROVIDE( _eusrstack = .); + } >RAM +} diff --git a/startup.S b/startup.S new file mode 100644 index 0000000..4e8a39b --- /dev/null +++ b/startup.S @@ -0,0 +1,77 @@ +.section .vector,"ax",@progbits +.align 1 + +.global _start +_start: + // Set up global pointer +.option push +.option norelax + la gp, __global_pointer$ +.option pop + + // Load data section from flash to RAM + la a0, _data_lma + la a1, _data_vma + la a2, _edata + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b +2: + + // Clear bss section + la a0, _sbss + la a1, _ebss + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + + // Call preinit array functions + la s0, __preinit_array_start + la s1, __preinit_array_end + bgeu s0, s1, 2f +1: + lw t0, (s0) + jalr t0 + addi s0, s0, 4 + bltu s0, s1, 1b +2: + + // Call init array functions + la s0, __init_array_start + la s1, __init_array_end + bgeu s0, s1, 2f +1: + lw t0, (s0) + jalr t0 + addi s0, s0, 4 + bltu s0, s1, 1b +2: + + // Invoke main with a possible mode switch + la ra, 1f + la t0, main + csrw mepc, t0 + mret + +1: + // Return from main, call fini array functions + la s0, __fini_array_start + la s1, __fini_array_end + bgeu s0, s1, 2f +1: + lw t0, (s0) + jalr t0 + addi s0, s0, 4 + bltu s0, s1, 1b +2: + + // Finally, loop infinitely + wfi + j 2b