Leaving the bootloader from an IRQ (eg USB or I2C IRQ) will not work if
MBOOT_LEAVE_BOOTLOADER_VIA_RESET is disabled, ie if mboot jumps directly to
the application. This is because the CPU will still be in IRQ state when
the application starts and IRQs of lower priority will be blocked.
Fix this by setting a flag when the bootloader should finish, and exit the
bootloader always from the main (top level) thread.
This also improves the USB behaviour of mboot: it no longer abruptly
disconnects when the manifest command is sent.
Signed-off-by: Damien George <damien@micropython.org>
A board can now customise mboot with:
- MBOOT_LED1, MBOOT_LED2, MBOOT_LED3, MBOOT_LED4: if it needs to have
different LEDs for mboot compared to the application
- MBOOT_BOARD_LED_INIT: if it needs a fully customised LED init function
- MBOOT_BOARD_LED_STATE: if it needs a fully customised LED state-setting
function
- MBOOT_BOARD_GET_RESET_MODE: if it needs a fully customised function to
get the reset mode
With full customisation, the only requirement is a single LED to show the
status of the bootloader (idle, erasing, flashing, etc), which can be
configured to do nothing if needed.
Signed-off-by: Damien George <damien@micropython.org>
It is enabled by default to get the standard behaviour of doing a reset
after it is finished, but can be disabled by a board to jump straight to
the application (likely the board needs to use MBOOT_BOARD_CLEANUP to make
this work).
The application is passed a reset mode of BOARDCTRL_RESET_MODE_BOOTLOADER
if the bootloader was active and entered via a jump.
Signed-off-by: Damien George <damien@micropython.org>
A board can now define MBOOT_TEXT0_ADDR to place mboot at a location other
than 0x08000000. This can be useful if, for example, there is already a
different bootloader on the device.
Signed-off-by: Damien George <damien@micropython.org>
A board can now define MBOOT_LD_FILES (at the Makefile-level) to specify
custom linker scripts. And stm32_generic.ld has been split into 2 pieces
so one or the other can be reused (usually stm32_sections.ld wolud be
reused by a board, and stm32_memory.ld redefined).
Signed-off-by: Damien George <damien@micropython.org>
A board can now use BUILDING_MBOOT at the Makefile-level to do things
conditional on building mboot, for example add source files to SRC_C.
Signed-off-by: Damien George <damien@micropython.org>
And use the same boardctrl.h header for both the application and mboot so
these constants are consistent.
Signed-off-by: Damien George <damien@micropython.org>
So that mboot can be used to program encrypted/signed firmware to regions
of flash that are not the main application, eg that are the filesystem.
Signed-off-by: Damien George <damien@micropython.org>
With mboot encrpytion and fsload enabled, the DEBUG build -O0 compiler
settings result in mboot no longer fitting in the 32k sector. This commit
changes this to -Og which also brings it into line with the regular stm32
build.
Changes are:
- refactor to use new _create_element function
- support extended version of MOUNT element with block size
- support STATUS element
Signed-off-by: Damien George <damien@micropython.org>
This new element takes the form: (ELEM_TYPE_STATUS, 4, <address>). If this
element is present in the mboot command then mboot will store to the given
address the result of the filesystem firmware update process. The address
can for example be an RTC backup register.
Signed-off-by: Damien George <damien@micropython.org>
Instead it is now passed in as an optional parameter to the ELEM_MOUNT
element, with a compile-time configurable default.
Signed-off-by: Damien George <damien@micropython.org>
This commit adds support to stm32's mboot for signe, encrypted and
compressed DFU updates. It is based on inital work done by Andrew Leech.
The feature is enabled by setting MBOOT_ENABLE_PACKING to 1 in the board's
mpconfigboard.mk file, and by providing a header file in the board folder
(usually called mboot_keys.h) with a set of signing and encryption keys
(which can be generated by mboot_pack_dfu.py). The signing and encryption
is provided by libhydrogen. Compression is provided by uzlib. Enabling
packing costs about 3k of flash.
The included mboot_pack_dfu.py script converts a .dfu file to a .pack.dfu
file which can be subsequently deployed to a board with mboot in packing
mode. This .pack.dfu file is created as follows:
- the firmware from the original .dfu is split into chunks (so the
decryption can fit in RAM)
- each chunk is compressed, encrypted, a header added, then signed
- a special final chunk is added with a signature of the entire firmware
- all chunks are concatenated to make the final .pack.dfu file
The .pack.dfu file can be deployed over USB or from the internal filesystem
on the device (if MBOOT_FSLOAD is enabled).
See #5267 and #5309 for additional discussion.
Signed-off-by: Damien George <damien@micropython.org>
Prior to this fix, the final piece of data in a compressed file may have
been lost when decompressing.
Signed-off-by: Damien George <damien@micropython.org>
This is needed to moderate concurrent access to the internal flash, as
while an erase/write is in progress execution will stall on the wireless
core due to the bus being locked.
This implements Figure 10 from AN5289 Rev 3.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Polling mode will cause failures with the mass-erase command due to USB
timeouts, because the USB IRQs are not being serviced. Swiching from
polling to IRQ mode fixes this because the USB IRQs can be serviced between
page erases.
Note that when the flash is being programmed or erased the MCU is halted
and cannot respond to USB IRQs, because mboot runs from flash, as opposed
to the built-in bootloader which is in system ROM. But the maximum delay
in responding to an IRQ is the time taken to erase a single page, about
100ms for large pages, and that is short enough that the USB does not
timeout on the host side.
Recent tests have shown that in the current mboot code IRQ mode is pretty
much the same speed as polling mode (within timing error), code size is
slightly reduced in IRQ mode, and IRQ mode idles at about half of the power
consumption as polling mode.
This is treated more like a "delay before continuing" in the spec and
official tools and does not appear to be really needed. In particular,
downloading firmware is much slower with non-zero timeouts because the host
must pause by the timeout between sending each DFU_GETSTATUS to poll for
download/erase complete.
The implementation internally uses sector erase to wipe everything except
the sector(s) that mboot lives in (by erasing starting from
APPLICATION_ADDR).
The erase command can take some time (eg an STM32F765 with 2MB of flash
takes 8 to 10 seconds). This time is normally enough to make pydfu.py fail
with a timeout. The DFU standard includes a mechanism for the DFU device
to request a longer timeout as part of the get-status response just before
starting an operation. This timeout functionality has been implemented
here.
By passing through the I2C instance to the application callbacks, the
application can implement multiple I2C slave devices on different
peripherals (eg I2C1 and I2C2).
This commit also adds a proper rw argument to i2c_slave_process_addr_match
for F7/H7/WB MCUs, and enables the i2c_slave_process_tx_end callback.
Mboot is also updated for these changes.
Signed-off-by: Damien George <damien@micropython.org>
Mboot now supports FAT, LFS1 and LFS2 filesystems, to load firmware from.
The filesystem needed by the board must be explicitly enabled by the
configuration variables MBOOT_VFS_FAT, MBOOT_VFS_LFS1 and MBOOT_VFS_LFS2.
Boards that previously used FAT implicitly (with MBOOT_FSLOAD enabled) must
now add the following config to mpconfigboard.h:
#define MBOOT_VFS_FAT (1)
Signed-off-by: Damien George <damien@micropython.org>
This commit factors the code for files and streaming to separate source
files (vfs_fat.c and gzstream.c respectively) and introduces an abstract
gzstream interface to make it easier to plug in different filesystems.
Signed-off-by: Damien George <damien@micropython.org>
There's no need to do a directory listing to search for the given firmware
filename, it just takes extra time and code size. Instead this commit
changes it so that the requested firmware file is opened immediately and
will abort if the file couldn't be opened. This also allows to specify
files in a directory.
Signed-off-by: Damien George <damien@micropython.org>
Commit 8675858465 switched to using the CMSIS
provided SystemInit function which sets VTOR to 0x00000000 (previously it
was 0x08000000). A VTOR of 0x00000000 will be correct on some MCUs but not
on others where the built-in bootloader is remapped to this address, via
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH().
To make sure mboot has the correct vector table, this commit explicitly
sets VTOR to the correct value of 0x08000000.
Signed-off-by: Damien George <damien@micropython.org>
There's no need to duplicate this functionality in mboot, the code provided
in stm32lib/CMSIS does the same thing and makes it easier to support other
MCU series.
Signed-off-by: Damien George <damien@micropython.org>
The flash functions in ports/stm32/flash.c are almost identical to those in
ports/stm32/mboot/main.c, so remove the duplicated code in mboot and use
instead the main stm32 code. This also allows supporting other MCU series.
Signed-off-by: Damien George <damien@micropython.org>
In mboot, the ability to override the USB vendor/product id's was added
back in 5688c9ba09. However, when the main
firmware is turned into a DFU file the default VID/PID are used there.
pydfu.py doesn't care about this but dfu-util does and prevents its use
when the VID/PID don't match.
This commit exposes BOOTLOADER_DFU_USB_VID/PID as make variables, for use
on either command line or mpconfigboard.mk, to set VID/PID in both mboot
and DFU files.
Add -Wdouble-promotion and -Wfloat-conversion for most ports to ban out
implicit floating point conversions, and add extra Travis builds using
MICROPY_FLOAT_IMPL_FLOAT to uncover warnings which weren't found
previously. For the unix port -Wsign-comparison is added as well but only
there since only clang supports this but gcc doesn't.
The "led" argument is always a pointer to the GPIO port, or'd with the pin
that the LED is on, so testing that it is "1" is unnecessary. The type of
"led" is also changed to uint32_t so it can properly hold a 32-bit pointer.
Updating the LED0 state from systick handler ensures LED0 is always
consistent with its flash rate regardless of other processing going on in
either interrupts or main. This improves the visible stability of the
bootloader, rather than LED0 flashing somewhat randomly at times.
This commit also changes the LED0 flash rate depending on the current state
of DFU, giving slightly more visual feedback on what the device is doing.