2
\$\begingroup\$

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?

\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ efficiency is not the main issue when you upgrade the firmware. The data correctness is \$\endgroup\$ – P__J__ May 24 '18 at 11:09
  • \$\begingroup\$ Correct me if I am wrong, I take the binary image, I send it packet by packet until the last part of it. Once i finish, I send I 32 bit CRC of the binary file and I check if its the same as the calculated one in my board? \$\endgroup\$ – Pryda May 24 '18 at 13:59
  • \$\begingroup\$ You can always verify correctness by reading back the programmed data. This would also check for flash programming errors, instead of just verifying the communication. I would definitely keep using the ROM bootloader, because it will remain available even if you somehow accidentally erase the whole flash. \$\endgroup\$ – jpa May 24 '18 at 15:13
  • 2
    \$\begingroup\$ @Pryda: I think it's better to embed a checksum right into the uploaded image itself. That way correctness of the image can always be verified, not just at the time the bootloader is communicating with the host. \$\endgroup\$ – Olin Lathrop May 24 '18 at 15:33
  • \$\begingroup\$ Olaf. i usually implement the double check. The image checksum is a part of the image. The transmission checksum is something on top of it. Usually (actually always nowadays) I encrypt the image as well. \$\endgroup\$ – P__J__ May 24 '18 at 19:33
5
\$\begingroup\$

You want to write your own bootloader but you cite the app note for the built in one. Forget this one.

Write the bootloader and read only the Reference Manual. Forget the built in bootlader and its "commands"

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.