Skip to content

Commit a0570d1

Browse files
committed
Update README to go over serial update demo
1 parent 9b05b03 commit a0570d1

File tree

3 files changed

+94
-2
lines changed

3 files changed

+94
-2
lines changed

README.md

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Since the Mbed-OS mcuboot port uses Mbed's `BlockDevice` API, there is a lot of
4343

4444
The Mbed-OS mcuboot port also has an additional function that the application can define if needed: `void mbed_mcuboot_user_init(void)`. This is provided as a `weak` symbol so the application can perform any necessary initialization before the rest of the boot process begins.
4545

46-
## Binary Signing
46+
## Binary Signing and Running the Demo
4747

4848
It is beneficial to first install mcuboot's imgtool python command line tool:
4949

@@ -94,3 +94,89 @@ Explanation of each option:
9494
- `-S 901120`: this specifies the maximum size of the application ("slot size"). It **must** be the same as the value specified in the **main application's** `target.mbed_app_size` configuration (0xDC000 = 901120)
9595

9696
6.) Flash your target with both the mcuboot bootloader application and the signed main application
97+
98+
## Serial Bootloader Demo Application
99+
100+
This demo optionally includes a serial bootloader demo to reprogram the target using a simple serial protocol.
101+
102+
**Please note:** This serial bootloader is rather slow and has not been optimized for speed at this point. This speed issue is mainly due to Mbed's existing serial implementation that processes UART data byte-by-byte. The python serial loader script has a 1ms (in reality it's probably longer) delay between sending **each byte** of the update binary to ensure no data is dropped due to delays in Mbed's serial stack. A possible optimization in the future is to implement a protocol with a known/negotiated packet size and use the asynchronous serial API in Mbed to collect UART packets of that size in a more efficient and faster way.
103+
104+
**Also note:** This bootloader was developed on and tested using the `nRF52840_DK` and `EP_AGORA` targets
105+
106+
### Enabling the Serial Bootloader
107+
108+
To enable the serial bootloader, modify the `mbed_app.json` configuration as shown below:
109+
110+
```
111+
"config": {
112+
"serial-bootloader-build": {
113+
"help": "Build bootloader with serial update support",
114+
"value": 1
115+
}
116+
}
117+
```
118+
119+
When this configuration option is set to 1, the serial bootloader code will be compiled and run during the `mbed_mcuboot_user_init` hook.
120+
121+
### Operation Overview
122+
123+
Upon boot, the bootloader checks the target's `BTN1` pin to see if it is pulled low (button pressed). If it is, this starts a 5 second timeout where the bootloader waits for a 0-byte over the STDIO serial port. If no 0-byte is received within 5 seconds, the bootloader continues as usual and must be reset with `BTN1` pressed to enter serial bootloader mode again.
124+
125+
If the bootloader receives a 0-byte within the timeout period, it will write a `1` to the serial port to tell the loader script that it's there. The bootloader then prepares the update flash partition by erasing it. Once the erase operation is complete, the bootloader signals to the serial loader script that it is ready to receive data. The serial loader script reads the update binary in chunks and frames each binary chunk with a metadata header of the following format:
126+
127+
```
128+
typedef struct {
129+
uint16_t crc16; /** CRC16 of entire packet */
130+
uint16_t sequence_num; /** Sequence number of the OTA update, the special value 0xFFFF means the transfer is over. Wraps at 0xFFFE */
131+
uint16_t payload_size; /** Payload size of this packet in bytes */
132+
} packet_header_t;
133+
```
134+
135+
The header includes a CRC16 of the entire packet (including the other parts of the header), a 16-bit sequence number for synchronization, and a 16-bit payload size indicating how many payload bytes follow the header.
136+
137+
This framed packet is then encoded using COBS-R for transport over the serial link. This allows each packet to be delimited by a 0-byte.
138+
139+
When the bootloader receives a 0-byte, it decodes the collected buffer, checks the CRC16 and then programs the binary payload to the update partition in flash.
140+
141+
At the end of the binary, the serial loader sends a special packet with a sequence number of `0xFFFF` to indicate the transfer is complete. The bootloader calls the mcuboot API function: `boot_set_pending`. This sets flags to tell mcuboot the update partition has an update candidate available.
142+
143+
The bootloader then continues on to mcuboot subroutines. mcuboot will then see the update binary in the update partition, check its validity (through digital signature verification), and load it as appropriate.
144+
145+
The final step of the update process is for the updated application to mark itself as "OK". This is accomplished by calling the mcuboot API function: `boot_set_confirmed`. This prevents the update from being reverted on the next system reset.
146+
147+
148+
### Running the Serial Bootloader Demo
149+
150+
To run the serial bootloader demo, you must have first completed the "Binary Signing and Running the Demo" section above and have mcuboot and the blinky demo application running on your target.
151+
152+
To build the update version of the blinky application, you can compile the blinky demo application with the following command:
153+
154+
```
155+
mbed comile -DMCUBOOT_UPDATE
156+
```
157+
158+
This adds a preprocessor definition, `MCUBOOT_UPDATE`, which changes the blinked LED from `LED1` to `LED2` and increases the blinking rate from 1 second to 250 milliseconds.
159+
160+
Once the build is complete, you must sign the update and convert the hex file to a binary. Use the following command below:
161+
162+
```
163+
imgtool sign -k ../mbed-mcuboot-demo/signing-keys.pem --align 4 -v 1.2.4 --header-size 4096 --pad-header -S 61440 -M 256 --pad BUILD/NRF52840_DK/GCC_ARM/mbed-mcuboot-blinky.hex signed-update.hex
164+
```
165+
166+
In this case, the `-S` (slot size) option should be just enough to fit the application, header (4kB size in this case) and some metadata. The slot size must be a multiple of your target's erase sector size (4kB in this case) so round up to the nearest multiple.
167+
168+
The `-v` option bumps the version in the mcuboot header to `1.2.4`.
169+
170+
To convert the signed hex file to a binary that is compatible with the serial loader script, use the following command (only if you're using the GCC ARM toolchain):
171+
172+
```
173+
arm-none-eabi-objcopy -I ihex -O binary signed-update.hex signed-update.bin
174+
```
175+
176+
Then, to upload the signed update binary, perform the following steps:
177+
178+
1. Press and hold the target's BTN1 while resetting it
179+
2. Within 5 seconds, execute the following: `python serial_loader.py signed-update.bin /dev/ttyACM0`. Make sure to change `/dev/ttyACM0` to the serial port your target is on.
180+
3. Wait for the update operation to be completed.
181+
182+
Once complete, the application should now be the updated version and should be blinking LED2 at a much faster rate than before.

mbed_app.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
22
"requires": ["bare-metal", "mbedtls", "mcuboot", "flashiap-block-device", "spif-driver", "qspif", "mbed-trace", "serialcobs"],
3+
"config": {
4+
"serial-bootloader-build": {
5+
"help": "Build bootloader with serial update support",
6+
"value": 0
7+
}
8+
},
39
"target_overrides": {
410
"*": {
511
"target.restrict_size": "0x20000",

mcuboot.lib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
https://github.com/AGlass0fMilk/mcuboot/#9adc5c15e05691c8bcfc7d617bbc67b5e9ef57ba
1+
https://github.com/AGlass0fMilk/mcuboot/#aff9bd34ceb8e4fb1f0697045e2f09764e738844

0 commit comments

Comments
 (0)