lynxis lazus has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-asf4-dfu/+/42273?usp=email )
Change subject: WIP: dfu-download: flash the first block into manifest phase
......................................................................
WIP: dfu-download: flash the first block into manifest phase
To prevent half flashed applications, erase the first page
when dfu downloading starts and save the first block for later.
In manifest stage, flash the first block.
If the first 4 byte are 0xffffffff, the board won't boot
into application and go into the dfu bootloader.
TODO: Needs testing.
Change-Id: I894f3ee71587ccb287e92d7025039954991c631f
---
M usb/class/dfu/device/dfudf.c
M usb/class/dfu/device/dfudf.h
M usb_start.c
3 files changed, 51 insertions(+), 9 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-asf4-dfu refs/changes/73/42273/1
diff --git a/usb/class/dfu/device/dfudf.c b/usb/class/dfu/device/dfudf.c
index bca0a6b..2af1998 100644
--- a/usb/class/dfu/device/dfudf.c
+++ b/usb/class/dfu/device/dfudf.c
@@ -45,6 +45,11 @@
/* flashed the last given block */
uint8_t dfu_download_data[512];
volatile uint16_t dfu_download_length = 0;
+
+/* buffer the first block, to write it last */
+uint8_t dfu_download_data_first[512];
+uint16_t dfu_download_data_first_length = 0;
+
volatile size_t dfu_download_offset = 0;
/* only when flash done is true, flash rc is valid */
diff --git a/usb/class/dfu/device/dfudf.h b/usb/class/dfu/device/dfudf.h
index b9db46f..bbfb58b 100644
--- a/usb/class/dfu/device/dfudf.h
+++ b/usb/class/dfu/device/dfudf.h
@@ -52,6 +52,9 @@
/** Offset of where the downloaded data should be flashed in bytes */
extern volatile size_t dfu_download_offset;
+extern uint8_t dfu_download_data_first[512];
+extern uint16_t dfu_download_length_first;
+
/** when flash done is true, flash status is valid */
extern volatile bool dfu_flash_done;
/** Result of the last blocked flashed. */
diff --git a/usb_start.c b/usb_start.c
index e9dce79..6de384c 100644
--- a/usb_start.c
+++ b/usb_start.c
@@ -156,6 +156,7 @@
LED_SYSTEM_on(); // switch LED on to indicate USB DFU stack is ready
uint32_t application_start_address = BL_SIZE_BYTE;
+ int rc;
ASSERT(application_start_address > 0);
while (true) { // main DFU infinite loop
@@ -170,9 +171,21 @@
LED_SYSTEM_off(); // switch LED off to indicate we are
flashing
if (dfu_download_length > 0) { // there is some data to
be flashed
- int32_t rc = flash_write(&FLASH_0,
application_start_address + dfu_download_offset,
- dfu_download_data,
- dfu_download_length);
// write downloaded data chunk to flash
+ /* The first block will be only erased, to
ensure the
+ * full firmware has been written.
+ * In case of a power loss, the bootloader
won't boot applications
+ * if the first 4 byte are 0xffffffff
+ */
+ if (dfu_download_offset == 0) {
+ dfu_download_length_first =
dfu_download_length;
+ memcpy(dfu_download_data_first,
dfu_download_data, dfu_download_length);
+ /* erasing the first page is enough,
flash_write will keep care of the remaining ones */
+ rc = flash_erase(&FLASH_0,
application_start_address, 1);
+ } else {
+ rc = flash_write(&FLASH_0,
application_start_address + dfu_download_offset,
+ dfu_download_data,
dfu_download_length);
+ }
+
CRITICAL_SECTION_ENTER();
switch (rc) {
case ERR_NONE:
@@ -194,16 +207,37 @@
}
LED_SYSTEM_on(); // switch LED on to indicate USB DFU
can resume
break;
- case USB_DFU_STATE_DFU_MANIFEST: // we can start manifestation
(finish flashing)
- // in theory every DFU files should have a suffix to
with a CRC to check the data
- // in practice most downloaded files are just the raw
binary with DFU suffix
+ case USB_DFU_STATE_DFU_MANIFEST:
+ /* finish flashing by writing the first block */
+ rc = flash_write(&FLASH_0, application_start_address,
+ dfu_download_data_first,
dfu_download_length_first);
+ switch (rc) {
+ case ERR_NONE:
+ break;
+ case ERR_BAD_ADDRESS:
+ dfu_flash_status = USB_DFU_STATUS_ERR_ADDRESS;
+ break;
+ case ERR_DENIED:
+ dfu_flash_status = USB_DFU_STATUS_ERR_WRITE;
+ break;
+ default:
+ dfu_flash_status = USB_DFU_STATUS_ERR_PROG;
+ break;
+ }
+
+ /* try to clear it, to ensure it doesn't boot into a
broken application */
+ if (dfu_flash_status != ERR_NONE) {
+ flash_erase(&FLASH_0,
application_start_address, 1);
+ }
+
CRITICAL_SECTION_ENTER();
dfu_manifestation_complete = true; // we completed
flashing and all checks
- if (usb_dfu_func_desc->bmAttributes &
USB_DFU_ATTRIBUTES_MANIFEST_TOLERANT) {
+ if (dfu_flash_status != ERR_NONE)
+ dfu_state = USB_DFU_STATE_DFU_ERROR;
+ else if (usb_dfu_func_desc->bmAttributes &
USB_DFU_ATTRIBUTES_MANIFEST_TOLERANT)
dfu_state = USB_DFU_STATE_DFU_MANIFEST_SYNC;
- } else {
+ else
dfu_state =
USB_DFU_STATE_DFU_MANIFEST_WAIT_RESET;
- }
CRITICAL_SECTION_LEAVE();
break;
case USB_DFU_STATE_DFU_MANIFEST_WAIT_RESET:
--
To view, visit https://gerrit.osmocom.org/c/osmo-asf4-dfu/+/42273?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-asf4-dfu
Gerrit-Branch: master
Gerrit-Change-Id: I894f3ee71587ccb287e92d7025039954991c631f
Gerrit-Change-Number: 42273
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <[email protected]>