Refactor OTA update code
This commit is contained in:
@@ -246,6 +246,7 @@
|
||||
// FLASH
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
#include "drivers/SPIFlash/SPIFlash.cpp"
|
||||
#include "core/MyOTAFirmwareUpdate.cpp"
|
||||
#endif
|
||||
#include "core/MyTransport.cpp"
|
||||
#if (defined(MY_RADIO_NRF24) && defined(MY_RADIO_RFM69)) || (defined(MY_RADIO_NRF24) && defined(MY_RS485)) || (defined(MY_RADIO_RFM69) && defined(MY_RS485))
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2016 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyOTAFirmwareUpdate.h"
|
||||
|
||||
SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID);
|
||||
NodeFirmwareConfig _fc;
|
||||
bool _fwUpdateOngoing;
|
||||
unsigned long _fwLastRequestTime;
|
||||
uint16_t _fwBlock;
|
||||
uint8_t _fwRetry;
|
||||
|
||||
inline void readFirmwareSettings() {
|
||||
hwReadConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
|
||||
}
|
||||
|
||||
inline void firmwareOTAUpdateRequest() {
|
||||
unsigned long enter = hwMillis();
|
||||
if (_fwUpdateOngoing && (enter - _fwLastRequestTime > MY_OTA_RETRY_DELAY)) {
|
||||
if (!_fwRetry) {
|
||||
debug(PSTR("fw upd fail\n"));
|
||||
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
|
||||
_fwUpdateOngoing = false;
|
||||
ledBlinkErr(1);
|
||||
return;
|
||||
}
|
||||
_fwRetry--;
|
||||
_fwLastRequestTime = enter;
|
||||
// Time to (re-)request firmware block from controller
|
||||
RequestFWBlock firmwareRequest;
|
||||
firmwareRequest.type = _fc.type;
|
||||
firmwareRequest.version = _fc.version;
|
||||
firmwareRequest.block = (_fwBlock - 1);
|
||||
debug(PSTR("req FW: T=%02X, V=%02X, B=%04X\n"),_fc.type,_fc.version,_fwBlock - 1);
|
||||
_sendRoute(build(_msgTmp, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false).set(&firmwareRequest,sizeof(RequestFWBlock)));
|
||||
}
|
||||
}
|
||||
|
||||
inline bool firmwareOTAUpdateProcess() {
|
||||
if (_msg.type == ST_FIRMWARE_CONFIG_RESPONSE) {
|
||||
NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)_msg.data;
|
||||
// compare with current node configuration, if they differ, start fw fetch process
|
||||
if (memcmp(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) {
|
||||
debug(PSTR("fw update\n"));
|
||||
// copy new FW config
|
||||
memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig));
|
||||
// Init flash
|
||||
if (!_flash.initialize()) {
|
||||
debug(PSTR("flash init fail\n"));
|
||||
_fwUpdateOngoing = false;
|
||||
} else {
|
||||
// erase lower 32K -> max flash size for ATMEGA328
|
||||
_flash.blockErase32K(0);
|
||||
// wait until flash erased
|
||||
while ( _flash.busy() );
|
||||
_fwBlock = _fc.blocks;
|
||||
_fwUpdateOngoing = true;
|
||||
// reset flags
|
||||
_fwRetry = MY_OTA_RETRY+1;
|
||||
_fwLastRequestTime = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
debug(PSTR("fw update skipped\n"));
|
||||
} else if (_msg.type == ST_FIRMWARE_RESPONSE) {
|
||||
if (_fwUpdateOngoing) {
|
||||
// Save block to flash
|
||||
debug(PSTR("fw block %d\n"), _fwBlock);
|
||||
// extract FW block
|
||||
ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data;
|
||||
// write to flash
|
||||
_flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
||||
// wait until flash written
|
||||
while ( _flash.busy() );
|
||||
_fwBlock--;
|
||||
if (!_fwBlock) {
|
||||
// We're finished! Do a checksum and reboot.
|
||||
_fwUpdateOngoing = false;
|
||||
if (transportIsValidFirmware()) {
|
||||
debug(PSTR("fw checksum ok\n"));
|
||||
// All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it)
|
||||
uint16_t fwsize = FIRMWARE_BLOCK_SIZE * _fc.blocks;
|
||||
uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(uint8_t)(fwsize >> 8),(uint8_t)(fwsize & 0xff),':'};
|
||||
_flash.writeBytes(0, OTAbuffer, 10);
|
||||
// Write the new firmware config to eeprom
|
||||
hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
|
||||
hwReboot();
|
||||
} else {
|
||||
debug(PSTR("fw checksum fail\n"));
|
||||
}
|
||||
}
|
||||
// reset flags
|
||||
_fwRetry = MY_OTA_RETRY+1;
|
||||
_fwLastRequestTime = 0;
|
||||
} else {
|
||||
debug(PSTR("No fw update ongoing\n"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void presentBootloaderInformation(){
|
||||
RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)_msgTmp.data;
|
||||
mSetLength(_msgTmp, sizeof(RequestFirmwareConfig));
|
||||
mSetCommand(_msgTmp, C_STREAM);
|
||||
mSetPayloadType(_msgTmp,P_CUSTOM);
|
||||
// copy node settings to reqFWConfig
|
||||
memcpy(reqFWConfig,&_fc,sizeof(NodeFirmwareConfig));
|
||||
// add bootloader information
|
||||
reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
|
||||
_fwUpdateOngoing = false;
|
||||
_sendRoute(build(_msgTmp, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false));
|
||||
}
|
||||
// do a crc16 on the whole received firmware
|
||||
inline bool transportIsValidFirmware() {
|
||||
// init crc
|
||||
uint16_t crc = ~0;
|
||||
for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) {
|
||||
crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET);
|
||||
for (int8_t j = 0; j < 8; ++j) {
|
||||
if (crc & 1)
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
else
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
return crc == _fc.crc;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2016 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyOTAFirmwareUpdate_h
|
||||
#define MyOTAFirmwareUpdate_h
|
||||
|
||||
#include "MySensorCore.h"
|
||||
|
||||
// Size of each firmware block
|
||||
#define FIRMWARE_BLOCK_SIZE 16
|
||||
// Number of times a firmware block should be requested before giving up
|
||||
#define FIRMWARE_MAX_REQUESTS 5
|
||||
// Number of times to request a fw block before giving up
|
||||
#define MY_OTA_RETRY 5
|
||||
// Number of millisecons before re-request a fw block
|
||||
#define MY_OTA_RETRY_DELAY 500
|
||||
// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first)
|
||||
#define FIRMWARE_START_OFFSET 10
|
||||
// Bootloader version
|
||||
#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3
|
||||
#define MY_OTA_BOOTLOADER_MINOR_VERSION 0
|
||||
#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION)
|
||||
|
||||
|
||||
/// @brief FW config structure, stored in eeprom
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t blocks; //!< Number of blocks
|
||||
uint16_t crc; //!< CRC of block data
|
||||
} __attribute__((packed)) NodeFirmwareConfig;
|
||||
|
||||
/// @brief FW config request structure
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t blocks; //!< Number of blocks
|
||||
uint16_t crc; //!< CRC of block data
|
||||
uint16_t BLVersion; //!< Bootloader version
|
||||
} __attribute__((packed)) RequestFirmwareConfig;
|
||||
|
||||
/// @brief FW block request structure
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t block; //!< Block index
|
||||
} __attribute__((packed)) RequestFWBlock;
|
||||
|
||||
/// @brief FW block reply structure
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t block; //!< Block index
|
||||
uint8_t data[FIRMWARE_BLOCK_SIZE]; //!< Block data
|
||||
} __attribute__((packed)) ReplyFWBlock;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read firmware settings from EEPROM
|
||||
*
|
||||
* Current firmware settings (type, version, crc, blocks) are read into _fc
|
||||
*/
|
||||
void readFirmwareSettings();
|
||||
/**
|
||||
* @brief Handle OTA FW update requests
|
||||
*/
|
||||
void firmwareOTAUpdateRequest();
|
||||
/**
|
||||
* @brief Handle OTA FW update responses
|
||||
*
|
||||
* This function handles incoming OTA FW packets and stores them to external flash (Sensebender)
|
||||
*/
|
||||
bool firmwareOTAUpdateProcess();
|
||||
/**
|
||||
* @brief Validate uploaded FW CRC
|
||||
*
|
||||
* This function verifies if uploaded FW CRC is valid
|
||||
*/
|
||||
bool transportIsValidFirmware();
|
||||
/**
|
||||
* @brief Present bootloader/FW information upon startup
|
||||
*/
|
||||
void presentBootloaderInformation();
|
||||
|
||||
#endif
|
||||
@@ -128,9 +128,9 @@ void _begin() {
|
||||
#elif defined(MY_RADIO_FEATURE)
|
||||
// Read settings from eeprom
|
||||
hwReadConfigBlock((void*)&_nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig));
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
||||
// Read firmware config from EEPROM, i.e. type, version, CRC, blocks
|
||||
hwReadConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
|
||||
readFirmwareSettings();
|
||||
#endif
|
||||
|
||||
_autoFindParent = MY_PARENT_NODE_ID == AUTO;
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
#include "MyConfig.h"
|
||||
#include "MyEepromAddresses.h"
|
||||
#include "MyMessage.h"
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
#include "drivers/SPIFlash/SPIFlash.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
@@ -23,16 +23,6 @@
|
||||
bool _autoFindParent;
|
||||
uint8_t _failedTransmissions;
|
||||
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID);
|
||||
NodeFirmwareConfig _fc;
|
||||
bool _fwUpdateOngoing;
|
||||
unsigned long _fwLastRequestTime;
|
||||
uint16_t _fwBlock;
|
||||
uint8_t _fwRetry;
|
||||
#endif
|
||||
|
||||
|
||||
static inline bool isValidDistance( const uint8_t distance ) {
|
||||
return distance != DISTANCE_INVALID;
|
||||
}
|
||||
@@ -43,25 +33,7 @@ inline void transportProcess() {
|
||||
if (!transportAvailable(&to))
|
||||
{
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
unsigned long enter = hwMillis();
|
||||
if (_fwUpdateOngoing && (enter - _fwLastRequestTime > MY_OTA_RETRY_DELAY)) {
|
||||
if (!_fwRetry) {
|
||||
debug(PSTR("fw upd fail\n"));
|
||||
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
|
||||
_fwUpdateOngoing = false;
|
||||
ledBlinkErr(1);
|
||||
return;
|
||||
}
|
||||
_fwRetry--;
|
||||
_fwLastRequestTime = enter;
|
||||
// Time to (re-)request firmware block from controller
|
||||
RequestFWBlock *firmwareRequest = (RequestFWBlock *)_msg.data;
|
||||
mSetLength(_msg, sizeof(RequestFWBlock));
|
||||
firmwareRequest->type = _fc.type;
|
||||
firmwareRequest->version = _fc.version;
|
||||
firmwareRequest->block = (_fwBlock - 1);
|
||||
_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false));
|
||||
}
|
||||
firmwareOTAUpdateRequest();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -179,72 +151,13 @@ inline void transportProcess() {
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
else if (command == C_STREAM) {
|
||||
if (type == ST_FIRMWARE_CONFIG_RESPONSE) {
|
||||
NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)_msg.data;
|
||||
// compare with current node configuration, if they differ, start fw fetch process
|
||||
if (memcmp(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) {
|
||||
debug(PSTR("fw update\n"));
|
||||
// copy new FW config
|
||||
memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig));
|
||||
// Init flash
|
||||
if (!_flash.initialize()) {
|
||||
debug(PSTR("flash init fail\n"));
|
||||
_fwUpdateOngoing = false;
|
||||
} else {
|
||||
// erase lower 32K -> max flash size for ATMEGA328
|
||||
_flash.blockErase32K(0);
|
||||
// wait until flash erased
|
||||
while ( _flash.busy() );
|
||||
_fwBlock = _fc.blocks;
|
||||
_fwUpdateOngoing = true;
|
||||
// reset flags
|
||||
_fwRetry = MY_OTA_RETRY+1;
|
||||
_fwLastRequestTime = 0;
|
||||
}
|
||||
return ;
|
||||
} else if (command == C_STREAM) {
|
||||
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
||||
if(firmwareOTAUpdateProcess()){
|
||||
return; // OTA FW update processing indicated no further action needed
|
||||
}
|
||||
debug(PSTR("fw update skipped\n"));
|
||||
} else if (type == ST_FIRMWARE_RESPONSE) {
|
||||
if (_fwUpdateOngoing) {
|
||||
// Save block to flash
|
||||
debug(PSTR("fw block %d\n"), _fwBlock);
|
||||
// extract FW block
|
||||
ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data;
|
||||
// write to flash
|
||||
_flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
||||
// wait until flash written
|
||||
while ( _flash.busy() );
|
||||
_fwBlock--;
|
||||
if (!_fwBlock) {
|
||||
// We're finished! Do a checksum and reboot.
|
||||
_fwUpdateOngoing = false;
|
||||
if (transportIsValidFirmware()) {
|
||||
debug(PSTR("fw checksum ok\n"));
|
||||
// All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it)
|
||||
uint16_t fwsize = FIRMWARE_BLOCK_SIZE * _fc.blocks;
|
||||
uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(uint8_t)(fwsize >> 8),(uint8_t)(fwsize & 0xff),':'};
|
||||
_flash.writeBytes(0, OTAbuffer, 10);
|
||||
// Write the new firmware config to eeprom
|
||||
hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
|
||||
hwReboot();
|
||||
} else {
|
||||
debug(PSTR("fw checksum fail\n"));
|
||||
}
|
||||
}
|
||||
// reset flags
|
||||
_fwRetry = MY_OTA_RETRY+1;
|
||||
_fwLastRequestTime = 0;
|
||||
} else {
|
||||
debug(PSTR("No fw update ongoing\n"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
// Hand over message to controller
|
||||
gatewayTransportSend(_msg);
|
||||
@@ -296,26 +209,6 @@ inline void transportProcess() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
// do a crc16 on the whole received firmware
|
||||
bool transportIsValidFirmware() {
|
||||
// init crc
|
||||
uint16_t crc = ~0;
|
||||
for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) {
|
||||
crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET);
|
||||
for (int8_t j = 0; j < 8; ++j) {
|
||||
if (crc & 1)
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
else
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
return crc == _fc.crc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
boolean transportSendWrite(uint8_t to, MyMessage &message) {
|
||||
|
||||
mSetVersion(message, PROTOCOL_VERSION);
|
||||
@@ -463,6 +356,9 @@ void transportPresentNode() {
|
||||
#endif
|
||||
#else
|
||||
if (_nc.nodeId != AUTO) {
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
presentBootloaderInformation();
|
||||
#endif
|
||||
// Send signing preferences for this node to the GW
|
||||
signerPresentation(_msg, GATEWAY_ADDRESS);
|
||||
|
||||
@@ -479,19 +375,6 @@ void transportPresentNode() {
|
||||
|
||||
// Wait configuration reply.
|
||||
wait(2000, C_INTERNAL, I_CONFIG);
|
||||
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)_msg.data;
|
||||
mSetLength(_msg, sizeof(RequestFirmwareConfig));
|
||||
mSetCommand(_msg, C_STREAM);
|
||||
mSetPayloadType(_msg,P_CUSTOM);
|
||||
// copy node settings to reqFWConfig
|
||||
memcpy(reqFWConfig,&_fc,sizeof(NodeFirmwareConfig));
|
||||
// add bootloader information
|
||||
reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
|
||||
_fwUpdateOngoing = false;
|
||||
_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -23,59 +23,9 @@
|
||||
#include <stdint.h>
|
||||
#include "MySensorCore.h"
|
||||
|
||||
// Size of each firmware block
|
||||
#define FIRMWARE_BLOCK_SIZE 16
|
||||
// Number of times a firmware block should be requested before giving up
|
||||
#define FIRMWARE_MAX_REQUESTS 5
|
||||
// Number of times to request a fw block before giving up
|
||||
#define MY_OTA_RETRY 5
|
||||
// Number of millisecons before re-request a fw block
|
||||
#define MY_OTA_RETRY_DELAY 500
|
||||
// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first)
|
||||
#define FIRMWARE_START_OFFSET 10
|
||||
// Bootloader version
|
||||
#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3
|
||||
#define MY_OTA_BOOTLOADER_MINOR_VERSION 0
|
||||
#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION)
|
||||
|
||||
// Search for a new parent node after this many transmission failures
|
||||
#define SEARCH_FAILURES 5
|
||||
|
||||
|
||||
/// @brief FW config structure, stored in eeprom
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t blocks; //!< Number of blocks
|
||||
uint16_t crc; //!< CRC of block data
|
||||
} __attribute__((packed)) NodeFirmwareConfig;
|
||||
|
||||
/// @brief FW config request structure
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t blocks; //!< Number of blocks
|
||||
uint16_t crc; //!< CRC of block data
|
||||
uint16_t BLVersion; //!< Bootloader version
|
||||
} __attribute__((packed)) RequestFirmwareConfig;
|
||||
|
||||
/// @brief FW block request structure
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t block; //!< Block index
|
||||
} __attribute__((packed)) RequestFWBlock;
|
||||
|
||||
/// @brief FW block reply structure
|
||||
typedef struct {
|
||||
uint16_t type; //!< Type of config
|
||||
uint16_t version; //!< Version of config
|
||||
uint16_t block; //!< Block index
|
||||
uint8_t data[FIRMWARE_BLOCK_SIZE]; //!< Block data
|
||||
} __attribute__((packed)) ReplyFWBlock;
|
||||
|
||||
|
||||
|
||||
#define AUTO 0xFF // 0-254. Id 255 is reserved for auto initialization of nodeId.
|
||||
|
||||
#define BROADCAST_ADDRESS ((uint8_t)0xFF)
|
||||
|
||||
Reference in New Issue
Block a user