Skip to content

Commit ff12f22

Browse files
committed
STM32_Update_From_Array: Update to use RTK routines
Differences between RTK routines and example routines show additional code in RTK routines to support NVM, SD, network and CRC.
1 parent ce13a58 commit ff12f22

13 files changed

Lines changed: 7081 additions & 14366 deletions

File tree

Firmware/Test Sketches/Flash_Update/STM32_Update_From_Array/Device_Firmware_Update.ino

Lines changed: 635 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
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__
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2+
Device_Update_ESP32.ino
3+
4+
Support routines to program the ESP32 firmware application area
5+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6+
7+
//----------------------------------------
8+
// Reboot the ESP32
9+
//----------------------------------------
10+
void dfuEsp32Reboot()
11+
{
12+
// Restart ESP32 to see changes
13+
systemPrintf("Rebooting. Goodbye!\r\n");
14+
Serial.flush();
15+
delay(1000);
16+
ESP.restart();
17+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2+
Device_Update_LoRa.ino
3+
4+
Update LoRa (STM32) firmware
5+
See https://www.st.com/resource/en/application_note/CD00264342.pdf
6+
7+
Example Linux command to covert Intel Hex files into binary files:
8+
9+
objcopy --input-target=ihex --output-target=binary --gap-fill 0xff SparkPNT_LoRa_3.0.1.hex SparkPNT_LoRa_3.0.1.bin
10+
11+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12+
13+
//----------------------------------------
14+
// Perform the cleanup after the firmware download
15+
//----------------------------------------
16+
void dfuLoRaClose(DEVICE_FIRMWARE_CTX * ctx)
17+
{
18+
systemPrintf("Update Complete. Resetting IC...");
19+
20+
gpioExpanderLoraBootDisable(); // Pull BOOT0 low to exit bootloader mode on reset
21+
dfuLoRaReset(); // Power cycle LoRa to reset into normal mode
22+
}
23+
24+
//----------------------------------------
25+
// Initialize the device specific context structure
26+
//----------------------------------------
27+
bool dfuLoRaCtxInit(DEVICE_FIRMWARE_CTX * ctx)
28+
{
29+
DFU_STM32_CONTEXT * stm32Ctx;
30+
31+
stm32Ctx = (DFU_STM32_CONTEXT *)(ctx->_devCtx);
32+
stm32Ctx->_stm32Serial = SerialForLoRa;
33+
return true;
34+
}
35+
36+
//----------------------------------------
37+
// There is not a hardware reset pin exposed. Power cycle the device.
38+
//----------------------------------------
39+
void dfuLoRaReset()
40+
{
41+
gpioExpanderLoraDisable(); // Power off
42+
delay(100);
43+
gpioExpanderLoraEnable(); // Power on
44+
delay(100);
45+
}
46+
47+
//----------------------------------------
48+
// Reset the LoRa (STM32) and start the boot loader
49+
//----------------------------------------
50+
bool dfuLoRaReset(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec)
51+
{
52+
// Connect ESP32 UART2 to LoRa UART2 via SW3 for configuration and bootloading/firmware updates
53+
gpioExpanderSelectLoraConfigure();
54+
serialInputClear(SerialForLoRa);
55+
56+
// Pull BOOT0 high to enter bootloader mode on reset
57+
gpioExpanderLoraBootEnable();
58+
59+
// Power cycle the LoRa device to perform the reset and enter
60+
// bootloader mode
61+
dfuLoRaReset();
62+
63+
// Send 0x7F for auto-baud detection
64+
return dfuStm32Autobaud(ctx);
65+
}

0 commit comments

Comments
 (0)