From dfa652604c82320e719113c66c9fd4979d50d217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Wed, 9 Jan 2019 14:48:20 +0100 Subject: use reserved bootloader get application start the reserved bootloader size is set in the NVM user configuration and allows to know the application start address (e.g. after the bootloader) Change-Id: I9dda27d6401caabb4a6470aa3fe9691f63097136 --- usb/class/dfu/device/dfudf.c | 6 +++--- usb/class/dfu/device/dfudf.h | 4 ++-- usb_start.c | 22 +++++++++++++--------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/usb/class/dfu/device/dfudf.c b/usb/class/dfu/device/dfudf.c index 41e235b..8232979 100644 --- a/usb/class/dfu/device/dfudf.c +++ b/usb/class/dfu/device/dfudf.c @@ -44,7 +44,7 @@ enum usb_dfu_status dfu_status = USB_DFU_STATUS_OK; uint8_t dfu_download_data[512]; uint16_t dfu_download_length = 0; -size_t dfu_download_progress = 0; +size_t dfu_download_offset = 0; bool dfu_manifestation_complete = false; /** @@ -215,7 +215,7 @@ static int32_t dfudf_out_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stag to_return = usbdc_xfer(ep, NULL, 0, false); // send ACK break; case USB_DFU_ABORT: // abort current operation - dfu_download_progress = 0; // reset download progress + dfu_download_offset = 0; // reset download progress dfu_state = USB_DFU_STATE_DFU_IDLE; // put back in idle state (nothing else to do) to_return = usbdc_xfer(ep, NULL, 0, false); // send ACK break; @@ -246,7 +246,7 @@ static int32_t dfudf_out_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stag if (USB_SETUP_STAGE == stage) { // there will be data to be flash to_return = usbdc_xfer(ep, dfu_download_data, req->wLength, false); // send ack to the setup request to get the data } else { // now there is data to be flashed - dfu_download_progress = req->wValue * sizeof(dfu_download_data); // remember which block to flash + dfu_download_offset = req->wValue * sizeof(dfu_download_data); // remember which block to flash dfu_download_length = req->wLength; // remember the data size to be flash dfu_state = USB_DFU_STATE_DFU_DNLOAD_SYNC; // go to sync state to_return = usbdc_xfer(ep, NULL, 0, false); // ACK the data diff --git a/usb/class/dfu/device/dfudf.h b/usb/class/dfu/device/dfudf.h index a19b569..cee5845 100644 --- a/usb/class/dfu/device/dfudf.h +++ b/usb/class/dfu/device/dfudf.h @@ -49,8 +49,8 @@ extern enum usb_dfu_status dfu_status; extern uint8_t dfu_download_data[512]; /** Length of downloaded data in bytes */ extern uint16_t dfu_download_length; -/** Progress of the already downloaded data in bytes */ -extern size_t dfu_download_progress; +/** Offset of where the downloaded data should be flashed in bytes */ +extern size_t dfu_download_offset; /** If manifestation (firmware flash and check) is complete */ extern bool dfu_manifestation_complete; diff --git a/usb_start.c b/usb_start.c index 0ce8aba..7503094 100644 --- a/usb_start.c +++ b/usb_start.c @@ -45,14 +45,6 @@ static const usb_dfu_func_desc_t* usb_dfu_func_desc = (usb_dfu_func_desc_t*)&usb /** Ctrl endpoint buffer */ static uint8_t ctrl_buffer[64]; -/** Application address in the flash - ( - * It comes after the bootloader. - * The NVMCTRL allows to reserve space at the beginning of the flash for the bootloader, but only in multiples of 8192 bytes. - * The binary just with the USB stack already uses 8 kB, we reserve 16 kB for the bootloader (giving use a bit of margin for future fixes). - */ -#define APPLICATION_ADDR (8192*2) - /** * \brief USB DFU Init */ @@ -89,12 +81,24 @@ void usb_dfu(void) { while (!dfudf_is_enabled()); // wait for DFU to be installed gpio_set_pin_level(LED_SYSTEM, false); // switch LED on to indicate USB DFU stack is ready + + uint32_t application_start = hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw); // read BOOTPROT setting to get the bootloader size + ASSERT(application_start <= 15); + application_start = (15 - application_start) * 8192; // calculate bootloader size to know where we should write the application firmware + while (0 == application_start) { // no space has been reserved for the bootloader + // blink the LED to tell the user we don't know where the application starts + gpio_set_pin_level(LED_SYSTEM, false); + delay_ms(500); + gpio_set_pin_level(LED_SYSTEM, true); + delay_ms(500); + } + while (true) { // main DFU infinite loop // run the second part of the USB DFU state machine handling non-USB aspects if (USB_DFU_STATE_DFU_DNLOAD_SYNC == dfu_state || USB_DFU_STATE_DFU_DNBUSY == dfu_state) { // there is some data to be flashed gpio_set_pin_level(LED_SYSTEM, true); // 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_ADDR + dfu_download_progress, dfu_download_data, dfu_download_length); // write downloaded data chunk to flash + int32_t rc = flash_write(&FLASH_0, application_start + dfu_download_offset, dfu_download_data, dfu_download_length); // write downloaded data chunk to flash if (ERR_NONE == rc) { dfu_state = USB_DFU_STATE_DFU_DNLOAD_IDLE; // indicate flashing this block has been completed } else { // there has been a programming error -- cgit v1.2.3