kopia lustrzana https://github.com/stlink-org/stlink
54 wiersze
3.7 KiB
Markdown
54 wiersze
3.7 KiB
Markdown
# Flashloaders
|
|
|
|
## What do flashloaders do
|
|
|
|
The on-chip FLASH of STM32 needs to be written once a byte/half word/word/double word, which would lead to a unbearably long flashing time if the process is solely done by `stlink` from the host side. Flashloaders are introduced to cooperate with `stlink` so that the flashing process is divided into two stages. In the first stage, `stlink` loads flashloaders and flash data to SRAM where busy check is not applied. In the second stage, flashloaders are kick-started, writing data from SRAM to FLASH, where a busy check is applied. Thus the write-check\_if\_busy cycle of flashing is done solely by STM32 chip, which saves considerable time in communications between `stlink` and STM32.
|
|
|
|
As SRAM is usually less in size than FLASH, `stlink` only flashes one page (may be less if SRAM is insufficient) at a time. The whole flashing process may consist of server launches of flashloaders.
|
|
|
|
## The flashing process
|
|
|
|
1. `st-flash` loads compiled binary of corresponding flashloader to SRAM by calling `stlink_flash_loader_init` in `src/flash_loader.c`
|
|
2. `st-flash` erases corresponding flash page by calling `stlink_erase_flash_page` in `common.c`.
|
|
3. `st-flash` calls `stlink_flash_loader_run` in `flash_loader.c`. In this function
|
|
+ buffer of one flash page is written to SRAM following the flashloader
|
|
+ the buffer start address (in SRAM) is written to register `r0`
|
|
+ the target start address (in FLASH, page aligned) is written to register `r1`
|
|
+ the buffer size is written to register `r2`
|
|
+ the start address (for now 0x20000000) of flash loader is written to `r15` (`pc`)
|
|
+ After that, launching the flashloader and waiting for a halted core (triggered by our flashloader) and confirming that flashing is completed with a zeroed `r2`
|
|
4. flashloader part: much like a `memcpy` with busy check
|
|
+ copy a single unit of data from SRAM to FLASH
|
|
+ (for most devices) wait until flash is not busy
|
|
+ trigger a breakpoint which halts the core when finished
|
|
|
|
## Constraints
|
|
|
|
Thus for developers who want to modify flashloaders, the following constraints should be satisfied.
|
|
|
|
* only thumb-1 (for stm32f0 etc) or (thumb-1 and thumb-2) (for stm32f1 etc) instructions can be used, no ARM instructions.
|
|
* no stack, since it may overwrite buffer data.
|
|
* for most devices, after writing a single unit data, wait until FLASH is not busy.
|
|
* for some devices, check if there are any errors during flashing process.
|
|
* respect unit size of a single copy.
|
|
* after flashing, trigger a breakpint to halt the core.
|
|
* a sucessful run ends with `r2` set to zero when halted.
|
|
* be sure that flashloaders are at least be capable of running at 0x20000000 (the base address of SRAM)
|
|
|
|
|
|
For devices that need to wait until the flash is not busy, check FLASH_SR_BUSY bit. For devices that need to check if there is any errors during flash, check FLASH\_SR\_(X)ERR where `X` can be any error state
|
|
|
|
FLASH_SR related offset and copy unit size may be found in ST official reference manuals and/or some header files in other open source projects. Clean room document provides some of them.
|
|
|
|
|
|
## Debug tricks
|
|
|
|
If you find some flashloaders to be broken or you need to write a new flashloader for new devices, the following tricks may help.
|
|
|
|
1. Modify `WAIT_ROUNDS` marco to a bigger value so that you will have time to kill st-flash when it is waiting for a halted core.
|
|
2. run `st-flash` and kill it after the flashloader is loaded to SRAM
|
|
3. launch `st-util` and `gdb`/`lldb`
|
|
4. set a breakpoint at the base address of SRAM
|
|
5. jump to the base address and start your debug
|
|
|
|
The tricks work because by this means, most work (flash unlock, flash erase, load flashloader to SRAM) would have been done automatically, saving time to construct a debug environment. |