Skip to content

Commit f0b9e68

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 f0b9e68

12 files changed

Lines changed: 7026 additions & 14363 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: 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+
}
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2+
Device_Update_STM32.ino
3+
4+
Update STM32 firmware
5+
See https://www.st.com/resource/en/application_note/CD00264342.pdf
6+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7+
8+
//----------------------------------------
9+
// STM32 firmware open
10+
//----------------------------------------
11+
bool dfuStm32Open(DEVICE_FIRMWARE_CTX * ctx)
12+
{
13+
const uint8_t eraseCmd[] =
14+
{
15+
0xFF, // Erase all pages
16+
0xFF,
17+
0x00 // Checksum
18+
};
19+
const uint8_t extendedEraseCmd[] =
20+
{
21+
0x44, // Special Mass Erase
22+
0xBB // Checksum for 0x44
23+
};
24+
25+
do
26+
{
27+
systemPrintf("Erasing STM32 flash...\r\n");
28+
29+
// Global Mass Erase Command (0x44 for extended erase)
30+
if (dfuStm32SendData(ctx, extendedEraseCmd, sizeof(extendedEraseCmd), "Extended erase") != sizeof(extendedEraseCmd))
31+
{
32+
systemPrintf("ERROR: Failed to send extended erase command!\r\n");
33+
break;
34+
}
35+
if (dfuStm32WaitForAck(ctx) == false)
36+
break;
37+
38+
// Erase all pages
39+
if (dfuStm32SendData(ctx, eraseCmd, sizeof(eraseCmd), "Erase") != sizeof(eraseCmd))
40+
{
41+
systemPrintf("ERROR: Failed to send erase command!\r\n");
42+
break;
43+
}
44+
if (dfuStm32WaitForAck(ctx) == false)
45+
break;
46+
47+
if (settings.debugFirmwareUpdate)
48+
systemPrintf("STM32 flash erased.\r\n");
49+
return true;
50+
} while (0);
51+
return false;
52+
}
53+
54+
//----------------------------------------
55+
// Send the autobaud command to the STM32 boot loader
56+
//----------------------------------------
57+
bool dfuStm32Autobaud(DEVICE_FIRMWARE_CTX * ctx)
58+
{
59+
const uint8_t autobaudCmd[] =
60+
{
61+
0x7F
62+
};
63+
bool resetComplete;
64+
65+
do
66+
{
67+
// Send 0x7F for auto-baud detection
68+
resetComplete = false;
69+
if (dfuStm32SendData(ctx, autobaudCmd, sizeof(autobaudCmd), "Autobaud") != sizeof(autobaudCmd))
70+
{
71+
systemPrintf("ERROR: Failed to send autobaud command\r\n");
72+
break;
73+
}
74+
75+
// Wait for the ACK
76+
resetComplete = dfuStm32WaitForAck(ctx);
77+
if (resetComplete == false)
78+
{
79+
systemPrintf("ERROR: STM32 bootloader failed to sync!\r\n");
80+
break;
81+
}
82+
83+
if (settings.debugFirmwareUpdate)
84+
systemPrintf("STM32 bootloader synced.\r\n");
85+
} while (0);
86+
return resetComplete;
87+
}
88+
89+
//----------------------------------------
90+
// Send commands and data to the STM32 device
91+
//----------------------------------------
92+
ssize_t dfuStm32SendData(DEVICE_FIRMWARE_CTX * ctx,
93+
const uint8_t * data,
94+
size_t numberOfBytes,
95+
const char * description)
96+
{
97+
DFU_STM32_CONTEXT * stm32Ctx;
98+
99+
stm32Ctx = (DFU_STM32_CONTEXT *)(ctx->_devCtx);
100+
if (settings.debugFirmwareUpdate && ctx->_debugVerbose)
101+
{
102+
systemPrintf("TX Data: %s\r\n", description);
103+
dumpBuffer(0, data, numberOfBytes);
104+
}
105+
return stm32Ctx->_stm32Serial->write(data, numberOfBytes);
106+
}
107+
108+
//----------------------------------------
109+
// Display the wait time
110+
//----------------------------------------
111+
void dfuStm32WaitDisplayTime(DEVICE_FIRMWARE_CTX * ctx,
112+
const char * event,
113+
bool rxData,
114+
uint8_t * buffer)
115+
{
116+
if (settings.debugFirmwareUpdate)
117+
{
118+
// Display the data timing
119+
if (rxData)
120+
{
121+
systemPrintf("RX %s\r\n", event);
122+
123+
// Display the received data
124+
if (buffer && (buffer - ctx->_saveData))
125+
dumpBuffer(0, ctx->_saveData, buffer - ctx->_saveData);
126+
}
127+
else
128+
systemPrintf("RX Timeout, No data!\r\n");
129+
}
130+
}
131+
132+
//----------------------------------------
133+
// Helper to wait for an ACK (0x79) after a command was sent to the STM32
134+
//----------------------------------------
135+
bool dfuStm32WaitForAck(DEVICE_FIRMWARE_CTX * ctx)
136+
{
137+
uint8_t * buffer;
138+
uint8_t * bufferEnd;
139+
uint8_t data;
140+
bool rxData;
141+
DFU_STM32_CONTEXT * stm32Ctx;
142+
143+
stm32Ctx = (DFU_STM32_CONTEXT *)(ctx->_devCtx);
144+
uint32_t startTime = millis();
145+
buffer = ctx->_saveData;
146+
bufferEnd = &buffer[ctx->_saveDataLength];
147+
while ((millis() - startTime) < 1000)
148+
{
149+
if (stm32Ctx->_stm32Serial->available())
150+
{
151+
data = stm32Ctx->_stm32Serial->read();
152+
rxData = true;
153+
154+
// Save the data if requested
155+
if (buffer && (buffer < bufferEnd))
156+
*buffer++ = data;
157+
158+
// Check for ACK
159+
if (ctx->_debugVerbose)
160+
systemPrintf("0x%02x\r\n", data);
161+
if (data == 0x79)
162+
{
163+
dfuStm32WaitDisplayTime(ctx, "ACK", true, buffer);
164+
return true;
165+
}
166+
167+
// Check for NACK
168+
if (data == 0x1f)
169+
{
170+
dfuStm32WaitDisplayTime(ctx, "NACK", true, buffer);
171+
return false;
172+
}
173+
}
174+
}
175+
dfuStm32WaitDisplayTime(ctx, "Timeout", rxData, buffer);
176+
return false;
177+
}
178+
179+
//----------------------------------------
180+
// STM32 firmware write
181+
//----------------------------------------
182+
ssize_t dfuStm32Write(DEVICE_FIRMWARE_CTX * ctx,
183+
const uint8_t * buffer,
184+
size_t bytesToWrite)
185+
{
186+
bool ack;
187+
uint32_t addr;
188+
uint8_t addressBytes[5];
189+
uint8_t * buf;
190+
ssize_t bytesWritten;
191+
uint8_t checksum;
192+
uint8_t data;
193+
int i;
194+
size_t totalBytes;
195+
uint8_t * writeBuffer;
196+
const uint8_t writeMemoryCmd[] =
197+
{
198+
0x31,
199+
0xCE // Checksum for 0x31
200+
};
201+
202+
do
203+
{
204+
// Write Memory Command + checksum
205+
writeBuffer = ctx->_writeBuffer;
206+
if (dfuStm32SendData(ctx,
207+
writeMemoryCmd,
208+
sizeof(writeMemoryCmd),
209+
"Write memory") != sizeof(writeMemoryCmd))
210+
{
211+
systemPrintf("ERROR: Failed to send write memory command!\r\n");
212+
break;
213+
}
214+
ack = dfuStm32WaitForAck(ctx);
215+
if (ack == false)
216+
{
217+
systemPrintf("ERROR: Failed to receive ACK for write memory command!\r\n");
218+
break;
219+
}
220+
221+
// Address + checksum
222+
addr = 0x08000000 + ctx->_bytesWritten;
223+
addressBytes[0] = (uint8_t)(addr >> 24);
224+
addressBytes[1] = (uint8_t)(addr >> 16);
225+
addressBytes[2] = (uint8_t)(addr >> 8);
226+
addressBytes[3] = (uint8_t)addr;
227+
addressBytes[4] = addressBytes[0] ^ addressBytes[1]
228+
^ addressBytes[2] ^ addressBytes[3];
229+
if (dfuStm32SendData(ctx,
230+
addressBytes,
231+
sizeof(addressBytes),
232+
"Address") != sizeof(addressBytes))
233+
{
234+
systemPrintf("ERROR: Failed to send addres!\r\n");
235+
break;
236+
}
237+
ack = dfuStm32WaitForAck(ctx);
238+
if (ack == false)
239+
{
240+
systemPrintf("ERROR: Failed to receive ACK for address!\r\n");
241+
break;
242+
}
243+
244+
// STM32 firmware packet with checksum
245+
// .---------------------+------------...------------+----------.
246+
// | Number of bytes - 1 | 1 - 256 bytes of firmware | checksum |
247+
// '---------------------+------------...------------+----------'
248+
//
249+
buf = ctx->_writeBuffer;
250+
251+
// Packet length - 1
252+
checksum = DFU_STM32_MAX_PAYLOAD_SIZE - 1;
253+
*buf++ = checksum;
254+
255+
// Firmware data
256+
for (i = 0; i < bytesToWrite; i++)
257+
{
258+
data = *buffer++;
259+
*buf++ = data;
260+
checksum ^= data;
261+
}
262+
263+
// Fill remaining space in packet with erased byte contents
264+
data = 0xff;
265+
for (; i < DFU_STM32_MAX_PAYLOAD_SIZE; i++)
266+
{
267+
*buf++ = data;
268+
checksum ^= data;
269+
}
270+
271+
// Checksum
272+
*buf++ = checksum;
273+
274+
// Verify the buffer size
275+
totalBytes = buf - ctx->_writeBuffer;
276+
if (totalBytes > DFU_STM32_BYTES)
277+
{
278+
systemPrintf("ERROR: writeBuffer too small, increase to %d bytes!\r\n", totalBytes);
279+
reportFatalError("writeBuffer too small!");
280+
}
281+
282+
if (totalBytes < DFU_STM32_BYTES)
283+
{
284+
systemPrintf("ERROR: Fill remaining space failed, totalBytes: %d!\r\n", totalBytes);
285+
reportFatalError("Fill remaining space failed!");
286+
}
287+
288+
// Send the firmware packet
289+
bytesWritten = dfuStm32SendData(ctx, ctx->_writeBuffer, totalBytes, "Firmware data");
290+
if (bytesWritten != totalBytes)
291+
{
292+
systemPrintf("ERROR: Failed to send firmware data, bytesToWrite: %d, totalBytes: %d, bytesWritten: %d\r\n",
293+
bytesToWrite, totalBytes, bytesWritten);
294+
break;
295+
}
296+
ack = dfuStm32WaitForAck(ctx);
297+
if (ack == false)
298+
{
299+
if (settings.debugFirmwareUpdate)
300+
{
301+
dumpBuffer(0, ctx->_writeBuffer, totalBytes);
302+
systemPrintf("ERROR: Failed to receive ACK for firmware data, bytesToWrite: %d, totalBytes: %d!\r\n", bytesToWrite, totalBytes);
303+
}
304+
break;
305+
}
306+
return bytesToWrite;
307+
} while (0);
308+
if (settings.debugFirmwareUpdate)
309+
{
310+
systemPrintf("bytesWritten: %d, bytesRemaining: %d, bytesToWrite: %d\r\n", ctx->_bytesWritten,
311+
ctx->_fileBytes - ctx->_bytesWritten, bytesToWrite);
312+
}
313+
return 0;
314+
}

0 commit comments

Comments
 (0)