Electronic – Upgrade user application using custom bootloader via UART (STM32)

bootloaderembeddedmicrocontrollerserialstm32

I'm using an STM32L4 board and my flash memory looks like this:

|______________
|
| USER application
|
|
|______________
|Vector table(UA)
|______________ 0x8000 – 8000
|
| Custom Bootloader
|
|
|______________
|Vector table(BL)
|______________ 0x8000 – 0000

My board is connected to another board using UART (Let's define the other board as Master and my board as Slave).
Master board shall be able to upgrade the user application of Slave board via UART. The idea is to send a binary file via UART and write it in the user application section.

According to ST's application note, there is a command called Write Memory command:

The Write Memory command is used to write data to any valid memory address (see note below) i.e. RAM, Flash memory, option byte area
When the bootloader receives the Write Memory command, it transmits
the ACK byte to the application. After the transmission of the ACK
byte, the bootloader waits for an address (4 bytes, byte 1 is the
address MSB and byte 4 is the LSB) and a checksum byte, it then checks
the received address. For the Option byte area, the start address must
be the base address of the Option byte area (see note) to avoid
writing inopportunely in this area.

if the received address is valid and the checksum is correct, the
bootloader transmits an ACK byte, otherwise it transmits a NACK byte
and aborts the command. When the address is valid and the checksum is
correct, the bootloader:

• gets a byte, N, which contains the number of data bytes to be
received

• receives the user data ((N + 1) bytes) and the checksum (XOR of N
and of all data bytes)

• programs the user data to memory starting from the received address

• at the end of the command, if the write operation was successful,
the bootloader transmits the ACK byte; otherwise it transmits a NACK
byte to the application and aborts the command

• The maximum length of the block to be written for the STM32 is 256 bytes

This means that I can only upgrade 256 bytes by a packet coming from Master board to Slave board.

Now let's say that Master board has an SD card that contains a binary file and I want to flash this file to the user application section. How can I do this? Should read the binary file, and send a series of 256 bytes, each 256 in a packet?

Best Answer

Yes. Obviously you can send multiple packets.

There is a tradeoff between efficiency, and the cost of getting a packet wrong. With small packets, there is more total overhead for the amount of data actually delivered. However, if there is a error, less data will have to be re-sent.

That all said, data errors are, or at least should be, rare. Generally you send maximum-size packets until there is less than a full packet of data left.

Their checksum algorithm is rather a joke, let's say "primitive" at best. Smaller packets have more checksum protection because there are effectively more checksum bits per data bit.

Of course you aren't stuck with this bootloader. You can write one that does whatever you want. See this question for more information on bootloaders in general.

More on verification

As Peter pointed out in a comment, data correctness is essential in a bootloader.

That is a good argument for ditching this bootloader and it's ridiculously naïve checksum algorithm. What I usually do is not even attempt to checksum individual packets. I design the protocol for reasonable efficiency, but add a good checksum to the whole image.

Communicating the data from the host to the device is only one part of the problem. It then has to be written correctly to the non-volatile memory. That's actually much more likely to fail. A power glitch, or the user hitting the reset button at a bad time can cause corruption, for example.

My strategy is generally not to worry about the possible errors in individual steps of the process, but to verify the final result. I usually put something like a 24 or 32 bit CRC checksum at the end of the uploaded image. Before the bootloader runs the main app, it verifies the checksum. If it fails, it requests a new image, runs the previous image, signals error, or something. Never ever run a corrupted image.

From a comment:

The binary file contains a Firmware (some .c and .h and libraries generated with an embedded IDE like Keil) .. How to add this checksum to the image itself? Is it safe to modify such a file?

No, the binary file doesn't contain any .c and .h files. It's a binary file. You need to step back and learn what the compiler, librarian, and linker each do, and what kind of information is in the various file types. You can't go about developing code where you're close to the hardware without understanding these things.

Adding the checksum to the binary file (often in Intel Hex format) is one way to add a checksum to the image. You could write a separate tool that runs after the linker. This tool reads the image, computes the checksum, and embeds it back into the image at a known place.

Another way is to have the uploader program add the checksum on the fly. The uploader reads the unmodified binary file, and adds the checksum at the known locations, usually the last few bytes of the image. This modified image is then sent to the bootloader, but the binary file is never altered.