diff --git a/docs/Bootloaders.md b/docs/Bootloaders.md index 94b9b0dd..830077ef 100755 --- a/docs/Bootloaders.md +++ b/docs/Bootloaders.md @@ -209,11 +209,11 @@ avrdude -c stk500v2 -p atmega2560 -P /dev/ttyACM0 -u -Uflash:w:out/klipper.elf.h STM32F103 micro-controllers (Blue Pill devices) =============================================== -The STM32F103 devices have a ROM that can flash a bootloader via 3.3V -serial. To access this ROM, one should connect the "boot 0" pin to -high and "boot 1" pin to low, and then reset the device. The -"stm32flash" package can then be used to flash the device using -something like: +The STM32F103 devices have a ROM that can flash a bootloader or +application via 3.3V serial. To access this ROM, one should connect +the "boot 0" pin to high and "boot 1" pin to low, and then reset the +device. The "stm32flash" package can then be used to flash the device +using something like: ``` stm32flash -w out/klipper.bin -v -g 0 /dev/ttyAMA0 ``` @@ -224,8 +224,32 @@ stm32flash protocol uses a serial parity mode which the Raspberry Pi's https://www.raspberrypi.org/documentation/configuration/uart.md for details on enabling the full uart on the Raspberry Pi GPIO pins. -This document does not describe the method to flash an application via -an STM32F103 bootloader. +After flashing, set both "boot 0" and "boot 1" back to low so that +future resets boot from flash. + +## STM32F103 with stm32duino bootloader ## + +The "stm32duino" project has a USB capable bootloader - see: +https://github.com/rogerclarkmelbourne/STM32duino-bootloader + +This bootloader can be flashed via 3.3V serial with something like: +``` +wget 'https://github.com/rogerclarkmelbourne/STM32duino-bootloader/raw/master/binaries/generic_boot20_pc13.bin' +stm32flash -w generic_boot20_pc13.bin -v -g 0 /dev/ttyAMA0 +``` + +This bootloader uses 8KiB of flash space (the application must be +compiled with a start address of 8KiB). Flash an application with +something like: +``` +dfu-util -d 1eaf:0003 -a 2 -R -D out/klipper.bin +``` + +The bootloader typically runs for only a short period after boot. It +may be necessary to time the above command so that it runs while the +bootloader is still active (the bootloader will flash a board led +while it is running). Alternatively, set the "boot 0" pin to low and +"boot 1" pin to high to stay in the bootloader after a reset. LPC176x micro-controllers (Smoothieboards) ========================================== diff --git a/src/stm32f1/Kconfig b/src/stm32f1/Kconfig index 81e03bf1..802c793a 100644 --- a/src/stm32f1/Kconfig +++ b/src/stm32f1/Kconfig @@ -18,6 +18,19 @@ config CLOCK_FREQ int default 8000000 # 72000000 / 9 +choice + prompt "Bootloader offset" + config STM_FLASH_START_0000 + bool "No bootloader" + config STM_FLASH_START_2000 + bool "8KiB bootloader (stm32duino)" +endchoice + +config FLASH_START + hex + default 0x2000 if STM_FLASH_START_2000 + default 0x0000 + config USBSERIAL bool "Use USB for communication (instead of serial)" default y diff --git a/src/stm32f1/Makefile b/src/stm32f1/Makefile index 1d33c470..169e71ee 100644 --- a/src/stm32f1/Makefile +++ b/src/stm32f1/Makefile @@ -13,8 +13,7 @@ CFLAGS += -Ilib/hal-stm32f1/include CFLAGS += -DSTM32F103xB CFLAGS += -O3 -CFLAGS_klipper.elf += -Llib/cmsis-stm32f1/source/ -CFLAGS_klipper.elf += -Tlib/cmsis-stm32f1/source/stm32f1.ld +CFLAGS_klipper.elf += -T $(OUT)stm32f1.ld CFLAGS_klipper.elf += --specs=nano.specs --specs=nosys.specs # Add source files @@ -33,6 +32,13 @@ $(OUT)%.o: %.s $(OUT)autoconf.h $(OUT)board-link $(OUT)klipper.elf: $(patsubst %.s, $(OUT)src/%.o,$(asmsrc-y)) +# Build the linker script +target-y := $(OUT)stm32f1.ld $(target-y) + +$(OUT)stm32f1.ld: src/stm32f1/stm32f1.ld $(OUT)board-link + @echo " Preprocessing $@" + $(Q)$(CPP) -P -MD -MT $@ -DFLASH_START=$(CONFIG_FLASH_START) $< -o $@ + # Binary output file rules target-y += $(OUT)klipper.bin diff --git a/src/stm32f1/main.c b/src/stm32f1/main.c index c6839c36..b91d4dd0 100644 --- a/src/stm32f1/main.c +++ b/src/stm32f1/main.c @@ -135,6 +135,8 @@ int main(void) { SystemInit(); + SCB->VTOR += CONFIG_FLASH_START; + LL_Init1msTick(SystemCoreClock); clock_config(); adc_config(); diff --git a/src/stm32f1/stm32f1.ld b/src/stm32f1/stm32f1.ld new file mode 100644 index 00000000..e13d7c46 --- /dev/null +++ b/src/stm32f1/stm32f1.ld @@ -0,0 +1,113 @@ +/* Cortex-M linker script + + This file is taken from lib/cmsis-stm32f1/source/stm32f1.ld . It + has been modified to support a bootloader offset. +*/ + +ENTRY(Reset_Handler) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000 + FLASH_START, LENGTH = 64K - FLASH_START + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* highest address of the user mode stack */ +_estack = 0x20005000; + +SECTIONS +{ + /* Interrupt vector table */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } >FLASH + + /* Program code and constant data */ + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.rodata) + *(.rodata*) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + _etext = .; + } >FLASH + + /* Exception handling */ + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + /* Static constructor initialization (C++) */ + .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(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + + /* Initialized data, needs to be handled by startup code */ + _sidata = .; + .data : AT (_sidata) + { + . = ALIGN(4); + _sdata = . ; + _data = . ; + *(.data) + *(.data*) + *(.RAMtext) + . = ALIGN(4); + _edata = . ; + } >RAM + + /* Uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = .; + __bss_start__ = .; + _bss = .; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + __bss_end__ = _ebss; + } >RAM + + /* Pointers to end of data for dynamic memory management */ + PROVIDE (end = _ebss); + PROVIDE (_end = _ebss); + + /* Remove debugging from standard libraries */ + /DISCARD/ : + { + libc.a (*) + libm.a (*) + libgcc.a (*) + } +}