From 0be35cfc81d1bbc67f40459d13a494e912cf7208 Mon Sep 17 00:00:00 2001 From: rusefi Date: Thu, 1 Jun 2017 20:32:26 -0400 Subject: [PATCH] bootloader - first step --- .../STMFlashLoader_all_screenshots.png | Bin 0 -> 33996 bytes firmware/bootloader/readme.txt | 45 +++ firmware/bootloader/src/Makefile | 329 ++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 firmware/bootloader/STMFlashLoader_all_screenshots.png create mode 100644 firmware/bootloader/readme.txt create mode 100644 firmware/bootloader/src/Makefile diff --git a/firmware/bootloader/STMFlashLoader_all_screenshots.png b/firmware/bootloader/STMFlashLoader_all_screenshots.png new file mode 100644 index 0000000000000000000000000000000000000000..a663b26cbaa1db4fe9f993bdf5348cb0ebf8dee3 GIT binary patch literal 33996 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 R!yW)X>MEBnSelection command (only Sector erase is currently supported, not Full Erase!). + +To update the firmware: +- choose "Download to device" mode; +- select the firmware file (rusefi.hex). Note! ***Use only recent firmware builds with bootloader support!*** +- you may select "verify" option to check +- you may select "Jump to the user program" to automatically run the main firmware after the update. + +See STMFlashLoader_all_screenshots.png for more info. + +!!! Note that the bootloader can update only the main firmware, but not itself !!! + +Use this code on your own risk! + + +*** Developers Section *** + +How it works, in two words: +- The bootloader requires a separate makefile because it's a separate binary executable with its own project settings and fileset. +- Start firmware/bootloader/compile_bootloader.bat to compile the bootloader code. Use it only if bootloader modification is required. +- The compiled bootloader code is stored in bootloader/bootloader_generated.hxx and it can be included into the main firmware (build/rusefi.hex) if the bootloader support is enabled. +- The bootloader support is disabled by default (USE_BOOTLOADER=no). You can enable it by adding "USE_BOOTLOADER=yes" to Makefile or "SET USE_BOOTLOADER=yes" to your Windows compile batch-file. +- When USE_BOOTLOADER=yes, a special version of linker script is used: STM32F407xG_CCM_bootloader.ld. It shifts 'flash' memory address to 32kb (0x08008000), and clears a space for bootloader at the very beginning of the flash memory. It also adds section ".bl" for the bootloader code. +- The file bootloader_storage.c used to include the bootloader code into the firmware (using '.bl' section). +- In result, there are two binary executables combined in one firmware: the bootloader starts first, and the main firmware start afterwards. +- All those can be overridden by board configs and makefiles - that's exactly how it's been compiled for Prometheus board. + +The bootloader executable works as follows: +- Init ChibiOS and UART/Serial driver using tunerstudio_io code; +- Create a thread to listen to UART (thBootloaderSerial), using dfuStartLoop(); +- The PC 'stm32-flasher' software sends its request byte only once, so we don't wait for it - the bootloader sends an answer as soon as it starts (both the request & answer bytes are known consts); +- If the next command doesn't come immediately (<100 ms), we abort the bootloader dfu loop and run the application code - calling dfuJumpToApp() in main(). +- Otherwise, if at least one command is received, we stay in the bootloader mode and process commands. diff --git a/firmware/bootloader/src/Makefile b/firmware/bootloader/src/Makefile new file mode 100644 index 0000000000..915a2bcb91 --- /dev/null +++ b/firmware/bootloader/src/Makefile @@ -0,0 +1,329 @@ +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# by default EXTRA_PARAMS is empty and we create 'debug' version of the firmware with additional assertions and statistics +# for 'release' options see 'clean_compile_two_versions.bat' file + +ifeq ($(DEBUG_LEVEL_OPT),) + # this value would be used by default. For 'debug' configuration override with '-O0 -ggdb -g3' or something along these lines + DEBUG_LEVEL_OPT = -O2 + DDEFS += -DEFI_ENABLE_ASSERTS=FALSE -DCH_DBG_ENABLE_TRACE=FALSE -DCH_DBG_ENABLE_ASSERTS=FALSE -DCH_DBG_ENABLE_STACK_CHECK=FALSE -DCH_DBG_FILL_THREADS=FALSE -DCH_DBG_THREADS_PROFILING=FALSE +endif + +# disable some modules to shrink bootloader binary +DDEFS += -DHAL_USE_ADC=FALSE -DHAL_USE_CAN=FALSE -DHAL_USE_EXT=FALSE -DHAL_USE_GPT=FALSE -DHAL_USE_I2C=FALSE -DHAL_USE_ICU=FALSE -DHAL_USE_PWM=FALSE -DHAL_USE_RTC=FALSE -DHAL_USE_I2C=FALSE + +# disable USB (The bootloader has currently UART support only) +DDEFS += -DEFI_USB_SERIAL=FALSE -DHAL_USE_SERIAL_USB=FALSE -DHAL_USE_USB=FALSE -DHAL_USE_USB_MSD=FALSE + + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = $(EXTRA_PARAMS) $(DEBUG_LEVEL_OPT) $(RFLAGS) -fomit-frame-pointer -falign-functions=16 -Werror-implicit-function-declaration -Werror -Wno-error=pointer-sign -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=sign-compare -Wno-error=unused-parameter -Wno-error=missing-field-initializers -Werror=type-limits -Wno-error=strict-aliasing -Wno-error=attributes +endif + +#USE_OPT += -fPIC + +# C specific options here (added to USE_OPT). +ifeq ($(USE_COPT),) + USE_COPT = -fgnu89-inline -std=gnu99 +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -std=c++11 -fno-rtti -fno-exceptions -fno-use-cxa-atexit -Werror=write-strings -Werror=type-limits +endif + +# Enable this if you want the linker to remove unused code and data +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# Linker extra options here. +ifeq ($(USE_LDOPT),) + USE_LDOPT = +endif + +# Enable this if you want link time optimizations (LTO) +ifeq ($(USE_LTO),) + USE_LTO = no +endif + +# If enabled, this option allows to compile the application in THUMB mode. +ifeq ($(USE_THUMB),) + USE_THUMB = yes +endif + +# Enable this if you want to see the full log while compiling. +ifeq ($(USE_VERBOSE_COMPILE),) + USE_VERBOSE_COMPILE = no +endif + +# If enabled, this option makes the build process faster by not compiling +# modules not used in the current configuration. +ifeq ($(USE_SMART_BUILD),) + USE_SMART_BUILD = no +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Stack size to be allocated to the Cortex-M process stack. This stack is +# the stack used by the main() thread. +ifeq ($(USE_PROCESS_STACKSIZE),) + USE_PROCESS_STACKSIZE = 0x0600 +endif + +# Stack size to the allocated to the Cortex-M main/exceptions stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_EXCEPTIONS_STACKSIZE),) + USE_EXCEPTIONS_STACKSIZE = 0x1000 +endif + +# Enables the use of FPU on Cortex-M4 (no, softfp, hard). +ifeq ($(USE_FPU),) + USE_FPU = softfp +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define project name here +PROJECT = bootloader +PROJECT_DIR = .. + +# Imported source files and paths +CHIBIOS = $(PROJECT_DIR)/ChibiOS3 +CHIBIOS_CONTRIB = $(PROJECT_DIR)/ChibiOS-Contrib + +ifeq ($(PROJECT_BOARD),) + PROJECT_BOARD = ST_STM32F4 +endif +DDEFS += -D$(PROJECT_BOARD) + +CONFIG = $(PROJECT_DIR)/config + +# Startup files. +include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk +# HAL-OSAL files (optional). +include $(CHIBIOS_CONTRIB)/os/hal/hal.mk +include $(CHIBIOS_CONTRIB)/os/hal/ports/STM32/STM32F4xx/platform.mk +include $(CHIBIOS)/os/hal/osal/rt/osal.mk +# RTOS files (optional). +include $(CHIBIOS)/os/rt/rt.mk +include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk +include $(CHIBIOS)/os/various/cpp_wrappers/chcpp.mk + +include $(CONFIG)/boards/$(PROJECT_BOARD)/board.mk + +# Define linker script file here +ifeq ($(LDSCRIPT),) + LDSCRIPT= $(CONFIG)/stm32f4ems/STM32F407xG_CCM.ld +endif + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(STARTUPSRC) \ + $(KERNSRC) \ + $(PORTSRC) \ + $(OSALSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + $(CHIBIOS)/os/various/syscalls.c \ + $(CHIBIOS)/os/hal/lib/streams/memstreams.c \ + $(CHIBIOS)/os/hal/lib/streams/chprintf.c \ + $(CHIBIOS)/os/various/shell.c \ + $(UTILSRC) \ + $(ENGINES_SRC) \ + $(CONSOLESRC) \ + $(DEV_SRC) \ + $(HW_LAYER_EMS) \ + $(CONTROLLERSSRC) \ + $(CONTROLLERS_ALGO_SRC) \ + $(CONTROLLERS_CORE_SRC) \ + $(CONTROLLERS_SENSORS_SRC) \ + $(FATFSSRC) \ + $(SYSTEMSRC) \ + $(PROJECT_DIR)/hw_layer/flash.c + +# C++ sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CPPSRC = $(CHCPPSRC) \ + $(TRIGGER_SRC_CPP) \ + $(TRIGGER_DECODERS_SRC_CPP) \ + $(DEV_SRC_CPP) \ + $(CONTROLLERS_ALGO_SRC_CPP) \ + $(SYSTEMSRC_CPP) \ + $(BOARDSRC_CPP) \ + $(ENGINES_SRC_CPP) \ + $(HW_LAYER_EMS_CPP) \ + $(HW_SENSORS_SRC) \ + $(TUNERSTUDIO_SRC_CPP) \ + $(CONSOLE_SRC_CPP) \ + $(CONTROLLERS_SENSORS_SRC_CPP) \ + $(CONTROLLERS_SRC_CPP) \ + $(UTILSRC_CPP) \ + $(CONTROLLERS_CORE_SRC_CPP) \ + $(CONTROLLERS_MATH_SRC_CPP) \ + $(PROJECT_DIR)/console/binary/tunerstudio_io.cpp \ + $(PROJECT_DIR)/controllers/system/efiGpio.cpp \ + $(PROJECT_DIR)/controllers/algo/engine_configuration.cpp \ + $(PROJECT_DIR)/hw_layer/io_pins.cpp \ + $(PROJECT_DIR)/hw_layer/pin_repository.cpp \ + src/rusefi_stubs.cpp \ + src/dfu.cpp \ + src/main.cpp + +# C sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACSRC = + +# C++ sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACPPSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCPPSRC = + +# List ASM source files here +# List ASM source files here +ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) + +INCDIR = .. \ + $(PORTINC) \ + $(OSALINC) \ + $(KERNINC) \ + $(TESTINC) \ + $(STARTUPINC) \ + $(HALINC) \ + $(PLATFORMINC) \ + $(BOARDINC) \ + $(CHCPPINC) \ + $(CHIBIOS)/os/hal/lib/streams \ + $(CHIBIOS)/os/various \ + $(CHIBIOS)/os/various/devices_lib/accel \ + $(CHIBIOS_CONTRIB)/os/various \ + $(CONFIG)/stm32f4ems \ + $(CHIBIOS)/os/various \ + $(CONFIG)/stm32f4ems \ + $(CONFIG)/engines \ + $(PROJECT_DIR)/ext \ + $(PROJECT_DIR)/ext_algo \ + $(PROJECT_DIR)/util \ + $(PROJECT_DIR)/console_util \ + $(PROJECT_DIR)/console \ + $(PROJECT_DIR)/console/binary \ + $(PROJECT_DIR)/console/fl_binary \ + $(PROJECT_DIR)/hw_layer \ + $(PROJECT_DIR)/mass_storage \ + $(PROJECT_DIR)/hw_layer/serial_over_usb \ + $(PROJECT_DIR)/hw_layer/algo \ + $(PROJECT_DIR)/hw_layer/lcd \ + $(PROJECT_DIR)/hw_layer/sensors \ + $(PROJECT_DIR)/hw_layer/mass_storage \ + $(PROJECT_DIR)/hw_layer/stm32f4 \ + $(PROJECT_DIR)/development \ + $(PROJECT_DIR)/development/hw_layer \ + $(PROJECT_DIR)/development/test \ + $(PROJECT_DIR)/controllers \ + $(PROJECT_DIR)/controllers/sensors \ + $(PROJECT_DIR)/controllers/system \ + $(PROJECT_DIR)/controllers/algo \ + $(PROJECT_DIR)/controllers/core \ + $(PROJECT_DIR)/controllers/math \ + $(PROJECT_DIR)/controllers/trigger/decoders \ + $(PROJECT_DIR)/controllers/trigger \ + config + +BUILDDIR=blbuild + +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +MCU = cortex-m4 + +#TRGT = arm-elf- +TRGT = arm-none-eabi- +CC = $(TRGT)gcc +CPPC = $(TRGT)g++ +# Enable loading with g++ only if you need C++ runtime support. +# NOTE: You can use C++ even without C++ support if you are careful. C++ +# runtime support makes code size explode. +LD = $(TRGT)gcc +#LD = $(TRGT)g++ +CP = $(TRGT)objcopy +AS = $(TRGT)gcc -x assembler-with-cpp +AR = $(TRGT)ar +OD = $(TRGT)objdump +SZ = $(TRGT)size +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +# ARM-specific options here +AOPT = + +# THUMB-specific options here +TOPT = -mthumb -DTHUMB + +# Define C warning options here +CWARN = -Wall -Wextra -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = + +# Define ASM defines here +UADEFS = + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = -lm + +# +# End of user defines +############################################################################## + +RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC +include $(RULESPATH)/rules.mk