[En-Nut-Discussion] Robust Ethernet bootloader

Philipp Burch phip at hb9etc.ch
Tue Jul 10 11:35:18 CEST 2018


Hi everyone,

I've now implemented a bootloader for the TIVA microcontroller. It's an
implementation from scratch, this seemed to be less work than trying to
adapt some existing solution... The bootloader exposes a simple
UDP-based interface to control it. It grew a bit larger than I initially
expected, the binary amounts to approx. 27kB now, so that the
application image can start at an offset of 0x8000 (32768 bytes).
When the MCU starts, the bootloader first configures the Ethernet
interface and then broadcasts an advertisement packet. It then waits for
a short time for a response and if nothing follows, it tries to boot the
application. In case this fails, the MCU resets and the bootloader
starts over. The application image is checked for sanity by examining
the first two words (the initial SP must point to RAM and the initial PC
to flash) and a CRC over the full image to check if it is valid.

A Python script is used to listen for the advertising packet and then
download and boot the new image.

You can find all the code in

https://hb9etc.ch/hg/tiva_ethloader/

mcu/ contains the bootloader code itself that should go to the MCU.
pc/ contains the Python frontend.
sample_app/ contains a simple application that can be flashed using the
bootloader to test it.

When compiling the application, it is required to tell the linker to
place all code after the bootloader. This can be done by slightly
modifying the linker file:

MEMORY
{
    FLASH0 (rx) : ORIGIN = DEFINED(bootloader_offset) ?
bootloader_offset : 0, LENGTH = 1024K - (DEFINED(bootloader_offset) ?
bootloader_offset : 0)
    SRAM0 (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
}

The application Makefile should then appropriately define the
bootloader_offset symbol for compiler and linker:

# Add the bootloader information to move the application image further back.
ifdef USE_BOOTLOADER
	CFLAGS += -DBOOTLOADER_OFFSET=0x8000
	LDFLAGS += -Wl,--defsym=bootloader_offset=0x8000
endif


Possible future improvements:

- Update interface_init() to wait for a link to be established (with a
timeout) instead of waiting for a fixed delay. See my other thread
concerning the detection of link establishment.

- Add the required code to Ethernut, so that the bootloader does not
need to use MCU-specific stuff but can be converted to a pure Ethernut
application. It currently uses the following unabstracted MCU features:
Flash writing (FLASH peripheral), internal EEPROM to store the
application image size and CRC (EEPROM peripheral), hardware CRC
calculator (CCM0 peripheral, could easily be replaced by a
zlib-compatible software implementation in pure C) and the watchdog
(WATCHDOG1 peripheral). Additionally, there is a short block of inline
assembler to actually boot the application image in
mcu_boot_application() that is specific to ARM Cortex-M cores.

- Add security features like encryption, authentication and signed
images; required if such a device is connected to an untrusted network.


Feel free to use the bootloader for your own projects. In case anyone
feels like improving it, just let me know :)

Many thanks especially to Uwe for his support!

Best regards,
Philipp


More information about the En-Nut-Discussion mailing list