Firmware upgrade using IOT device
This document describes how to perform a firmware upgrade using CAN and siliXcon’s SRM (server with firmware repository) for an external developer. It should be regarded as a simple guide allowing to embed the upgrade process into another system. The document doesn’t aim to describe the entire proprietary service protocol, just the selected parts that are necessary for the upgrade process.
All the data in the CAN messages are encoded in little endian - INTEL format
Please ensure that the CAN bus and CAN timing are correctly set. Please do not mix CANH and CANL wires and ensure that the bus is properly terminated with a 120Ohm resistor. All CAN IDs described below are 11 bits.
The firmware size is around 250kb.
Legend
- Host: the 3RD party system (to implement the upgrade process). Have address 7.
- Device: A siliXcon product (display, device, BMS)
- DNC: Do Not Care. This information can have an arbitrary value with no significance for the host.
- SRM: Secure Remote Management (siliXcon’s server with firmware repository)
- Service: a device‘s internal communication object with an independent context. (BL, ID, PWR)
Establishing dialog with the bootloader
First of all, the host needs to put the device into bootloader mode. This is done by resetting the device and sending the SELECT command, as described below.
1. Reset the device
Reset the device using the PWR/reboot command. This command will instruct all devices (or another siliXcon products on the CAN-bus) to reboot. It is necessary to reboot the device in order to establish communication with the bootloader.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
PWR / Reboot | Host -> Device | 0 | 1 |
Payload:
Byte 0 |
---|
Target address |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
2. Wait for the ATR
Wait for the ATR (answer to reset). As a response to the REBOOT, the device sends a message called ATR (answer to reset). The host shall wait for this message to ensure the reset took place. If the ATR does not arrive (within a timeout of ~500ms), the host can attempt to reset the device once again. The first 3 bytes must contain the value specified in the table, all other bytes shall not be parsed. At most 3 attempts are recommended, before a failure shall be considered.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / ATR response | Device -> Host | 8*4 + device address Usually 32 (device address 0) | 8 |
Payload:
Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
---|---|---|---|---|---|---|---|
0xFF (0x07 for Boootloader version older than 2022) | 0x40 | 0x00 | DNC | DNC | DNC | DNC | DNC |
Host address (broadcast) | RESET | RESPONSE indication | Reset reason |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
3. Do a handshake by issuing the SELECT command.
The bootloader waits for about ~200ms after the ATR is sent, for the SELECT command. If the SELECT command is not received, the bootloader passes control to the main application.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / SELECT | Host -> Device | 8*4 + host address (7 is used as host address) Usually 39 (host with address 7) | 4 |
Payload:
Byte 0 | Byte 1 | Byte 2 | Byte 3 |
---|---|---|---|
0x00 | 0x02 | 0x00 | Session ID (DNC) |
Device address | SELECT command | Device address repeated | X (device increments the X value with each new host‘s command) |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
4. Wait for the SELECT response
Wait for the SELECT response. The bootloader sends this message as a confirmation of successful selection (hand shaken back). If the host doesn’t receive the SELECT response or, the first three bytes contain other than specified values, the host can attempt to send the SELECT command again. At most 3 attempts are recommended, before a failure shall be considered.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / SELECT response | Device -> Host | 8*4 + device address Usually 32 (device address 0) | 3 |
Payload:
| Byte 0 | Byte 1 | Byte 2 | | ------------ | ------ | ------------------- | ----------------------- | | 0x00 | 0x42 | 0x00 | | Host address | SELECT | RESPONSE indication | Device address repeated |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
Retrieving the identifiers
At this step, we assume that the communication with the bootloader was established up to the point where the SELECT response was successfully received.
Get device IDINFO
1. Request device IDINFO
Ask for the device’s IDINFO using the GETINFO command of the ID service. Now, the host shall issue the GETINFO command if the ID service retrieves the IDINFO. IDINFO is a set of string identifiers that the host must afterward send to the online SRM service.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO | Host -> Device | 8*3 + host address (7 is used as host address) Usually 31 (host with address 7) | 3 |
Payload:
Byte 0 | Byte 1 | Byte 2 |
---|---|---|
0x00 | 0x01 | 0x00 |
Device address | GETINFO command | - |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
2. Receive IDINFO
Receive IDINFO data from the device. The device will respond with a series of messages to the GETINFO command. The host shall receive all these messages, collect the DATA in an input buffer and once transmission is finished, it should compute the CRC8 and check it against the CRC received in the footer message.
The IDINFO header message indicates the transfer start, contains the number of bytes the device will consequently send (dlen) and is transmitted once.
- CAN
- UART
Header message:
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO response | Device -> Host | 8*3 + device address Usually 24 (device address 0) | 8 |
Byte 0 | Byte 1 | Byte 2 | Byte 3 - 6 | Byte 7 |
---|---|---|---|---|
0x07 | 0x41 | 0x10 = success | Dlen LSB - Dlen MSB | Session ID (DNC) |
Host address | GETINFO / RESPONSE indication | Command result | Number of bytes to be transferred, UINT32_T (encoded in little endian) | X (device increments the X value with each new host‘s command) |
Data message
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO response data | Device -> Host | 8*3 + device address Usually 24 (device address 0) | Max(8, remaining bytes to be transferred) |
Byte 0 | Byte 1 | Byte 2 - 7 |
---|---|---|
0x07 | 0x71 | Payload |
Host address | GETINFO / DATA indication | The payload (1 – 6 bytes per single message). |
Footer message
The IDINFO footer message is transmitted at the end. It contains the 8-bit CRC of the transferred data. The CRC is computed from the entire data using the attached C-code. If there is a CRC mismatch, not all data were received or either the footer or header message is missing, the host can retry the transaction (by issuing the GETINFO command again).
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO response footer | Device -> Host | 8*3 + device address Usually 24 (device address 0) | 5 |
Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
---|---|---|---|---|
0x07 | 0x51 | 0x00 | CRC | Session ID (DNC) |
Host address | GETINFO / CMDPART1 footer indication | The data payload (1 – 6 bytes per single message). | The host should compute the CRC8 of the received data chunk and compare it against this value. | X (device increments the X value with each new host‘s command) |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
3. Request device BLINFO
Ask for the device’s BLINFO using the GETINFO command of the BL service. Now, the host shall issue the GETINFO command of the BL service to retrieve the BLINFO. BLINFO is another set of string identifiers that the host must afterward send to the online SRM.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / GETINFO | Host -> Device | 8*4 + host address (7 is used as host address) Usually 39 (host with address 7) | 3 |
Payload:
Byte 0 | Byte 1 | Byte 2 |
---|---|---|
0x00 | 0x03 | 0x00 |
Device address | BL GETINFO command | DNC |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
4. Receive BLINFO
Receive BLINFO data from the device. The device will respond with a series of messages to the GETINFO command. The host shall receive all these messages, collect the DATA in an input buffer and once transmission is finished, it should compute the CRC8 and check it against the CRC received in the footer message. Semantics is described below:
The BLINFO header message indicates the transfer start, contains the number of bytes the device will consequently send (dlen) and is transmitted once.
- CAN
- UART
Header message:
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO response | Device -> Host | 8*4 + device address Usually 32 (device address 0) | 8 |
Byte 0 | Byte 1 | Byte 2 | Byte 3 - Byte 6 | Byte 7 |
---|---|---|---|---|
0x07 | 0x43 | 0x10 = success | Dlen LSB - Dlen MSB | Session ID (DNC) |
Host address | GETINFO / RESPONSE indication | Command result | Number of bytes to be transferred, UINT32_T (encoded in little endian) | X (device increments the X value with each new host‘s command) |
Data message
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO response data | Device -> Host | 8*4 + device address Usually 32 (device address 0) | Max(8, remaining bytes to be transferred) |
Byte 0 | Byte 1 | Byte 2 - 7 |
---|---|---|
0x07 | 0x73 | Payload |
Host address | GETINFO / DATA indication | The payload (1 – 6 bytes per single message). |
Footer message
The BLINFO footer message is transmitted at the end. It contains the 8-bit CRC of the transferred data. The CRC is computed from the entire data using the attached C-code. If there is a CRC mismatch, not all data were received or either the footer or header message is missing, the host can retry the transaction (by issuing the GETINFO command again).
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
ID / GETINFO response footer | Device -> Host | 8*4 + device address Usually 32 (device address 0) | 5 |
Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
---|---|---|---|---|
0x07 | 0x53 | 0x00 | CRC | Session ID (DNC) |
Host address | GETINFO / CMDPART1 footer indication | The data payload (1 – 6 bytes per single message). | The host should compute the CRC8 of the received data chunk and compare it against this value. | X (device increments the X value with each new host‘s command) |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
Querying the SRM
As a next step, once the IDINFO and BLINFO are successfully obtained, the host shall invoke the SRM with an UPGRADE query. The SRM is an online querying service that can be used (apart from other functionality) to retrieve the firmware upgrades. SRM listens on port 443 of the https://srm.silixcon.com.
SRM can be queried using HTTP(s) GET of the file /srm-update.php. The data are expected as standard, php-style arguments (separated with ? and &).
Argument | Encoding | Content |
---|---|---|
-i | Hex16 | IDINFO - as receiver from the device |
-b | Hex16 | BLINFO - as received from the device |
-o | Hex16 | QUERY string. By using „UPGRADE“, SRM will automatically select and send the latest compatible firmware. |
IDINFO and BLINFO data encoded in hex16, QUERY string set to „UPGRADE“ (in uppercase)
GET http://srm.silixcon.com/srm-update.php?&i=3141343100657363332D736C31675F3438657861313036302D34303000534C6B616C6B00456D424C204D61722032392032303231003230333833373332353433343537303930303339303032320030433A534C00&b=314134380034313046433234310038303030003430303030003130303000374144363442313900323938343000564543544F525F63616B652D756E69765F67656E657269632076312E3761204D6172203131203230323100&o=55504752414445
Approximatelly from the new year 2025, the SRM endpoint will be changed. If you are using or implementing this protocol, please contact us and we will keep you informed about the changes in advance.
Response:
&res=X
Where X is a numerical value containing the result of the issued query. The host can parse the res value and convert the query result to text according to the following table:
Res value | Meaning |
---|---|
0 | success |
4 | entry does not exist in the database |
6 | could not locate the release |
other | unknown / server access error |
If the res ends with 0 (success), the file follows with
&load=0123456789ABCDEF…
**Where the data is the payload to be flashed to the device. **
Flashing the received payload to the device
2. Send LOAD command
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL/LOAD | Host -> Device | 8*4 + host address (7) Usually 39 | 8 |
Payload
Byte 0 | Byte 1 | Byte 2 - 5 | Byte 6-7 |
---|---|---|---|
0x00 | 0x0E | UINT32_T Litte endian | 0x015C |
Device address | Load | Total lenght | Crypto ID |
Response:
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / LOAD | Device -> host | 8*4 + host address (0 is used as host address) Usually 31 (host with address 7) | 7 |
Payload:
Byte 0 | Byte 1 | Byte 2 | Byte 3 - 7 |
---|---|---|---|
0x00 | 0x4E | 0x10 = success | Chunk size |
Host address | BL/LOAD response | Command result | UINT32_T Litte endian |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
2.1 Send the firmware payload - SLOW method
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / LOAD | Host -> Device | 8*4 + host address (7 is used as host address) Usually 39 (host with address 7) | 8, or remaining bytes to be transferred |
Payload:
Byte 0 | Byte 1 | Byte 2--7 |
---|---|---|
0x00 | 0x3E | Total lenght of the payload |
Device address | BL/LOAD DATA indication | Payload 0 - 5 |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
2.2 Send the firmware payload - FAST method
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / LOAD | Host -> Device | 8*5 + host address (7 is used as host address) Usually 47 (host with address 7) | 8, or remaining bytes to be transferred |
Payload:
Byte 0 - 7 |
---|
Payload 0 - Payload 7 |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
2.3 Send the firmware payload - footer
- CAN
- UART
Footer messge:
The LOAD footer message is transmitted at the end of the chunk. It contains the 8-bit CRC of the transferred data. The CRC is computed from the entire data. If there is a CRC mismatch, not all data were received or either the footer or header message is missing, the host can retry to retransmit the data chunk.
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / LOAD | Host -> Device | 8*4 + host address (7 is used as host address) Usually 39 (host with address 7) | 3 |
Payload:
Byte 0 | Byte 1 | Byte 2 |
---|---|---|
0x00 | 0x2E | CRC8 |
Device address | BL/LOAD DATA footer indication | CRC of the transfered chunk |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
2.4 Receive ack
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / LOAD | Device -> host | 8*4 + host address (0 is used as host address) Usually 32 (host with address 0) | 8 |
Payload:
Byte 0 | Byte 1 | Byte 2 | Byte 3 - 6 | Byte 7 |
---|---|---|---|---|
0x07 | 0x4E | 0x10 - send next chunk 0x00 - done other - error | Next chunk size | Session ID |
Host address | BL/LOAD response | Command result | UINT32_T Litte endian | X |
Exit bootloader
A Last step is necessary to exit the bootloader and enter the main program. To perform this step run command needs to be sent. After this, the device should be updated and prepared to work
If the upgrade process is interrupted, or the internal CRC check of the whole FW is incorrect, the device stays in bootloader mode. In this case, it is necessary to repeat the whole process again.
- CAN
- UART
Service / Command | Direction | CAN ID | DLC |
---|---|---|---|
BL / RUN | Host -> Device | 8*4 + host address (7 is used as host address) Usually 39 (host with address 7) | 2 |
Payload:
Byte 0 | Byte 1 |
---|---|
0xFF | 0x01 |
Device address (broadcast) | RUN command |
Device upgrade is possible over all its interfaces, but it needs to be documented first. :-/
Appendix
CRC8 computation
The CRC8 is computed using the following C-code:
static const uint8_t crc8_table[256] = {0x0, 0x7, 0xE, 0x9, 0x1C, 0x1B,
0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E,
0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4,
0xC3, 0xCA, 0xCD, 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF,
0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5,
0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE,
0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 0x27,
0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04,
0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61,
0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0xF9, 0xFE, 0xF7, 0xF0, 0xE5,
0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E,
0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43,
0x44, 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28,
0x3D, 0x3A, 0x33, 0x34, 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76,
0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25,
0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0,
0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA,
0xFD, 0xF4, 0xF3
};
uint8_t
crc8(const uint8_t* ptr, int32_t len)
{
uint8_t crc = 0;
len++;
while (--len)
crc = crc8_table[crc ^ *ptr++];
return crc;
}
ACK and Commands results
The result is bitwise, i.e. there can be multiple results at once.
Name | Value | Description |
---|---|---|
TCP_STE_DONE | 0x00 | |
TCP_ERR_GENERIC | 0x08 | |
TCP_ERR_WRONG_NBYTES | 0x09 | |
TCP_ERR_NO_TRANSFER | 0x0A | |
TCP_ERR_CRC | 0x0B | |
TCP_ERR_CHUNK | 0x0C | |
TCP_ERR_ARB_LOST | 0x0D | |
TCP_ERR_SIZE | 0x0E | |
TCP_ERR_UNSUPPORT | 0x0F | |
TCP_STE_PENDING | 0x10 | |
TCP_STE_EXPEDITED | 0x80 |