Skip to content

Commit 9b05b03

Browse files
committed
Working serial bootloader demo
1 parent 4c5b08f commit 9b05b03

File tree

5 files changed

+64
-21
lines changed

5 files changed

+64
-21
lines changed

SerialOTA.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SerialOTA::ota_error_t SerialOTA::begin(void) {
2020
uint32_t bytes_collected = 0;
2121
packet_header_t header = { 0 };
2222
uint32_t crc;
23+
uint8_t tx_byte = 0;
2324

2425
// Initialize the secondary block device
2526
_update_bd.init();
@@ -29,8 +30,9 @@ SerialOTA::ota_error_t SerialOTA::begin(void) {
2930

3031
_serial.set_blocking(true);
3132

32-
// Tell the serial bootloader host application to begin :)
33-
_serial.write("GO", 2);
33+
// Tell the serial bootloader host application to begin
34+
tx_byte = 2;
35+
_serial.write(&tx_byte, 1);
3436

3537
while(true) {
3638

@@ -40,13 +42,8 @@ SerialOTA::ota_error_t SerialOTA::begin(void) {
4042
// The first bytes will be the header
4143
memcpy(&header, _payload_buffer, sizeof(packet_header_t));
4244

43-
// If the sequence number is OTA_DONE_SEQ_NUM we're done!
44-
if(header.sequence_num == OTA_DONE_SEQ_NUM) {
45-
return OTA_SUCCESS;
46-
}
47-
4845
// Check the sequence number
49-
if(_current_seq != header.sequence_num) {
46+
if((_current_seq != header.sequence_num) && (header.sequence_num != OTA_DONE_SEQ_NUM)) {
5047
return OTA_OUT_OF_SYNC;
5148
}
5249

@@ -73,5 +70,16 @@ SerialOTA::ota_error_t SerialOTA::begin(void) {
7370
_current_seq++;
7471
bytes_collected += header.payload_size;
7572

73+
// If the sequence number is OTA_DONE_SEQ_NUM we're done!
74+
if(header.sequence_num == OTA_DONE_SEQ_NUM) {
75+
return OTA_SUCCESS;
76+
}
77+
78+
// Tell the loader script to continue
79+
tx_byte = 0;
80+
_serial.write(&tx_byte, 1);
81+
7682
}
83+
84+
return OTA_SUCCESS;
7785
}

default_bd.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "BlockDevice.h"
99

10+
#include "SlicingBlockDevice.h"
11+
1012
#if COMPONENT_SPIF
1113
#include "SPIFBlockDevice.h"
1214
#endif
@@ -72,7 +74,12 @@ BlockDevice *BlockDevice::get_default_instance()
7274
* You can override this function to suit your hardware/memory configuration
7375
* By default it simply returns what is returned by BlockDevice::get_default_instance();
7476
*/
75-
//mbed::BlockDevice* get_secondary_bd(void) {
76-
// return mbed::BlockDevice::get_default_instance();
77-
//}
77+
mbed::BlockDevice* get_secondary_bd(void) {
78+
// In this case, our flash is much larger than a single image so
79+
// slice it into a smaller size, 1MB at the beginning
80+
81+
mbed::BlockDevice* default_bd = mbed::BlockDevice::get_default_instance();
82+
static mbed::SlicingBlockDevice sliced_bd(default_bd, 0x0, 0xDD000);
83+
return &sliced_bd;
84+
}
7885

mbed_app.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
"target.features_add": ["STORAGE"],
1111
"target.features_remove": ["CRYPTOCELL310"],
1212
"target.macros_remove": ["MBEDTLS_CONFIG_HW_SUPPORT"],
13-
"target.components_add": ["QSPIF", "FLASHIAP"]
13+
"target.components_add": ["QSPIF", "FLASHIAP"],
14+
"mcuboot.max-img-sectors": 256,
15+
"qspif.QSPI_MIN_PROG_SIZE": 4
1416
},
1517
"EP_AGORA": {
1618
"target.device_has_remove": ["ITM"],
1719
"target.features_add": ["STORAGE"],
1820
"target.features_remove": ["CRYPTOCELL310"],
1921
"target.macros_remove": ["MBEDTLS_CONFIG_HW_SUPPORT"],
2022
"target.components_remove": ["QSPIF"],
21-
"target.components_add": ["SPIF", "FLASHIAP"]
23+
"target.components_add": ["SPIF", "FLASHIAP"],
24+
"mcuboot.max-img-sectors": 256
2225
}
2326
}
2427
}

serial_loader.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import serial
33
import argparse
44
import struct
5-
from crc16 import crc16xmodem as crc16
5+
from crccheck.crc import Crc16CcittFalse
6+
from time import sleep
7+
import os
68

79
CHUNK_SIZE = 128
810

@@ -14,6 +16,7 @@
1416
# Payload Size (2-bytes)
1517
HEADER_FORMAT = "<HH".format(CHUNK_SIZE)
1618

19+
crc16 = Crc16CcittFalse.calc
1720

1821
def read_in_chunks(file_object, chunk_size=256):
1922
while True:
@@ -33,6 +36,8 @@ def main():
3336
# Create the OTA serial
3437
ser = serial.Serial(args.port, 115200, timeout=0.1)
3538

39+
binary_size = os.path.getsize(args.binary)
40+
3641
# Open the binary
3742
with open(args.binary, 'rb') as f:
3843

@@ -57,24 +62,30 @@ def main():
5762

5863
sequence_num = 0
5964
for chunk in read_in_chunks(f, CHUNK_SIZE):
60-
61-
if len(chunk) != CHUNK_SIZE:
65+
bytes_written_after = sequence_num * (CHUNK_SIZE+1)
66+
if len(chunk) != CHUNK_SIZE or bytes_written_after >= binary_size:
6267
sequence_num = 0xFFFF
6368

6469
# Pack the header
6570
tx_buf = struct.pack(HEADER_FORMAT, sequence_num, len(chunk)) + chunk
6671

6772
# Calculate the CRC16 of the chunk and the header info
73+
#print(tx_buf.hex())
74+
6875
crc = crc16(bytes(tx_buf))
6976
print("Sending chunk: crc({}), seq num({}), size({})".format(crc, sequence_num, len(chunk)))
7077

7178
tx_buf = struct.pack("<H", crc) + tx_buf
7279

7380
# Encode with COBS
7481
tx_cobs = cobsr.encode(tx_buf) + bytes([0])
75-
print(type(tx_cobs))
76-
ser.write(tx_cobs)
77-
print(tx_cobs.hex())
82+
#print(type(tx_cobs))
83+
#ser.write(tx_cobs)
84+
#print(tx_cobs.hex())
85+
86+
for b in tx_cobs:
87+
ser.write(bytes([b]))
88+
sleep(0.001)
7889

7990
while(True):
8091
# Wait until the bootloader is ready
@@ -85,5 +96,12 @@ def main():
8596

8697
sequence_num = sequence_num + 1
8798

99+
100+
ser.close()
101+
ser = serial.Serial(args.port, 9600)
102+
while(True):
103+
print(ser.readline())
104+
105+
88106
if __name__ == '__main__':
89-
main()
107+
main()

user_main.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
#include "drivers/DigitalIn.h"
2929
#include "SerialCOBS.h"
3030

31+
#include "SlicingBlockDevice.h"
32+
33+
#include "bootutil.h"
34+
3135
#define BOOT_WAIT_TIMEOUT 5s
3236

3337
using namespace std::chrono;
@@ -49,6 +53,7 @@ void mbed_mcuboot_user_init(void) {
4953

5054
// Set up the serial interface
5155
mbed::BufferedSerial pc(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_APP_SERIAL_BOOTLOADER_BAUD);
56+
//mbed::BufferedSerial pc(P0_3, P0_4, MBED_CONF_APP_SERIAL_BOOTLOADER_BAUD);
5257

5358
// Wait for a specified timeout until just booting
5459
rtos::Kernel::Clock::duration time_waited = 0ms;
@@ -87,7 +92,9 @@ void mbed_mcuboot_user_init(void) {
8792

8893
SerialOTA::ota_error_t error = ota.begin();
8994

90-
// TODO - check error?
95+
if(error == SerialOTA::OTA_SUCCESS) {
96+
boot_set_pending(false);
97+
}
9198

9299
#endif // MBED_CONF_APP_SERIAL_BOOTLOADER_ENABLE
93100

0 commit comments

Comments
 (0)