From cfc170f896abb323cdff3c646829b098e55e33ed Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Thu, 11 Nov 2021 10:04:17 +0800 Subject: [PATCH] tools: add flash_loader Signed-off-by: liangkangnan --- tools/flash_loader/.gitignore | 9 ++ tools/flash_loader/Makefile | 58 +++++++++++++ tools/flash_loader/bin2char.sh | 14 ++++ tools/flash_loader/link.ld | 148 +++++++++++++++++++++++++++++++++ tools/flash_loader/main.c | 63 ++++++++++++++ tools/flash_loader/start.S | 41 +++++++++ 6 files changed, 333 insertions(+) create mode 100644 tools/flash_loader/.gitignore create mode 100644 tools/flash_loader/Makefile create mode 100755 tools/flash_loader/bin2char.sh create mode 100644 tools/flash_loader/link.ld create mode 100644 tools/flash_loader/main.c create mode 100644 tools/flash_loader/start.S diff --git a/tools/flash_loader/.gitignore b/tools/flash_loader/.gitignore new file mode 100644 index 0000000..7000dc9 --- /dev/null +++ b/tools/flash_loader/.gitignore @@ -0,0 +1,9 @@ +# Object files +*.o +*.ko +*.obj +*.bin +*.dump +*.mem +flash_loader +tinyriscv.inc diff --git a/tools/flash_loader/Makefile b/tools/flash_loader/Makefile new file mode 100644 index 0000000..9193ff7 --- /dev/null +++ b/tools/flash_loader/Makefile @@ -0,0 +1,58 @@ +TARGET := flash_loader + +BSP_DIR := ../../sdk/bsp + +RISCV_TOOLS_PATH := /opt/riscv32/bin +RISCV_TOOLS_PREFIX := riscv32-unknown-elf- + +RISCV_GCC := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)gcc) +RISCV_AS := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)as) +RISCV_GXX := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)g++) +RISCV_OBJDUMP := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)objdump) +RISCV_GDB := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)gdb) +RISCV_AR := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)ar) +RISCV_OBJCOPY := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)objcopy) +RISCV_READELF := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)readelf) + + +.PHONY: all +all: $(TARGET) + +ASM_SRCS += start.S + +C_SRCS += main.c +C_SRCS += $(BSP_DIR)/lib/flash_ctrl.c + +LINKER_SCRIPT := link.ld + +INCLUDES += -I$(BSP_DIR)/include + +LDFLAGS += -Os -T $(LINKER_SCRIPT) -nostartfiles -Wl,--gc-sections -Wl,--check-sections + +ASM_OBJS := $(ASM_SRCS:.S=.o) +C_OBJS := $(C_SRCS:.c=.o) + +LINK_OBJS += $(ASM_OBJS) $(C_OBJS) +LINK_DEPS += $(LINKER_SCRIPT) + +CLEAN_OBJS += $(TARGET) $(LINK_OBJS) $(TARGET).dump $(TARGET).bin $(TARGET).hex $(TARGET).mem tinyriscv.inc + +CFLAGS += -march=rv32im +CFLAGS += -mabi=ilp32 +CFLAGS += -mcmodel=medlow -ffunction-sections -fdata-sections -fno-builtin-printf -fno-builtin-malloc + +$(TARGET): $(LINK_OBJS) $(LINK_DEPS) Makefile + $(RISCV_GCC) $(CFLAGS) $(INCLUDES) $(LINK_OBJS) -o $@ $(LDFLAGS) + $(RISCV_OBJCOPY) -O binary $@ $@.bin + $(RISCV_OBJDUMP) --disassemble-all $@ > $@.dump + ./bin2char.sh < flash_loader.bin > tinyriscv.inc + +$(ASM_OBJS): %.o: %.S + $(RISCV_GCC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +$(C_OBJS): %.o: %.c + $(RISCV_GCC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +.PHONY: clean +clean: + rm -f $(CLEAN_OBJS) diff --git a/tools/flash_loader/bin2char.sh b/tools/flash_loader/bin2char.sh new file mode 100755 index 0000000..85a0fd6 --- /dev/null +++ b/tools/flash_loader/bin2char.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +[ $# != 0 ] && { + echo "Usage: $0" + echo + echo "Read binary data from standard input and write it as a comma separated" + echo "list of hexadecimal byte values to standard ouput. The output is usable" + echo "as a C array initializer. It is terminated with a comma so it can be" + echo "continued e.g. for zero termination." + exit 1 +} + +echo "/* Autogenerated with $0 */" +od -v -A n -t x1 | sed 's/ *\(..\) */0x\1,/g' diff --git a/tools/flash_loader/link.ld b/tools/flash_loader/link.ld new file mode 100644 index 0000000..e38cee4 --- /dev/null +++ b/tools/flash_loader/link.ld @@ -0,0 +1,148 @@ +OUTPUT_ARCH( "riscv" ) +ENTRY(_start) + + +MEMORY +{ + flash (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 4K + ram (wxa!ri) : ORIGIN = 0x20001000, LENGTH = 1K +} + + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 256; + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash + + .text : + { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash + + . = ALIGN(4); + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>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 AT>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 AT>flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram + + . = ALIGN(8); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + __freertos_irq_stack_top = .; + } >ram AT>ram + +} diff --git a/tools/flash_loader/main.c b/tools/flash_loader/main.c new file mode 100644 index 0000000..be70e5a --- /dev/null +++ b/tools/flash_loader/main.c @@ -0,0 +1,63 @@ +#include + +#include "flash_ctrl.h" + + +// 烧写数据地址:4K + 1K + 256 +#define DATA_ADDR (0x20001500) + +// 烧写数据长度 +#define DATA_LEN (0x20001400) + +// 烧写(擦除)地址 +#define PROGRAM_ADDR (0x20001404) + +// 擦除标志 +// 0: 不擦除,1:擦除 +#define ERASE_FLAG (0x20001408) + +// 烧写状态标志 +// bit0为烧写结束标志,0:未烧写完成,1:烧写完成。 +// bit1为烧写结果标志,0:烧写失败,1:烧写成功 +#define RESULT_FLAG (0x2000140C) + +#define PAGE_SIZE (256) + + +static uint32_t *data_p; +static uint32_t *result_p; +static uint32_t len, addr; +static uint32_t erase; +static uint8_t succ; + +int main() +{ + data_p = (uint32_t *)DATA_ADDR; + result_p = (uint32_t *)RESULT_FLAG; + len = *((uint32_t *)DATA_LEN); + addr = *((uint32_t *)PROGRAM_ADDR); + erase = *((uint32_t *)ERASE_FLAG); + + *result_p = 0; + + flash_ctrl_init(); + + // 擦除操作 + if (erase) { + // 擦除子扇区 + succ = flash_ctrl_sector_erase(addr); + // 编程操作 + } else { + // 编程 + succ = flash_ctrl_page_program(addr, data_p, len); + } + + flash_ctrl_deinit(); + + if (succ) + *result_p = 0x3; + else + *result_p = 0x1; + + while (1); +} diff --git a/tools/flash_loader/start.S b/tools/flash_loader/start.S new file mode 100644 index 0000000..ce08b41 --- /dev/null +++ b/tools/flash_loader/start.S @@ -0,0 +1,41 @@ + .section .init; + .globl _start; + .type _start,@function + + +_start: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la sp, _sp + + /* Load data section */ + la a0, _data_lma + la a1, _data + 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, __bss_start + la a1, _end + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + + li a0, 0 + li a1, 0 + call main + +loop: + j loop