|
| 1 | +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
| 2 | +Device_Update.h |
| 3 | +
|
| 4 | + Device firmware update data structures and declarations |
| 5 | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 6 | + |
| 7 | +#ifndef __DEVICE_UPDATE_H__ |
| 8 | +#define __DEVICE_UPDATE_H__ |
| 9 | + |
| 10 | +//---------------------------------------- |
| 11 | +// Describe the volatile buffer description |
| 12 | +//---------------------------------------- |
| 13 | +typedef struct _DFU_BUFFER_DATA |
| 14 | +{ |
| 15 | + uint8_t * _address; |
| 16 | + size_t _length; |
| 17 | + size_t _offset; |
| 18 | + char ** _nameArray; |
| 19 | + int * _sortArray; |
| 20 | +} DFU_BUFFER_DATA; |
| 21 | + |
| 22 | +//---------------------------------------- |
| 23 | +// Allocate and forget buffer descriptions used during early initialization |
| 24 | +//---------------------------------------- |
| 25 | +typedef struct _DFU_BUFFER_INFO |
| 26 | +{ |
| 27 | + bool * _present; // nullptr or *_present = true, allocate buffer |
| 28 | + size_t _sizeInBytes; // Initial buffer size |
| 29 | + DFU_BUFFER_DATA * _bufferData; |
| 30 | + const char * _description; // Text for rtkMalloc |
| 31 | +} DFU_BUFFER_INFO; |
| 32 | + |
| 33 | +//---------------------------------------- |
| 34 | +// Context for the firmware update processing |
| 35 | +//---------------------------------------- |
| 36 | +typedef struct _DEVICE_FIRMWARE_CTX |
| 37 | +{ |
| 38 | + void * _devCtx; // Device specific context address |
| 39 | + const struct _DEVICE_FIRMWARE_INFO * _deviceInfo; // Selected device |
| 40 | + int _state; // Current device firmware update state |
| 41 | + bool _doAll; // Perform all of the device firmware updates |
| 42 | + bool _debugVerbose; // Display the most amount of data |
| 43 | + |
| 44 | + // Input device |
| 45 | + int _inputDeviceType; // Type of input device |
| 46 | + bool _networkConfigured; // Is the network configured |
| 47 | + size_t _fileBytes; // Length of the file in bytes |
| 48 | + |
| 49 | + // Buffer support |
| 50 | + bool _dynamicAllocationFd; |
| 51 | + bool _dynamicAllocationNet; |
| 52 | + bool _dynamicAllocationNvm; |
| 53 | + bool _dynamicAllocationSd; |
| 54 | + |
| 55 | + // Read support |
| 56 | + // |
| 57 | + // _buffer ---. .--- _data |
| 58 | + // | | |
| 59 | + // V V |
| 60 | + // [----------------xxxxxxxxxxxxxxxxxxxxxxxx--------] |
| 61 | + // | |<-- _validDataBytes -->| | |
| 62 | + // |<-- _bufferLength ----------------------------->| |
| 63 | + // |
| 64 | + // |<--------------- _fileBytes ------------------->| |
| 65 | + // [rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr---] |
| 66 | + // |<---------------- _bytesRead -------------->| |
| 67 | + // |
| 68 | + uint8_t * _buffer; // Buffer to read in the firmware |
| 69 | + uint8_t * _data; // Beginning of valid data |
| 70 | + size_t _bufferLength; // Length of the buffer |
| 71 | + size_t _validDataBytes; // Length of the valid data |
| 72 | + size_t _bytesRead; // Total number of bytes read |
| 73 | + |
| 74 | + // Write path support |
| 75 | + // |
| 76 | + // _buffer ---. .--- _data |
| 77 | + // | | |
| 78 | + // V V |
| 79 | + // [----------------xxxxxxxxxxxxxxxxxxxxxxxx--------] |
| 80 | + // | |<-- _bytesMax -->| | |
| 81 | + // | |<-- _validDataBytes -->| | |
| 82 | + // |<-- _bufferLength ----------------------------->| |
| 83 | + // |
| 84 | + // |
| 85 | + // |<--------------- _fileBytes ------------------->| |
| 86 | + // [wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwrrrrr---] |
| 87 | + // |<-------- _bytesWritten -------------->| | |
| 88 | + // |<---------------- _bytesRead -------------->| |
| 89 | + // |
| 90 | + int _outputDeviceType; // Type of output device |
| 91 | + uint8_t * _writeBuffer; // Additional buffer for write operations |
| 92 | + size_t _bytesMax; // Maximum bytes to write at one time |
| 93 | + size_t _bytesWritten; // Number of bytes written to the output device |
| 94 | + uint32_t _packetNumber; // Current firmware packet number |
| 95 | + |
| 96 | + // Verbose debug buffer |
| 97 | + uint8_t * _saveData; // Buffer to receive input data from device |
| 98 | + size_t _saveDataLength; // Size in bytes of the save buffer |
| 99 | + |
| 100 | + // Status values |
| 101 | + uint32_t _attemptNumber; // Number of attempts |
| 102 | + uint32_t _lastBlinkMsec; // Blinking LED to indicate activity |
| 103 | + uint32_t _startMsec; // Starting time of file transfer |
| 104 | + uint32_t _timerMsec; // General timer |
| 105 | + int _percentage; // Write percentage |
| 106 | + bool _complete; // Transfer complete (_bytesWritten == _fileBytes) |
| 107 | + bool _reboot; // Reboot after firmware update |
| 108 | +} DEVICE_FIRMWARE_CTX; |
| 109 | + |
| 110 | +//---------------------------------------- |
| 111 | +// Declare the global device firmware update context |
| 112 | +//---------------------------------------- |
| 113 | +DEVICE_FIRMWARE_CTX * dfuContext; |
| 114 | + |
| 115 | +//---------------------------------------- |
| 116 | +// Declare the device firmware update states (DFUS) |
| 117 | +//---------------------------------------- |
| 118 | +enum _DEVICE_FIRMWARE_UPDATE_STATE |
| 119 | +{ |
| 120 | + DFUS_DONE = 0, |
| 121 | + DFUS_INIT, |
| 122 | + DFUS_WAIT_NETWORK, |
| 123 | + DFUS_GET_DEVICE, |
| 124 | + DFUS_GET_NETWORK_FILES, |
| 125 | + DFUS_GET_HTTP_FILE_LIST_REQ, |
| 126 | + DFUS_GET_NETWORK_FILE_LIST, |
| 127 | + DFUS_GET_NVM_FILE_LIST, |
| 128 | + DFUS_GET_SD_FILE_LIST, |
| 129 | + DFUS_SELECT_FILE, |
| 130 | + DFUS_SELECT_ACTION, |
| 131 | + DFUS_CRC_OPEN_INPUT, |
| 132 | + DFUS_CRC_READ_DATA, |
| 133 | + DFUS_CRC_CLOSE, |
| 134 | + DFUS_DEVICE_OPEN_INPUT, |
| 135 | + DFUS_DEVICE_FILL_BUFFER, |
| 136 | + DFUS_DEVICE_RESET, |
| 137 | + DFUS_DEVICE_OPEN_OUTPUT, |
| 138 | + DFUS_DEVICE_PROGRAM_FIRMWARE, |
| 139 | + DFUS_READ_FIRMWARE_DATA, |
| 140 | + DFUS_DEVICE_CLOSE, |
| 141 | + DFUS_NEXT_DEVICE, |
| 142 | + DFUS_REBOOT, |
| 143 | + // Add new states above this line |
| 144 | + DFUS_MAX |
| 145 | +}; |
| 146 | + |
| 147 | +//---------------------------------------- |
| 148 | +// Output device to which the firmware file will be copied |
| 149 | +//---------------------------------------- |
| 150 | +enum DFU_OUTPUT_DEVICE_TYPE |
| 151 | +{ |
| 152 | + DFU_ODT_NONE = 0, |
| 153 | + DFU_ODT_TEST, |
| 154 | + DFU_ODT_DEVICE, |
| 155 | + DFU_ODT_NVM, |
| 156 | + DFU_ODT_SD, |
| 157 | +}; |
| 158 | + |
| 159 | +//---------------------------------------- |
| 160 | +// Declare the generic device firmware update routines |
| 161 | +//---------------------------------------- |
| 162 | +typedef void (* DEVICE_CLOSE)(DEVICE_FIRMWARE_CTX * ctx); |
| 163 | +typedef bool (* DEVICE_OPEN)(DEVICE_FIRMWARE_CTX * ctx); |
| 164 | +typedef bool (* DEVICE_RESET)(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec); |
| 165 | +typedef ssize_t (* DEVICE_WRITE)(DEVICE_FIRMWARE_CTX * ctx, |
| 166 | + const uint8_t * buffer, |
| 167 | + size_t bytesToWrite); |
| 168 | +typedef String (* GET_FIRMWARE_VERSION)(DEVICE_FIRMWARE_CTX * ctx); |
| 169 | +typedef bool (* INIT_DEV_CTX)(DEVICE_FIRMWARE_CTX * ctx); |
| 170 | + |
| 171 | +//---------------------------------------- |
| 172 | +// Describe a device that needs firmware updates |
| 173 | +//---------------------------------------- |
| 174 | +typedef struct _DEVICE_FIRMWARE_INFO |
| 175 | +{ |
| 176 | + // The following fields should be unique to each device |
| 177 | + const char * _deviceName; // Name of this device |
| 178 | + DEVICE_RESET _reset; // Reset the device before loading firmware |
| 179 | + DEVICE_OPEN _open; // Prepare for firmware updates |
| 180 | + DEVICE_WRITE _write; // Perform the firmware writes |
| 181 | + DEVICE_CLOSE _close; // Perform firmware write cleanup |
| 182 | + INIT_DEV_CTX _initDevCtx; // Initialize the device specific context |
| 183 | + size_t _devContextBytes; // Size of device specific context buffer |
| 184 | + size_t _writeBufferBytes; // Number of bytes needed for the write buffer |
| 185 | + size_t _maxWriteBytes; // Maximum write packet size |
| 186 | +} DEVICE_FIRMWARE_INFO; |
| 187 | + |
| 188 | +//---------------------------------------- |
| 189 | +// Statically allocated buffers |
| 190 | +//---------------------------------------- |
| 191 | + |
| 192 | +DFU_BUFFER_DATA dfuFirmwareData; |
| 193 | + |
| 194 | +// Allocate buffer when (_present == nullptr) or (*_present == true) |
| 195 | +// Delayed allocations must be detected by code using the buffer |
| 196 | +const DFU_BUFFER_INFO dfuBufferInfo[] = |
| 197 | +{ // _present _sizeInBytes _address _description |
| 198 | + {nullptr, 16 * 1024, &dfuFirmwareData, "DFU Firmware data buffer"}, |
| 199 | +}; |
| 200 | +const int dfuBufferInfoCount = sizeof(dfuBufferInfo) / sizeof(dfuBufferInfo[0]); |
| 201 | + |
| 202 | +//---------------------------------------- |
| 203 | +// Device specific context |
| 204 | +//---------------------------------------- |
| 205 | + |
| 206 | +typedef struct _DFU_STM32_CONTEXT |
| 207 | +{ |
| 208 | + HardwareSerial * _stm32Serial; // ESP32 serial port for STM32 communication |
| 209 | +} DFU_STM32_CONTEXT; |
| 210 | +#define DFU_STM32_CTX_LEN sizeof(DFU_STM32_CONTEXT) |
| 211 | + |
| 212 | +// Context initialization routines |
| 213 | +bool dfuLoRaCtxInit(DEVICE_FIRMWARE_CTX * ctx); |
| 214 | + |
| 215 | +//---------------------------------------- |
| 216 | +// Declare the device specific maximum write size |
| 217 | +//---------------------------------------- |
| 218 | + |
| 219 | +// LG290P declarations |
| 220 | +#ifdef COMPILE_LG290P |
| 221 | +#define DFU_LG290P_MAX_PAYLOAD_SIZE (5 * 1024) |
| 222 | +#define DFU_LG290P_BYTES (1 + 1 + 1 + 2 + 4 + DFU_LG290P_MAX_PAYLOAD_SIZE + 4 + 1) |
| 223 | +#endif // COMPILE_LG290P |
| 224 | + |
| 225 | +// STM32 declarations |
| 226 | +#define DFU_STM32_MAX_PAYLOAD_SIZE 256 |
| 227 | +#define DFU_STM32_BYTES (1 + DFU_STM32_MAX_PAYLOAD_SIZE + 1) |
| 228 | + |
| 229 | +//---------------------------------------- |
| 230 | +// Declare the forward device support routines |
| 231 | +//---------------------------------------- |
| 232 | + |
| 233 | +// Get firmware version |
| 234 | +String dfuEsp32GetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx); |
| 235 | +String dfuGnssGetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx); |
| 236 | +String dfuLoRaGetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx); |
| 237 | + |
| 238 | +// Device reset |
| 239 | +bool dfuLg290pReset(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec); |
| 240 | +bool dfuLoRaReset(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec); |
| 241 | + |
| 242 | +// Device open, prepare for writing firmware |
| 243 | +bool dfuEsp32Open(DEVICE_FIRMWARE_CTX * ctx); |
| 244 | +bool dfuLg290pOpen(DEVICE_FIRMWARE_CTX * ctx); |
| 245 | +bool dfuStm32Open(DEVICE_FIRMWARE_CTX * ctx); |
| 246 | + |
| 247 | +// Device write, perform the firmware update |
| 248 | +ssize_t dfuEsp32Write(DEVICE_FIRMWARE_CTX * ctx, |
| 249 | + const uint8_t * buffer, |
| 250 | + size_t bytesToWrite); |
| 251 | +ssize_t dfuLg290pWrite(DEVICE_FIRMWARE_CTX * ctx, |
| 252 | + const uint8_t * buffer, |
| 253 | + size_t bytesToWrite); |
| 254 | +ssize_t dfuStm32Write(DEVICE_FIRMWARE_CTX * ctx, |
| 255 | + const uint8_t * buffer, |
| 256 | + size_t bytesToWrite); |
| 257 | + |
| 258 | +// Device close, finalize the firmware update |
| 259 | +void dfuEsp32Close(DEVICE_FIRMWARE_CTX * ctx); |
| 260 | +void dfuLg290pClose(DEVICE_FIRMWARE_CTX * ctx); |
| 261 | +void dfuLoRaClose(DEVICE_FIRMWARE_CTX * ctx); |
| 262 | + |
| 263 | +// Declare the begin routine |
| 264 | +bool deviceFirmwareUpdateBegin(bool doAll, |
| 265 | + bool debugVerbose, |
| 266 | + size_t saveDataLength = 8 * 1024); |
| 267 | + |
| 268 | +//---------------------------------------- |
| 269 | +// Describe the devices that support firmware update |
| 270 | +//---------------------------------------- |
| 271 | + |
| 272 | +// Note: Use the JSON based OTA to get a new ESP32 image when the |
| 273 | +// parsing fails due to website changes on the servers below! |
| 274 | +const DEVICE_FIRMWARE_INFO deviceFirmwareInfo[] = |
| 275 | +{// Name Reset Open Write Close InitDevCtx Context Bytes Buffer Bytes Max Write Bytes |
| 276 | + // LoRa devices |
| 277 | + {"LoRa", dfuLoRaReset, dfuStm32Open, dfuStm32Write, dfuLoRaClose, dfuLoRaCtxInit, DFU_STM32_CTX_LEN, DFU_STM32_BYTES, DFU_STM32_MAX_PAYLOAD_SIZE}, |
| 278 | +}; |
| 279 | +const int deviceFirmwareInfoCount = sizeof(deviceFirmwareInfo) / sizeof(deviceFirmwareInfo[0]); |
| 280 | + |
| 281 | +#endif // __DEVICE_UPDATE_H__ |
0 commit comments