diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1e1793 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.elf +*.map +*.dump diff --git a/minimal-payload/.gdbinit b/minimal-payload/.gdbinit new file mode 100644 index 0000000..cefc7d4 --- /dev/null +++ b/minimal-payload/.gdbinit @@ -0,0 +1,2 @@ +tar ext localhost:3333 +load diff --git a/minimal-payload/Makefile b/minimal-payload/Makefile new file mode 100644 index 0000000..ee5d098 --- /dev/null +++ b/minimal-payload/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: main.elf + +main.elf: startup.o main.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/minimal-payload/linker.lds b/minimal-payload/linker.lds new file mode 100644 index 0000000..fc3ea8d --- /dev/null +++ b/minimal-payload/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/minimal-payload/main.c b/minimal-payload/main.c new file mode 100644 index 0000000..0acfe22 --- /dev/null +++ b/minimal-payload/main.c @@ -0,0 +1,25 @@ +int test = 0x12345; +int test2; + +#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" + ); +} + +__attribute__((constructor)) static void constructor() { + test2 = 0x5678; +} + +__attribute__((destructor)) static void destructor() { + test2 = 0x9abc; +} + +int main(void) { + test++; + test2--; + return 123; +} diff --git a/minimal-payload/startup.S b/minimal-payload/startup.S new file mode 100644 index 0000000..4e8a39b --- /dev/null +++ b/minimal-payload/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