Firmware update and file transfers¶
MiraOS comes with support for a method of distributing binary files to all nodes in a network. This method is intended for performing firmware updates over the air (FOTA), but can also be used for other purposes.
Transfer method¶
Figure 1: A file transfer throughout the network
A file is transferred hop by hop along the routing tree. It starts by the first node (root node) having the new file in its file swap storage. Its children download the file when they detect that there is a new version. This process continues throughout the network.
Update of Firmware¶
The transfer method allows for arbitrary binary files. It's the responsibility of the application to use this file in the correct way. The developer should take aspects of for example file integrity into consideration when designing the firmware file format.
It is the developer's responsibility to build their bootloader to have support for updating firmware.
Using the supported transfer method is optional, alternate methods may be used if the developer finds that more suitable for the application.
Types¶
Name | Type | Description |
---|---|---|
mira_fota_done_callback_t |
void(* )(void *storage) |
Callback to indicate result is finished. |
mira_fota_cb_init_t |
void(* )(void) |
FOTA driver callback, to initialize driver. Called to initialize FOTA driver |
mira_fota_cb_get_size_t |
int(* )(uint16_t slot_id, uint32_t *size, mira_fota_done_callback_t done_callback, void *storage) |
FOTA driver callback, to get the size of a slot. Called to get the available size for a given slot. Note that this is the size of the slot, not the size of the data written. On successful operation, call done_callback(storage). The callback does not have to be called within the method itself. However, it: must be called once and only once if the method returns 0 / success must not be called if the method returns an error. If the slot id is not supported, return an error code. 0 on successful request, non-zero if error |
mira_fota_cb_read_t |
int(* )(uint16_t slot_id, void *data, uint32_t address, uint32_t length, mira_fota_done_callback_t done_callback, void *storage) |
FOTA driver callback, to read data. Called when data should be read. Multiple read sessions may occur in parallel, but only one write. On successful operation, call done_callback(storage). The callback does not have to be called within the method itself. However, it: must be called once and only once if the method returns 0 / success must not be called if the method returns an error. If the slot id is not supported, return an error code. 0 on successful request, non-zero if error |
mira_fota_cb_write_t |
int(* )(uint16_t slot_id, const void *data, uint32_t address, uint32_t length, mira_fota_done_callback_t done_callback, void *storage) |
FOTA driver callback, to write data to driver. Called when data should be written. Multiple read sessions may occur in parallel, but only one write. Erase is treated as a write operation. On successful operation, call done_callback(storage). The callback does not have to be called within the method itself. However, it: must be called once and only once if the method returns 0 / success must not be called if the method returns an error. If the slot id is not supported, return an error code. 0 on successful request, non-zero if error |
mira_fota_cb_erase_t |
int(* )(uint16_t slot_id, mira_fota_done_callback_t done_callback, void *storage) |
FOTA driver callback, erase an entire slot. Called to erase the slot. Multiple read sessions may occur in parallel, but only one write. Erase is treated as a write operation. On successful operation, call done_callback(storage). The callback does not have to be called within the method itself. However, it: must be called once and only once if the method returns 0 / success must not be called if the method returns an error. If the slot id is not supported, return an error code. 0 on successful request, non-zero if error |
Functions¶
mira_fota_set_driver¶
mira_status_t mira_fota_set_driver( mira_fota_cb_init_t init, mira_fota_cb_get_size_t get_size, mira_fota_cb_read_t read, mira_fota_cb_write_t write, mira_fota_cb_erase_t erase);
Set FOTA backend driver. Update the driver from the built-in driver, to be able to use external storage.
The driver must implement all functions to work with FOTA.
If a driver is not specified by calling mira_fota_set_driver(...), a default driver which stores the FOTA image on an internal flash on the CPU will be used if available. In that case, only slot_id = 0 will be available. slot_id other than 0 for the mira_fota_*() calls will result in a failure, returning -1.
Each operation is started by FOTA calling the proper callback. The driver must then update the corresponding parameter, and when finished call done_callback(storage).
Note that done_callback(storage) does not need to be called directly from the operation callback implemented by the driver: it may be called later, if the driver implements a process. However, done_callback() must be called once and only once per started operation. The driver itself is responsible for handling timeouts.
Return 0 from each callback to indicate that the operation started without error. Non-zero return value from the callback means that the operation failed to start, and done_callback must not called by the driver.
Multiple operations can be requested in parallel. If only one operation can be executed at the same time, the driver needs to hold a queue of the operations requested.
Parameters
Parameter | Description |
---|---|
init |
Callback for when driver is initialized. |
get_size |
Callback to get size of swap space. |
read |
Callback to start reading from swap space. |
write |
Callback to start writing to swap space. |
erase |
Callback to erase entire swap space, to be clean for new write. |
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
The operation was successful. |
MIRA_ERROR_ALREADY_INITIALIZED |
The FOTA is already initialized. |
mira_fota_init¶
mira_status_t mira_fota_init( void);
Initialize firmware transfer OTA.
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
The operation was successful. |
MIRA_ERROR_ALREADY_INITIALIZED |
The FOTA is already initialized. |
mira_fota_is_valid¶
mira_bool_t mira_fota_is_valid( uint16_t slot_id);
Check if image in firmware is valid. Result is valid both during read operation and outside of read operation.
The result is guaranteed not to change during a read operation (between mira_fota_read_start has finished, and mira_fota_read_end).
Outside read operation, the result might change due to started OTA transfer, and may only be used for statistical purposes.
Parameters
Parameter | Description |
---|---|
slot_id |
Slot number. |
Return
If the image in the FOTA cache is valid.
Value | Description |
---|---|
MIRA_TRUE |
The FOTA is valid. |
MIRA_FALSE |
The FOTA is not valid. |
mira_fota_get_image_size¶
mira_size_t mira_fota_get_image_size( uint16_t slot_id);
Get size of FOTA image in cache. The result is guaranteed not to change during a read operation (between mira_fota_read_start has finished, and mira_fota_read_end).
Outside read operation, the result might change due to started OTA transfer, and may only be used for statistical purposes.
Parameters
Parameter | Description |
---|---|
slot_id |
Slot number. |
Return
0 if the image is not valid, otherwise the size of the image.
mira_fota_get_version¶
uint8_t mira_fota_get_version( uint16_t slot_id);
Get FOTA image version. The result is guaranteed not to change during a read operation (between mira_fota_read_start has finished, and mira_fota_read_end).
The image version is a sequence number for the update session. It is useful for statistics for which nodes have got the image.
The version number is in the range 0-254. 255 means version number is not present.
Parameters
Parameter | Description |
---|---|
slot_id |
Slot number. |
Return
255 if the image is not valid, otherwise the version number.
mira_fota_read_start¶
mira_status_t mira_fota_read_start( uint16_t slot_id);
Start a read session.
During the read session it is possible to use the mira_fota_read()
method.
If the return value is MIRA_SUCCESS, a read session is requested. The read session is first started once mira_fota_is_working()
returns MIRA_FALSE. See mira_fota_is_working()
for more information.
If the returned value is not MIRA_SUCCESS, triggering the request is not successful.
Parameters
Parameter | Description |
---|---|
slot_id |
Slot number. |
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
The read session is successfully requested. |
MIRA_ERROR_ALREADY_INITIALIZED |
Another FOTA session is already active. |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA. |
mira_fota_read¶
mira_status_t mira_fota_read( uint8_t* dst, mira_size_t* dst_length, mira_size_t src, mira_size_t length);
Read from flash cache. Start a read request from the FOTA cache storage.
If the return value is MIRA_SUCCESS, a read operation is requested. The operation is finished when mira_fota_is_working()
returns MIRA_FALSE.
Once the operation is finished, content is available at address of dst, and the size of the written data is available at dst_length.
If the returned value is not MIRA_SUCCESS, triggering the request is not successful.
Parameters
Parameter | Description |
---|---|
dst |
Pointer to where the read data should be stored. |
dst_length |
Pointer to the length of the read. |
src |
Offset in the FOTA cache from where to start the reading. |
length |
Size of block to read. |
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
The read request is successfully requested. |
MIRA_ERROR_NOT_INITIALIZED |
A read session has not been started yet (mira_fota_read_start() ). |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA. |
mira_fota_read_end¶
mira_status_t mira_fota_read_end( void);
Close the read session.
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
The read session was successfully closed. |
MIRA_ERROR_NOT_INITIALIZED |
A read session has not been started yet (mira_fota_read_start() ). |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA. |
mira_fota_write_start¶
mira_status_t mira_fota_write_start( uint16_t slot_id);
Start a write session to the FOTA cache.
During the write session it is possible to use the mira_fota_write()
method.
If the return value is MIRA_SUCCESS, a write session is requested. The write session is first started once mira_fota_is_working()
returns MIRA_FALSE. See mira_fota_is_working()
for more information.
If the returned value is not MIRA_SUCCESS, triggering the request is not successful.
Parameters
Parameter | Description |
---|---|
slot_id |
Slot number. |
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
A write session is successfully requested. |
MIRA_ERROR_ALREADY_INITIALIZED |
Another FOTA session is already active. |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA. |
mira_fota_write¶
mira_status_t mira_fota_write( mira_size_t dst, uint8_t* src, mira_size_t length);
Write to the FOTA cache. Writing to the FOTA cache is only available during a write session.
If the return value is MIRA_SUCCESS, a write operation is requested. The operation is finished when mira_fota_is_working()
returns MIRA_FALSE.
During the entire operation, the content of the memory must not change.
If the return value is not MIRA_SUCCESS, the write operation has not started.
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
A write request is successfully requested. |
MIRA_ERROR_NOT_INITIALIZED |
A write session has not been started yet (mira_fota_write_start() ). |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA. |
mira_fota_erase¶
mira_status_t mira_fota_erase( void);
Erase the FOTA cache. Erasing the FOTA cache is only available during the write cycle.
If the return value is MIRA_SUCCESS, an erase operation is requested. The operation is finished when mira_fota_is_working()
returns MIRA_FALSE.
If the return value is not MIRA_SUCCESS, the write operation has not started.
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
An erase request is successfully requested. |
MIRA_ERROR_NOT_INITIALIZED |
A write session has not been started yet (mira_fota_write_start() ). |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA read. |
mira_fota_write_header¶
mira_status_t mira_fota_write_header( mira_size_t size, uint32_t checksum, uint16_t type, uint8_t flags, uint8_t version);
Write a header to the FOTA cache. The header is necessary to validate the content of the cache, so transfer can proceed.
The version number is a sequence number which must be changed for every new image. Nodes use the version number to identify updates of the image. The version number does not have to be incremented in order. The version number must not be 255.
The checksum is of type CRC-32 of the content written to the cache. It's used to validate the content integrity for transfer errors. The checksum uses polynom defined as 0x04C11DB7.
If the return value is MIRA_SUCCESS, a write operation is requested. The operation is finished when mira_fota_is_working()
returns MIRA_FALSE.
If the return value is not MIRA_SUCCESS, the write operation has not started.
Parameters
Parameter | Description |
---|---|
size |
The size of the image to transfer. |
checksum |
Checksum of the content in the cache, which must match the data for the content to be treated as valid. |
type |
An integer to identify the information in the cache. |
flags |
Flags for future use, set to 0. |
version |
A sequence number that should change for each new update. |
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
A write request is successfully requested. |
MIRA_ERROR_NOT_INITIALIZED |
A write session has not been started yet (mira_fota_write_start() ). |
MIRA_ERROR_INVALID_VALUE |
The version parameter was 255. |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA read. |
mira_fota_write_end¶
mira_status_t mira_fota_write_end( void);
Close the write session. The write operation will continue to work while mira_fota_is_working is returning MIRA_TRUE.
If the returned value is not MIRA_SUCCESS, the write session is aborted, and the image will not be valid.
Return
Status of the operation.
Value | Description |
---|---|
MIRA_SUCCESS |
The write session was successfully closed. |
MIRA_ERROR_NOT_INITIALIZED |
A write session has not been started yet (mira_fota_write_start() ). |
MIRA_FOTA_ERROR_LOCK |
Unable to access a lock to the FOTA read. |
mira_fota_is_working¶
mira_bool_t mira_fota_is_working( void);
Check if the last operation is still running. The process which called the previous operation will be polled when the operation is finished. Recommended usage:
mira_fota_operation(...); PROCESS_WAIT_WHILE(mira_fota_is_working());
Return
If a FOTA operation is currently working.
Value | Description |
---|---|
MIRA_FALSE |
No FOTA operation is currently executing. |
MIRA_TRUE |
There is a FOTA operation which is currently executing. |