A little bit of background

Fore one of my last projects I faced a problem that sounds seemingly simple at first, but as its turd out, as always it wast that simple.
The vehicle tracker I build for my Surron had manny requirements, and one of them was that it needed to be somewhat water and dust-proof.

Sounds simple at first, doesn’t it ?

Turn out for achieving this goal I needed to make the case really sturdy and well sealed. You might ask why this matters ? When the case is closed it’s not that esy to reprogram the Esp32 that’s hiding inside, and in turn not that easy to make changes to the way Can Messages form the bike are interpreted and parsed.
But to my luck I already had a well sealed connector that’s ready to connect.

So you might think that’s as easy as routing RX and TX to the connector and upload binary’s via the build in Bootloader.

Well sadly all except of one pin were allocated with power ignition readout and CanBus.

So the idea was born if it was possible to upload binary’s via the CanBus. So i died a little bit of googling, and to my surprise I couldn’t find a single implementation of this being done.

So I figured it was my turn to implement this.

Basics of the architecture

The architecture is fortunately pretty simple.
The Esp32 has a callback function that gets called each time a Can Message with the corresponding ID is received. The frame then gets turned into a so-called “Command Message”, that can contain one of following Commands:

LIST_DEVICES

All devices on the network that support the upload protocol shall answer with their ID.

FLASH_BEGIN

Indicates that a binary will follow and the target should prepare itself.

FLASH_DATA

Sends a block of max 5 bytes of the binary.

FLASH_END

Upload is finished and binary should be compared to the contained checksum.


If you want to understand this in more detail i recommend that you look at the implementation yourself ^^

Host tool

Because just the MCU implementation itself is not able to grab the binary out of thin air, it needs a Host that’s a ble to provide it.

Implementation can be found here


When you try my implementation, be warned that it requires a Kvaser CanBus interface to function properly.

Calling ot is just that simple as specifying the wanted interface and binary, and you can watch the progress bar fill.

./OTA_CLI.exe -i 0 -b "./firmware.bin"

If you have selected an interface that does not exist, you see the following error message:

What’s still open

Currently, I haven’t implemented following things due to time constrains:

  • Targeting via ID
  • validating CRC
  • OTA fetching form gitlab
  • device discovery in a network

This thing will all follow in a future release :)