# Help with firmware bootloader on UAVCAN

7 posts / 0 new
jmachuca77
Offline
Last seen: 1 year 2 months ago
Joined: 2020-09-03 21:24
Posts: 10
Help with firmware bootloader on UAVCAN

Hi, I am trying to extend the UAVCAN drivers to be able to update the firmware through UAVCAN. However I do not uderstand how the bootloader process works. I see in the file commands.c several functions that I think are relevant but I dont know the order in which they are called, for example:

COMM_JUMP_TO_BOOTLOADER_ALL_CAN (I suppose after the application has been recived this is called)

COMM_ERASE_NEW_APP_ALL_CAN (probably called before the hosts sends the application?)

COMM_WRITE_NEW_APP_DATA_ALL_CAN (used to send the app data to the other CAN node ESC??)

If someone could quickly explain how the flashing process works that would be a great help towards supporting flashing via UAVCAN. Thanks.

benjamin
Offline
Last seen: 1 week 2 days ago
Joined: 2016-12-26 15:20
Posts: 487

The flash memory is structured as follows:

== Vector Table ==

== Parameter Backup ==

== Main Program ==

== Reserved space ==

The flashing process with the bootloader is mostly handled from the main program, and it looks as follows:

1. Erase the reserved space

2. Upload a new main program to the reserved space chunk by chunk

- The first 4 bytes must be set to the size of the new main program

- The next 2 bytes are a CRC-checksum of the new main program

The bootloader will then calculate the crc of the new program, compare it to the checksum that has been written and if they match it will replace the main program with the new one. This way nothing gets bricked even if the upload is aborted in the middle, but about half of the flash memory is reserved to have another copy of the main program.

The main program can also erase and write the bootloader itself in case it is missing or a new version is available. There are also other things that you don't need to support that can probably make it look more confusing, such as simultaneuous firmware uploads over CAN and LZO-compression to make the upload faster. The basic functionality is quite easy to implement. This is how the firmware upload is done from VESC Tool:

https://github.com/vedderb/vesc_tool/blob/master/vescinterface.cpp#L1200

Since you make a new implementation, it is probably best to just use the flash_helper:

https://github.com/vedderb/bldc/blob/master/flash_helper.h

The steps above can be done with just these three functions:

uint16_t flash_helper_erase_new_app(uint32_t new_app_size);
uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len);
void flash_helper_jump_to_bootloader(void);

The new_app_size can be set to 393216 to erase the entire reserved space (although that will be slightly slower than just erasing what you need) and the offset starts at 0 to write to the start of the reserved space.

jmachuca77
Offline
Last seen: 1 year 2 months ago
Joined: 2020-09-03 21:24
Posts: 10

Awesome, thanks for the explanation, I have a semi working version on my branch now. I can get the file data from the host through UAVCAN, but I am still not writing it to the flash. I have a couple of questions... seems that

• The first 4 bytes must be set to the size of the new main program
•  The next 2 bytes are a CRC-checksum of the new main program

These 6 bytes are calculated by the VESC_TOOL? I think in the case of UAVCAN these will probably be calculated some other way... I think the CRC is sent as part of the file transfer protocol so I might be able to extract it from there... and the size I might need to caculate after the transfer completes and then write it to the correct location.

jmachuca77
Offline
Last seen: 1 year 2 months ago
Joined: 2020-09-03 21:24
Posts: 10

Ok, I got the bootloader working through UAVCAN, however, currently the code is not being CRC checked instead the CRC is created after the file is received by the ESC and also the size and they are calculated and inserted in the first 6 bytes. The UAVCAN tools just push out the bin file to the clients, they cannot add the CRC or size at the begining so I think we need a took that inserts that into the BIN file if we really want to check the integrity of the file.
My test setup, I have an ardupilot compatible flight controller as an SLCAN device to talk to the CAN bus from mission planner. Mission Planner has an upload tool for UAVCAN so I can select the bin file from there and push it to the ESC directly.

My branch is here:
https://github.com/jmachuca77/bldc/tree/uavcan_upd

I'll make a pull request once I clean it up.

jmachuca77
Offline
Last seen: 1 year 2 months ago
Joined: 2020-09-03 21:24
Posts: 10

Pull request is up, its against the 5.03 branch.

https://github.com/vedderb/bldc/pull/269

benjamin
Offline
Last seen: 1 week 2 days ago
Joined: 2016-12-26 15:20
Posts: 487

Looks good, thanks for the contribution!

How likely is it to drop packets during the firmware update? I think that the CAN CRC handles corruption quite well, but if a chunk goes missing the firmware CRC and size will still be correct, which will brick the hardware.

One note in case you are wondering: writing the same thing to the same place on flash twice without erasing in between is no problem. An erase will set all bits, and write can only clear bits that are set. So writing the same thing twice will not change anything, as it only attempts to clear bits that are already cleared.

Making a tool that appends a CRC and size to the beginning of the bin-file is easy. Maybe there should be a UAVCAN-parameter for firmware updates that sets whether the size and CRC is expected, and only calculates it in the firmware and offsets the file if that parameter is cleared. That would make firmware updates much less likely to brick anything, but requires this extra tool. If it helps I can add a developer menu entry to VESC Tool that can open a bin-file, append a size and CRC and then save it. That tool could also be a command line option to VESC Tool, which just does the conversion without opening the GUI. Then it could be used from the Makefile.

jmachuca77
Offline
Last seen: 1 year 2 months ago
Joined: 2020-09-03 21:24
Posts: 10

It is definitely a concern, it can be bricked because the calculation is done on what we receive. That was meant to be used temporarily. I think the best would be to have a tool create a special version of the bin with the crc and size inserted as you propose. Then I would not calculate it onboard. I can add the parameter to control if its calculated or not and submit a new pull request.