From 83490ccb2b3f180b23874c5d2b1349fc4099cbfc Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Thu, 23 Jun 2022 09:54:48 -0700 Subject: [PATCH 1/8] adds a pin for DFU activation. If this is the same pin as FRST, dfu activation takes precedence. (Some solutions don't need FRST for BLE OTA updates, and those that do can define FRST as a separate pin) --- src/boards/boards.c | 23 ++++++-------- src/boards/boards.h | 31 +++++++++++++++++-- src/boards/feather_nrf52840_express/board.h | 4 +++ src/main.c | 34 ++++++++++++++++----- 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index 7a48259a..2e85b5ab 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -44,25 +44,19 @@ #endif //------------- IMPLEMENTATION -------------// -void button_init(uint32_t pin) +void button_init(uint32_t pin, uint32_t pull) { - if ( BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN ) - { - nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_HIGH); - } - else - { - nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_LOW); - } + nrf_gpio_cfg_sense_input(pin, pull, pull == NRF_GPIO_PIN_PULLDOWN ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW); } -bool button_pressed(uint32_t pin) +bool button_pressed(uint32_t pin, uint32_t pull) { - uint32_t const active_state = (BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN ? 1 : 0); + uint32_t const active_state = (pull == NRF_GPIO_PIN_PULLDOWN ? 1 : 0); return nrf_gpio_pin_read(pin) == active_state; } void board_init(void) + { // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; @@ -71,8 +65,11 @@ void board_init(void) NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC; NRF_CLOCK->TASKS_LFCLKSTART = 1UL; - button_init(BUTTON_DFU); - button_init(BUTTON_FRESET); + button_init(BUTTON_DFU, BUTTON_DFU_PULL); + button_init(BUTTON_FRESET, BUTTON_DFU_PULL); +#if defined(PIN_DFU_ACTIVATE) + button_init(PIN_DFU_ACTIVATE, PIN_DFU_ACTIVATE_PULL); +#endif NRFX_DELAY_US(100); // wait for the pin state is stable #if LEDS_NUMBER > 0 diff --git a/src/boards/boards.h b/src/boards/boards.h index 8aa0ece6..ee4d3f2d 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -45,6 +45,33 @@ #define BUTTON_FRESET BUTTON_2 #endif +#ifndef BUTTON_1_PULL +#define BUTTON_1_PULL BUTTON_PULL +#endif + +#ifndef BUTTON_2_PULL +#define BUTTON_2_PULL BUTTON_PULL +#endif + +#ifndef BUTTON_DFU_PULL +#define BUTTON_DFU_PULL BUTTON_1_PULL +#endif + +#ifndef BUTTON_RESET_PULL +#define BUTTON_RESET_PULL BUTTON_2_PULL +#endif + +#if defined(PIN_DFU_ACTIVATE) != defined(PIN_DFU_ACTIVATE_PULL) +#error "both PIN_DFU_ACTIVATE and PIN_DFU_ACTIVATE_PULL should be defined to use an additional pin for DFU activation." +#endif + +#if defined(PIN_DFU_ACTIVATE) && defined(PIN_DFU_ACTIVATE_PULL) +#define PIN_DFU_ACTIVATE_PRESENT 1 +#pragma message "board supports DFU activate pin" +#else +#define PIN_DFU_ACTIVATE_PRESENT 0 +#endif + // The primary LED is usually Red but not in all cases. #define LED_PRIMARY 0 // The secondary LED, when available, is usually blue. @@ -109,8 +136,8 @@ void led_tick(void); #error "At least two buttons required in the BSP (see 'BUTTONS_NUMBER')" #endif -void button_init(uint32_t pin); -bool button_pressed(uint32_t pin); +void button_init(uint32_t pin, uint32_t pull); +bool button_pressed(uint32_t pin, uint32_t pull); bool is_ota(void); diff --git a/src/boards/feather_nrf52840_express/board.h b/src/boards/feather_nrf52840_express/board.h index 2477ea4e..b5346015 100644 --- a/src/boards/feather_nrf52840_express/board.h +++ b/src/boards/feather_nrf52840_express/board.h @@ -47,6 +47,10 @@ #define BUTTON_2 _PINNUM(0, 10) #define BUTTON_PULL NRF_GPIO_PIN_PULLUP +// use the same pin as BUTTON_2/NRST which disables the NRST functionality +#define PIN_DFU_ACTIVATE BUTTON_2 +#define PIN_DFU_ACTIVATE_PULL NRF_GPIO_PIN_PULLDOWN + //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ diff --git a/src/main.c b/src/main.c index 8cbe93f1..ab8255da 100644 --- a/src/main.c +++ b/src/main.c @@ -251,16 +251,36 @@ static void check_dfu_mode(void) // Clear GPREGRET if it is our values if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; - // skip dfu entirely - if (dfu_skip) return; + // dfu activation pin for external control of DFU + bool dfu_activate = false; + bool dfu_activate_present = false; + bool frst_skip = false; + +#if PIN_DFU_ACTIVATE_PRESENT + dfu_activate = button_pressed(PIN_DFU_ACTIVATE, PIN_DFU_ACTIVATE_PULL); + dfu_activate_present = true; + // when the FRST button is defined the same as the DFU activation line, FRST is not used. + frst_skip = (PIN_DFU_ACTIVATE == BUTTON_FRESET); + #pragma message "FRST is overridden by the DFU activate setting" +#endif + + dfu_start = dfu_start || dfu_activate; - /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ - // DFU button pressed - dfu_start = dfu_start || button_pressed(BUTTON_DFU); + // DFU activation via the designated pin takes precedence + if (!dfu_activate_present || !dfu_activate) { + // skip dfu entirely + if (dfu_skip) return; - // DFU + FRESET are pressed --> OTA - _ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ; + /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ + // DFU button pressed + dfu_start = dfu_start || button_pressed(BUTTON_DFU, BUTTON_DFU_PULL); + // DFU + FRESET are pressed --> OTA + if (!frst_skip) { // skip button sense if on the same pin as DFU activation + _ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU, BUTTON_DFU_PULL) && button_pressed(BUTTON_FRESET, BUTTON_RESET_PULL) ) ; + } + } + bool const valid_app = bootloader_app_is_valid(); bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP; From 3a047c0677d6cb259522230b3a36f80b35ee8da9 Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Wed, 6 Jul 2022 16:57:50 -0700 Subject: [PATCH 2/8] makes both USB CDC and UART comms available at runtime, with the latter being active when the DFU Activation pin is asserted --- Makefile | 7 ++- lib/sdk/components/libraries/hci/hci_slip.c | 61 ++++++++++++++++--- lib/sdk/components/libraries/hci/hci_slip.h | 20 +++++++ src/boards/boards.c | 31 +++++++--- src/boards/boards.h | 5 +- src/boards/feather_nrf52840_express/board.h | 9 +++ src/boards/feather_nrf52840_express/board.mk | 1 + src/main.c | 62 +++++++++++++++++--- src/nrfx_config.h | 6 +- 9 files changed, 169 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 9ea2c887..b3acfd12 100644 --- a/Makefile +++ b/Makefile @@ -164,8 +164,8 @@ C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.c C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c # UART or USB Serial -ifeq ($(MCU_SUB_VARIANT),nrf52) - +ifdef USE_USART +$(info nrF52 UART) C_SRC += $(SDK_PATH)/libraries/uart/app_uart.c C_SRC += $(SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c C_SRC += $(SDK_PATH)/drivers_nrf/common/nrf_drv_common.c @@ -174,7 +174,7 @@ IPATH += $(SDK11_PATH)/libraries/util IPATH += $(SDK_PATH)/drivers_nrf/common IPATH += $(SDK_PATH)/drivers_nrf/uart -else +# else # pinconfig is required for 840 for CF2 C_SRC += src/boards/$(BOARD)/pinconfig.c @@ -196,6 +196,7 @@ C_SRC += \ $(TUSB_PATH)/class/msc/msc_device.c \ $(TUSB_PATH)/tusb.c +# endif #------------------------------------------------------------------------------ diff --git a/lib/sdk/components/libraries/hci/hci_slip.c b/lib/sdk/components/libraries/hci/hci_slip.c index f7673f63..8dde8756 100644 --- a/lib/sdk/components/libraries/hci/hci_slip.c +++ b/lib/sdk/components/libraries/hci/hci_slip.c @@ -43,9 +43,22 @@ #include #include "app_uart.h" #include "nrf_error.h" +#include "board.h" + +#if USE_RUNTIME_SELECTION +static bool selectSerial = false; // use USB by default + +void useSerialTransport() { + selectSerial = true; +} + +bool usingSerialTransport() { + return selectSerial; +} +#endif // nRF has native usb peripheral -#ifdef NRF_USBD +#ifdef USE_USB #include "tusb.h" #endif @@ -122,17 +135,25 @@ static uint32_t send_tx_byte_end(void); */ uint32_t (*send_tx_byte) (void) = send_tx_byte_default; -#ifdef NRF_USBD + +#if USE_USB && !USE_RUNTIME_SELECTION static uint32_t serial_put(char ch) { return tud_cdc_write_char(ch) ? NRF_SUCCESS : NRF_ERROR_NO_MEM; } -#else +#elif USE_SERIAL && !USE_RUNTIME_SELECTION #define serial_put app_uart_put +#else + +static uint32_t serial_put(char ch) +{ + return selectSerial ? app_uart_put(ch) : (tud_cdc_write_char(ch) ? NRF_SUCCESS : NRF_ERROR_NO_MEM); +} + #endif static uint32_t send_tx_byte_end(void) @@ -350,9 +371,8 @@ static bool rx_buffer_overflowed(void) return false; } -#ifdef NRF_USBD - -static uint32_t slip_uart_open(void) +#if USE_USB +static uint32_t slip_uart_open_usb_cdc(void) { m_current_state = SLIP_READY; return NRF_SUCCESS; @@ -367,7 +387,9 @@ void tud_cdc_rx_cb(uint8_t port) } } -#else +#endif + +#if USE_SERIAL /** @brief Function for handling the UART module event. It parses events from the UART when * bytes are received/transmitted. @@ -390,7 +412,7 @@ static void slip_uart_eventhandler(app_uart_evt_t * uart_event) /** @brief Function for enabling the UART module when the SLIP layer is opened. */ -static uint32_t slip_uart_open(void) +static uint32_t slip_uart_open_serial(void) { uint32_t err_code; @@ -419,6 +441,27 @@ static uint32_t slip_uart_open(void) #endif +#if !USE_SERIAL && !USE_USB +#error at least one of USE_SERIAL and USE_USB must be enabled +#endif + +static uint32_t slip_uart_open(void) { + #if USE_RUNTIME_SELECTION + if (selectSerial) { + return slip_uart_open_serial(); + } + else { + return slip_uart_open_usb_cdc(); + } + #elif USE_USB + return slip_uart_open_serial(); + #else + return slip_uart_open_usb_cdc(); + #endif + +} + + uint32_t hci_slip_evt_handler_register(hci_slip_event_handler_t event_handler) { m_slip_event_handler = event_handler; @@ -447,7 +490,7 @@ uint32_t hci_slip_close() { m_current_state = SLIP_OFF; -#ifdef NRF_USBD +#if USE_USB return NRF_SUCCESS; #else uint32_t err_code = app_uart_close(); diff --git a/lib/sdk/components/libraries/hci/hci_slip.h b/lib/sdk/components/libraries/hci/hci_slip.h index 16040fb4..107ef134 100644 --- a/lib/sdk/components/libraries/hci/hci_slip.h +++ b/lib/sdk/components/libraries/hci/hci_slip.h @@ -59,11 +59,31 @@ #define HCI_SLIP_H__ #include +#include "boards.h" + +// NRF_USBD +#ifdef NRF_USBD +#define USE_USB 1 +#else +#define USE_USB 0 +#endif + +/** + * @brief Enable UART interface with DFU_ACTIVATION present for MCU to MCU transfers + */ +#define USE_SERIAL PIN_DFU_ACTIVATE_PRESENT +#define USE_RUNTIME_SELECTION (USE_USB && USE_SERIAL) + #ifdef __cplusplus extern "C" { #endif +#if USE_RUNTIME_SELECTION +void useSerialTransport(void); +bool usingSerialTransport(void); +#endif + /**@brief Event types from the SLIP Layer. */ typedef enum { diff --git a/src/boards/boards.c b/src/boards/boards.c index 2e85b5ab..b9f3dde7 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -66,7 +66,11 @@ void board_init(void) NRF_CLOCK->TASKS_LFCLKSTART = 1UL; button_init(BUTTON_DFU, BUTTON_DFU_PULL); - button_init(BUTTON_FRESET, BUTTON_DFU_PULL); +#if defined(PIN_DFU_ACTIVATE) +#if PIN_DFU_ACTIVATE!=BUTTON_FRESET + button_init(BUTTON_FRESET, BUTTON_FRESET_PULL); +#endif +#endif #if defined(PIN_DFU_ACTIVATE) button_init(PIN_DFU_ACTIVATE, PIN_DFU_ACTIVATE_PULL); #endif @@ -268,18 +272,31 @@ void led_state(uint32_t state) uint32_t temp_color = 0; switch (state) { case STATE_USB_MOUNTED: - new_rgb_color = 0x00ff00; + new_rgb_color = 0x00ff00; // green + primary_cycle_length = 3000; + break; + + case STATE_UART_ACTIVE: + new_rgb_color = 0x00ffff; // cyan primary_cycle_length = 3000; break; case STATE_BOOTLOADER_STARTED: + new_rgb_color = 0x000001; // red + primary_cycle_length = 300; + break; + case STATE_UART_TIMEOUT: + new_rgb_color = 0x202020; // grey + primary_cycle_length = 300; + break; + case STATE_USB_UNMOUNTED: - new_rgb_color = 0xff0000; + new_rgb_color = 0x200000; // dark red primary_cycle_length = 300; break; case STATE_WRITING_STARTED: - temp_color = 0xff0000; + temp_color = 0xffff00; // yellow primary_cycle_length = 100; break; @@ -289,7 +306,7 @@ void led_state(uint32_t state) break; case STATE_BLE_CONNECTED: - new_rgb_color = 0x0000ff; + new_rgb_color = 0xff00ff; // purple #ifdef LED_SECONDARY_PIN secondary_cycle_length = 3000; #else @@ -298,7 +315,7 @@ void led_state(uint32_t state) break; case STATE_BLE_DISCONNECTED: - new_rgb_color = 0xff00ff; + new_rgb_color = 0xff00ff; // purple #ifdef LED_SECONDARY_PIN secondary_cycle_length = 300; #else @@ -307,7 +324,7 @@ void led_state(uint32_t state) break; default: - break; + break; } uint8_t* final_color = NULL; new_rgb_color &= BOARD_RGB_BRIGHTNESS; diff --git a/src/boards/boards.h b/src/boards/boards.h index ee4d3f2d..5513f6d8 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -67,7 +67,6 @@ #if defined(PIN_DFU_ACTIVATE) && defined(PIN_DFU_ACTIVATE_PULL) #define PIN_DFU_ACTIVATE_PRESENT 1 -#pragma message "board supports DFU activate pin" #else #define PIN_DFU_ACTIVATE_PRESENT 0 #endif @@ -118,7 +117,9 @@ enum { STATE_WRITING_STARTED, STATE_WRITING_FINISHED, STATE_BLE_CONNECTED, - STATE_BLE_DISCONNECTED + STATE_BLE_DISCONNECTED, + STATE_UART_ACTIVE, + STATE_UART_TIMEOUT }; void led_pwm_init(uint32_t led_index, uint32_t led_pin); diff --git a/src/boards/feather_nrf52840_express/board.h b/src/boards/feather_nrf52840_express/board.h index b5346015..d7ab81c3 100644 --- a/src/boards/feather_nrf52840_express/board.h +++ b/src/boards/feather_nrf52840_express/board.h @@ -70,4 +70,13 @@ #define UF2_BOARD_ID "nRF52840-Feather-revD" #define UF2_INDEX_URL "https://www.adafruit.com/product/4062" +/*------------------------------------------------------------------*/ +/* UART + *------------------------------------------------------------------*/ +#define RX_PIN_NUMBER 24 +#define TX_PIN_NUMBER 25 +#define CTS_PIN_NUMBER 0 +#define RTS_PIN_NUMBER 0 +#define HWFC false + #endif // _FEATHER_NRF52840_H diff --git a/src/boards/feather_nrf52840_express/board.mk b/src/boards/feather_nrf52840_express/board.mk index 9d29ac69..7b69a77d 100644 --- a/src/boards/feather_nrf52840_express/board.mk +++ b/src/boards/feather_nrf52840_express/board.mk @@ -1 +1,2 @@ MCU_SUB_VARIANT = nrf52840 +USE_USART = 1 diff --git a/src/main.c b/src/main.c index ab8255da..4683e83d 100644 --- a/src/main.c +++ b/src/main.c @@ -67,21 +67,49 @@ #include "nrf_mbr.h" #include "pstorage.h" #include "nrfx_nvmc.h" +#include "hci_slip.h" - -#ifdef NRF_USBD +#if USE_USB #include "nrf_usbd.h" #include "tusb.h" void usb_init(bool cdc_only); void usb_teardown(void); -#else +#endif + +#if USE_SERIAL +#define uart_init(x) led_state(STATE_UART_ACTIVE) // mark nrf52832 as mounted +#define uart_teardown() +#endif -#define usb_init(x) led_state(STATE_USB_MOUNTED) // mark nrf52832 as mounted -#define usb_teardown() +void channel_init(bool cdc_only) { +#if USE_RUNTIME_SELECTION + if (usingSerialTransport()) { + uart_init(cdc_only); + } else { + usb_init(cdc_only); + } +#elif USE_USB + usb_cdc_init(cdc_only); +#elif USE_SERIAL + uart_init(cdc_only); +#endif +} +void channel_teardown(void) { +#if USE_RUNTIME_SELECTION + if (usingSerialTransport()) { + uart_teardown(); + } else { + usb_teardown(); + } +#elif USE_USB + usb_teardown(); +#else USE_SERIAL + uart_teardown(); #endif +} //--------------------------------------------------------------------+ // @@ -257,6 +285,8 @@ static void check_dfu_mode(void) bool frst_skip = false; #if PIN_DFU_ACTIVATE_PRESENT + NRFX_DELAY_US(50000); // wait for the pin state is stable + dfu_activate = button_pressed(PIN_DFU_ACTIVATE, PIN_DFU_ACTIVATE_PULL); dfu_activate_present = true; // when the FRST button is defined the same as the DFU activation line, FRST is not used. @@ -318,6 +348,18 @@ static void check_dfu_mode(void) (*dbl_reset_mem) = 0; } + NRFX_DELAY_US(500); // wait for the pin state is stable + + /* + * Enable UART for MCU to MCU transfers. + */ + if (dfu_activate) { + useSerialTransport(); + } + + NRFX_DELAY_US(500); // wait for the pin state is stable + + // Enter DFU mode accordingly to input if ( dfu_start || !valid_app ) { @@ -333,7 +375,8 @@ static void check_dfu_mode(void) else { led_state(STATE_USB_UNMOUNTED); - usb_init(serial_only_dfu); + + channel_init(serial_only_dfu); } // Initiate an update of the firmware. @@ -345,15 +388,16 @@ static void check_dfu_mode(void) else { // No timeout if bootloader requires user action (double-reset). - bootloader_dfu_start(_ota_dfu, 0, false); + bootloader_dfu_start(_ota_dfu, 100000, false); } if ( _ota_dfu ) { sd_softdevice_disable(); - }else + } + else { - usb_teardown(); + channel_teardown(); } } } diff --git a/src/nrfx_config.h b/src/nrfx_config.h index b626e000..d745cf7b 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -17,8 +17,8 @@ #define NRFX_PWM3_ENABLED 0 // UART -#ifdef NRF52832_XXAA - +// mdm #ifdef NRF52832_XXAA +//#error mdm hey #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 @@ -26,6 +26,6 @@ #define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED #define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED #define NRFX_UART_DEFAULT_CONFIG_BAUDRATE NRF_UART_BAUDRATE_115200 -#endif +// #endif #endif From 29548945f2eb65981925aeaf9a8bbaba33b2ff08 Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Mon, 12 Sep 2022 16:47:49 -0700 Subject: [PATCH 3/8] feat: adds support for programming the external qspi flash --- .gitignore | 2 + Makefile | 10 ++ lib/nrfx | 2 +- .../components/libraries/hci/hci_mem_pool.c | 3 + lib/sdk/components/libraries/hci/hci_slip.c | 7 +- .../components/libraries/hci/hci_transport.c | 11 +- .../libraries/bootloader_dfu/bootloader.c | 6 +- .../libraries/bootloader_dfu/bootloader.h | 3 +- .../components/libraries/bootloader_dfu/dfu.h | 12 ++ .../bootloader_dfu/dfu_single_bank.c | 123 +++++++++++++++++- .../bootloader_dfu/dfu_transport_serial.c | 41 +++++- .../libraries/bootloader_dfu/dfu_types.h | 60 ++++++++- src/boards/boards.h | 4 + src/boards/feather_nrf52840_express/board.h | 13 ++ src/boards/feather_nrf52840_express/board.mk | 1 + src/main.c | 24 ++-- src/nrfx_config.h | 12 +- src/nrfx_glue.h | 4 +- 18 files changed, 306 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 1c244fca..50cfbe7e 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,5 @@ TAGS .DS_Store Makefile.user +venv +venv2 diff --git a/Makefile b/Makefile index b3acfd12..b28ae127 100644 --- a/Makefile +++ b/Makefile @@ -122,6 +122,10 @@ else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) endif +ifeq ($(DFU_EXTERNAL_FLASH),1) + CFLAGS += -DDFU_EXTERNAL_FLASH +endif + #------------------------------------------------------------------------------ # SOURCE FILES #------------------------------------------------------------------------------ @@ -139,6 +143,12 @@ C_SRC += src/boards/boards.c # nrfx C_SRC += $(NRFX_PATH)/drivers/src/nrfx_power.c C_SRC += $(NRFX_PATH)/drivers/src/nrfx_nvmc.c + +ifeq ($(DFU_EXTERNAL_FLASH),1) +C_SRC += $(NRFX_PATH)/drivers/src/nrfx_qspi.c +# C_SRC += src/amd5.c +endif + C_SRC += $(NRFX_PATH)/mdk/system_$(MCU_SUB_VARIANT).c # SDK 11 files: serial + OTA DFU diff --git a/lib/nrfx b/lib/nrfx index 7a4c9d94..f5a9b04b 160000 --- a/lib/nrfx +++ b/lib/nrfx @@ -1 +1 @@ -Subproject commit 7a4c9d946cf1801771fc180acdbf7b878f270093 +Subproject commit f5a9b04bacdd46cf6206f5813cd7e078ce5d553e diff --git a/lib/sdk/components/libraries/hci/hci_mem_pool.c b/lib/sdk/components/libraries/hci/hci_mem_pool.c index 82412399..ae378a92 100644 --- a/lib/sdk/components/libraries/hci/hci_mem_pool.c +++ b/lib/sdk/components/libraries/hci/hci_mem_pool.c @@ -39,6 +39,7 @@ */ #include "sdk_common.h" #if NRF_MODULE_ENABLED(HCI_MEM_POOL) +#include "app_util_platform.h" #include "hci_mem_pool.h" #include #include @@ -134,6 +135,7 @@ uint32_t hci_mem_pool_rx_produce(uint32_t length, void ** pp_buffer) } *pp_buffer = NULL; + NRFX_CRITICAL_SECTION_ENTER(); if (m_rx_buffer_queue.free_window_count != 0) { if (length <= HCI_RX_BUF_SIZE) @@ -163,6 +165,7 @@ uint32_t hci_mem_pool_rx_produce(uint32_t length, void ** pp_buffer) { err_code = NRF_ERROR_NO_MEM; } + NRFX_CRITICAL_SECTION_EXIT(); return err_code; } diff --git a/lib/sdk/components/libraries/hci/hci_slip.c b/lib/sdk/components/libraries/hci/hci_slip.c index 8dde8756..ed6c0d44 100644 --- a/lib/sdk/components/libraries/hci/hci_slip.c +++ b/lib/sdk/components/libraries/hci/hci_slip.c @@ -46,6 +46,7 @@ #include "board.h" #if USE_RUNTIME_SELECTION +#pragma message "USB and UART enabled" static bool selectSerial = false; // use USB by default void useSerialTransport() { @@ -137,8 +138,7 @@ uint32_t (*send_tx_byte) (void) = send_tx_byte_default; #if USE_USB && !USE_RUNTIME_SELECTION - -static uint32_t serial_put(char ch) +uint32_t serial_put(char ch) { return tud_cdc_write_char(ch) ? NRF_SUCCESS : NRF_ERROR_NO_MEM; } @@ -149,7 +149,7 @@ static uint32_t serial_put(char ch) #else -static uint32_t serial_put(char ch) +uint32_t serial_put(char ch) { return selectSerial ? app_uart_put(ch) : (tud_cdc_write_char(ch) ? NRF_SUCCESS : NRF_ERROR_NO_MEM); } @@ -499,7 +499,6 @@ uint32_t hci_slip_close() } - uint32_t hci_slip_write(const uint8_t * p_buffer, uint32_t length) { if (p_buffer == NULL) diff --git a/lib/sdk/components/libraries/hci/hci_transport.c b/lib/sdk/components/libraries/hci/hci_transport.c index 35064763..f9b85f8e 100644 --- a/lib/sdk/components/libraries/hci/hci_transport.c +++ b/lib/sdk/components/libraries/hci/hci_transport.c @@ -39,6 +39,7 @@ */ #include "sdk_common.h" #if NRF_MODULE_ENABLED(HCI_TRANSPORT) +#include "app_util_platform.h" #include "hci_transport.h" #include "hci_slip.h" #include "crc16.h" @@ -286,6 +287,7 @@ static void rx_vendor_specific_pkt_type_handle(const uint8_t * p_buffer, uint32_ err_code = hci_mem_pool_rx_produce(HCI_RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer); APP_ERROR_CHECK_BOOL((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM)); + // If memory pool RX buffer produce succeeded we register that buffer to slip layer // otherwise we register the internal acknowledgement buffer. err_code = hci_slip_rx_buffer_register( @@ -781,7 +783,9 @@ uint32_t hci_transport_rx_pkt_extract(uint8_t ** pp_buffer, uint16_t * p_length) if (m_is_slip_decode_ready) { m_is_slip_decode_ready = false; + CRITICAL_REGION_ENTER(); err_code = hci_mem_pool_rx_extract(pp_buffer, &length); + CRITICAL_REGION_EXIT(); length -= (PKT_HDR_SIZE + PKT_CRC_SIZE); *p_length = (uint16_t)length; @@ -800,9 +804,12 @@ uint32_t hci_transport_rx_pkt_extract(uint8_t ** pp_buffer, uint16_t * p_length) return err_code; } - uint32_t hci_transport_rx_pkt_consume(uint8_t * p_buffer) { - return (hci_mem_pool_rx_consume(p_buffer - PKT_HDR_SIZE)); + uint32_t r; + CRITICAL_REGION_ENTER(); + r = hci_mem_pool_rx_consume(p_buffer - PKT_HDR_SIZE); + CRITICAL_REGION_EXIT(); + return r; } #endif //NRF_MODULE_ENABLED(HCI_TRANSPORT) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 875ab6c4..98d8adba 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -354,7 +354,7 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout return err_code; } -void bootloader_app_start(void) +uint32_t bootloader_app_register(void) { // Disable all interrupts NVIC->ICER[0]=0xFFFFFFFF; @@ -396,9 +396,7 @@ void bootloader_app_start(void) // MBR use first 4-bytes of SRAM to store foward address *(uint32_t *)(0x20000000) = app_addr; } - - // jump to app - bootloader_util_app_start(app_addr); + return app_addr; } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h index efd72e75..05306ae8 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h @@ -50,9 +50,8 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout * The SoftDevice vector table base for interrupt forwarding will be set the application * address. * - * @param[in] app_addr Address to the region where the application is stored. */ -void bootloader_app_start(void); +uint32_t bootloader_app_register(void); /**@brief Function for retrieving the bootloader settings. * diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu.h index 8916b7a3..c869d713 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu.h @@ -129,6 +129,18 @@ uint32_t dfu_sd_image_swap(void); */ uint32_t dfu_init_pkt_complete(void); + +#if DFU_EXTERNAL_FLASH +uint32_t dfu_external_begin_pkt_handle(dfu_update_packet_t* p_packet); + +uint32_t dfu_erase_pkt_handle(dfu_erase_packet_t* p_packet); +uint32_t dfu_write_pkt_handle(dfu_write_packet_t* p_packet); +uint32_t dfu_checksum_pkt_handle(dfu_checksum_packet_t* p_packet); + +uint32_t dfu_external_end_pkt_handle(dfu_update_packet_t* p_packet); + +#endif + #endif // DFU_H__ /** @} */ diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index fa69ec83..e7f73b34 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -24,6 +24,10 @@ #include "nrf_mbr.h" #include "dfu_init.h" #include "sdk_common.h" +#if DFU_EXTERNAL_FLASH +#include "nrfx_qspi.h" +//#include "amd5.h" +#endif #include "boards.h" @@ -41,7 +45,6 @@ static pstorage_handle_t * mp_storage_handle_active; /**< Pointer to static dfu_callback_t m_data_pkt_cb; /**< Callback from DFU Bank module for notification of asynchronous operation such as flash prepare. */ static dfu_bank_func_t m_functions; /**< Structure holding operations for the selected update process. */ - /**@brief Function for handling callbacks from pstorage module. * * @details Handles pstorage results for clear and storage operation. For detailed description of @@ -101,7 +104,8 @@ static void dfu_prepare_func_app_erase(uint32_t image_size) } else { - uint32_t const page_count = NRFX_CEIL_DIV(m_image_size, CODE_PAGE_SIZE); + // MRFX_CEIL_DIV fails when the first operand is 0 + uint32_t const page_count = m_image_size ? NRFX_CEIL_DIV(m_image_size, CODE_PAGE_SIZE) : 0; for ( uint32_t i = 0; i < page_count; i++ ) { @@ -521,6 +525,121 @@ void dfu_reset(void) } +#if DFU_EXTERNAL_FLASH +static const nrfx_qspi_config_t qspi_config = NRFX_QSPI_DEFAULT_CONFIG(QSPI_SCK, QSPI_CS, QSPI_DATA0, QSPI_DATA1, QSPI_DATA2, QSPI_DATA3); + +nrfx_err_t dfu_init_qspi_flash(void) { + static bool inited = false; + uint32_t err_code = NRFX_SUCCESS; + if (!inited) { + // use blocking mode for simplicity + err_code = nrfx_qspi_init(&qspi_config, NULL, NULL); + if (err_code==NRFX_SUCCESS) { + inited = true; + } + NRFX_DELAY_MS(5); + } + return err_code; +} + +uint32_t dfu_external_begin_pkt_handle(dfu_update_packet_t* p_packet) { + if (dfu_init_qspi_flash()!=NRFX_SUCCESS) + return NRF_ERROR_BUSY; + return NRF_SUCCESS; +} + +uint32_t dfu_external_end_pkt_handle(dfu_update_packet_t* p_packet) { + // this crashes the device. reason unknown. + //nrfx_qspi_uninit(); + return NRF_SUCCESS; +} + + +dfu_erase_packet_t* m_erase_pkt; +uint32_t dfu_erase_pkt_handle(dfu_erase_packet_t * p_packet) +{ + VERIFY_PARAM_NOT_NULL(p_packet); + m_erase_pkt = p_packet; + + if (m_erase_pkt->memory_region != DFU_MEMORY_EXTERNAL_FLASH) { + return NRF_ERROR_NOT_SUPPORTED; + } + + while (m_erase_pkt->length) { + if (m_erase_pkt->length < 4096) { + return NRF_ERROR_INVALID_LENGTH; + } + if (nrfx_qspi_erase((m_erase_pkt->length>4096) ? NRF_QSPI_ERASE_LEN_64KB : NRF_QSPI_ERASE_LEN_4KB, m_erase_pkt->address)!=NRFX_SUCCESS) + return NRF_ERROR_NOT_FOUND; + const uint32_t block_size = (m_erase_pkt->length>4096) ? 64*1024 : 4*1024; + m_erase_pkt->length -= block_size; + m_erase_pkt->address += block_size; + } + return NRF_SUCCESS; +} + +#define XIP_BASE (0x12000000) + +uint32_t dfu_write_pkt_handle(dfu_write_packet_t * p_packet) +{ + VERIFY_PARAM_NOT_NULL(p_packet); + + if (p_packet->memory_region != DFU_MEMORY_EXTERNAL_FLASH) { + return NRF_ERROR_NOT_SUPPORTED; + } + + unsigned retries = 5; + + uint32_t remaining = p_packet->length; + uint32_t address = p_packet->address; + const char* data = (const char*)p_packet->data; + uint32_t error = NRF_ERROR_NOT_FOUND; + + while (retries-->0 && error != NRF_SUCCESS) { + // the nrfx interface uses error codes in a different range of numbers, so these need to be mapped + // to regular nrf error codes + if (nrfx_qspi_write(data, remaining, address)!=NRFX_SUCCESS) { + error = NRF_ERROR_NOT_FOUND; + } + else { + // verify against the xip region + if (memcmp(data, (void*)(XIP_BASE+address), remaining)) + error = NRF_ERROR_INVALID_DATA; + else + error = NRF_SUCCESS; + } + } + return error; +} + +/* +void compute_md5(uint8_t digest[16], uint32_t address, uint32_t length) { + struct MD5Context context; + MD5Init(&context); + MD5Update(&context, (const uint8_t*)(address+XIP_BASE), length); + MD5Final(digest, &context); +} +*/ + +uint32_t dfu_checksum_pkt_handle(dfu_checksum_packet_t * p_packet) +{ + VERIFY_PARAM_NOT_NULL(p_packet); + + if (p_packet->memory_region != DFU_MEMORY_EXTERNAL_FLASH) { + return NRF_ERROR_NOT_SUPPORTED; + } + + // uint8_t computed_md5[16]; + // compute_md5(computed_md5, p_packet->address, p_packet->length); + // if (memcmp(computed_md5, p_packet->md5, sizeof(computed_md5))) { + // return NRF_ERROR_INVALID_DATA; + // } + + return NRF_SUCCESS; +} + +#endif + static uint32_t dfu_compare_block(uint32_t * ptr1, uint32_t * ptr2, uint32_t len) { sd_mbr_command_t sd_mbr_cmd; diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c index 71f08526..cf6c7e96 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c @@ -11,6 +11,8 @@ */ #include "dfu_transport.h" +#include "app_util_platform.h" +#include #include #include "dfu.h" #include @@ -66,7 +68,7 @@ typedef struct { dfu_update_packet_t data_packet[MAX_BUFFERS]; /**< Bootloader data packets used when processing data from the UART. */ - volatile uint8_t count; /**< Counter to maintain number of elements in the queue. */ +_Atomic volatile uint8_t count; /**< Counter to maintain number of elements in the queue. */ } dfu_data_queue_t; static dfu_data_queue_t m_data_queue; /**< Received-data packet queue. */ @@ -109,14 +111,19 @@ static uint32_t data_queue_element_free(uint8_t element_index) if (MAX_BUFFERS > element_index) { + CRITICAL_REGION_ENTER(); p_data = (uint8_t *)DATA_QUEUE_ELEMENT_GET_PDATA(element_index); if (INVALID_PACKET != DATA_QUEUE_ELEMENT_GET_PTYPE(element_index)) { - m_data_queue.count--; data_queue_element_init (element_index); + m_data_queue.count--; retval = hci_transport_rx_pkt_consume((p_data - 4)); + if (retval) { + retval = hci_transport_rx_pkt_consume((p_data - 4)); + } APP_ERROR_CHECK(retval); } + CRITICAL_REGION_EXIT(); } else { @@ -190,6 +197,7 @@ static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data) APP_ERROR_CHECK(result); } +extern void tud_cdc_write_str(const char* s); static void process_dfu_packet(void * p_event_data, uint16_t event_size) { @@ -239,6 +247,35 @@ static void process_dfu_packet(void * p_event_data, uint16_t event_size) // Break the loop by returning. return; +#if DFU_EXTERNAL_FLASH + case EXTERNAL_FLASH_BEGIN_PACKET: + retval = dfu_external_begin_pkt_handle(packet); + APP_ERROR_CHECK(retval); + break; + + case EXTERNAL_FLASH_ERASE_PACKET: + retval = dfu_erase_pkt_handle((dfu_erase_packet_t*)&packet->params.data_packet.p_data_packet[0]); + APP_ERROR_CHECK(retval); + break; + + case EXTERNAL_FLASH_CHECKSUM_PACKET: + retval = dfu_checksum_pkt_handle((dfu_checksum_packet_t*)&packet->params.data_packet.p_data_packet[0]); + APP_ERROR_CHECK(retval); + break; + + case EXTERNAL_FLASH_WRITE_PACKET: + retval = dfu_write_pkt_handle((dfu_write_packet_t*)&packet->params.data_packet.p_data_packet[0]); + APP_ERROR_CHECK(retval); + break; + + case EXTERNAL_FLASH_END_PACKET: + retval = dfu_external_end_pkt_handle(packet); + APP_ERROR_CHECK(retval); + break; + +#endif + + case PING_PACKET: default: // No implementation needed. break; diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 8da73309..caafb660 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -77,10 +77,11 @@ static inline bool is_sd_existed(void) #define INVALID_PACKET 0x00 /**< Invalid packet identifies. */ #define INIT_PACKET 0x01 /**< Packet identifies for initialization packet. */ -#define STOP_INIT_PACKET 0x02 /**< Packet identifies for stop initialization packet. Used when complete init packet has been received so that the init packet can be used for pre validaiton. */ +//#define STOP_INIT_PACKET 0x02 // unused /**< Packet identifies for stop initialization packet. Used when complete init packet has been received so that the init packet can be used for pre validaiton. */ #define START_PACKET 0x03 /**< Packet identifies for the Data Start Packet. */ #define DATA_PACKET 0x04 /**< Packet identifies for a Data Packet. */ #define STOP_DATA_PACKET 0x05 /**< Packet identifies for the Data Stop Packet. */ +#define PING_PACKET 0x09 // used for synchronization and testing connectivity #define DFU_UPDATE_SD 0x01 /**< Bit field indicating update of SoftDevice is ongoing. */ #define DFU_UPDATE_BL 0x02 /**< Bit field indicating update of bootloader is ongoing. */ @@ -89,6 +90,14 @@ static inline bool is_sd_existed(void) #define DFU_INIT_RX 0x00 /**< Op Code identifies for receiving init packet. */ #define DFU_INIT_COMPLETE 0x01 /**< Op Code identifies for transmission complete of init packet. */ +#ifdef DFU_EXTERNAL_FLASH +#define EXTERNAL_FLASH_BEGIN_PACKET 0x10 +#define EXTERNAL_FLASH_ERASE_PACKET 0x11 +#define EXTERNAL_FLASH_CHECKSUM_PACKET 0x12 +#define EXTERNAL_FLASH_WRITE_PACKET 0x13 +#define EXTERNAL_FLASH_END_PACKET 0x14 +#endif + // Safe guard to ensure during compile time that the DFU_APP_DATA_RESERVED is a multiple of page size. STATIC_ASSERT((((DFU_APP_DATA_RESERVED) & (CODE_PAGE_SIZE - 1)) == 0x00)); @@ -151,6 +160,55 @@ typedef struct /**@brief Update complete handler type. */ typedef void (*dfu_complete_handler_t)(dfu_update_status_t dfu_update_status); +#ifdef DFU_EXTERNAL_FLASH + +typedef enum +{ + DFU_MEMORY_INTERNAL_FLASH = 0, // unsupported + DFU_MEMORY_EXTERNAL_FLASH = 16, +} dfu_memory_region_t; + +STATIC_ASSERT((sizeof(dfu_memory_region_t) == 1)); + + +typedef struct +{ + dfu_memory_region_t memory_region; + uint8_t reserved[3]; + uint32_t length; + uint32_t address; +} dfu_erase_packet_t; + +STATIC_ASSERT((sizeof(dfu_erase_packet_t) == 12)); + + +typedef struct +{ + dfu_memory_region_t memory_region; + uint8_t reserved[3]; + uint32_t address; // must be 8 byte aligned + uint32_t length; // the number of bytes of data to write + uint8_t data[]; // the data to write at the given address +} dfu_write_packet_t; + +STATIC_ASSERT((sizeof(dfu_write_packet_t) == 12)); + +typedef uint8_t md5_t[16]; +typedef struct +{ + dfu_memory_region_t memory_region; + uint8_t reserved[3]; + uint32_t address; + uint32_t length; + md5_t md5; +} dfu_checksum_packet_t; + +STATIC_ASSERT((sizeof(dfu_checksum_packet_t) == 28)); + + +#endif + + #endif // DFU_TYPES_H__ /**@} */ diff --git a/src/boards/boards.h b/src/boards/boards.h index 5513f6d8..7afd223d 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -71,6 +71,10 @@ #define PIN_DFU_ACTIVATE_PRESENT 0 #endif +#ifndef DFU_EXTERNAL_FLASH +#define DFU_EXTERNAL_FLASH 0 +#endif + // The primary LED is usually Red but not in all cases. #define LED_PRIMARY 0 // The secondary LED, when available, is usually blue. diff --git a/src/boards/feather_nrf52840_express/board.h b/src/boards/feather_nrf52840_express/board.h index d7ab81c3..22136dea 100644 --- a/src/boards/feather_nrf52840_express/board.h +++ b/src/boards/feather_nrf52840_express/board.h @@ -79,4 +79,17 @@ #define RTS_PIN_NUMBER 0 #define HWFC false +/*------------------------------------------------------------------*/ +/* QSPI external flash + *------------------------------------------------------------------*/ +#define DFU_EXTERNAL_FLASH 1 + +#define QSPI_DATA0 _PINNUM(0, 17) +#define QSPI_DATA1 _PINNUM(0, 22) +#define QSPI_DATA2 _PINNUM(0, 23) +#define QSPI_DATA3 _PINNUM(0, 21) +#define QSPI_SCK _PINNUM(0, 19) +#define QSPI_CS _PINNUM(0, 20) + + #endif // _FEATHER_NRF52840_H diff --git a/src/boards/feather_nrf52840_express/board.mk b/src/boards/feather_nrf52840_express/board.mk index 7b69a77d..17fda8c3 100644 --- a/src/boards/feather_nrf52840_express/board.mk +++ b/src/boards/feather_nrf52840_express/board.mk @@ -1,2 +1,3 @@ MCU_SUB_VARIANT = nrf52840 USE_USART = 1 +DFU_EXTERNAL_FLASH = 1 diff --git a/src/main.c b/src/main.c index 4683e83d..767f3718 100644 --- a/src/main.c +++ b/src/main.c @@ -83,6 +83,8 @@ void usb_teardown(void); #define uart_teardown() #endif +extern void serial_put(char c); + void channel_init(bool cdc_only) { #if USE_RUNTIME_SELECTION if (usingSerialTransport()) { @@ -174,7 +176,7 @@ bool is_ota(void) return _ota_dfu; } -static void check_dfu_mode(void); +static bool check_dfu_mode(void); static uint32_t ble_stack_init(void); // The SoftDevice must only be initialized if a chip reset has occurred. @@ -220,7 +222,7 @@ int main(void) // Check all inputs and enter DFU if needed // Return when DFU process is complete (or not entered at all) - check_dfu_mode(); + bool dfu_activate = check_dfu_mode(); // Reset peripherals board_teardown(); @@ -248,14 +250,17 @@ int main(void) // clear in case we kept DFU_DBL_RESET_APP there (*dbl_reset_mem) = 0; - // start application - bootloader_app_start(); + uint32_t app_addr = bootloader_app_register(); + if (!dfu_activate) { + // jump to app + bootloader_util_app_start(app_addr); + } } NVIC_SystemReset(); } -static void check_dfu_mode(void) +static bool check_dfu_mode(void) { uint32_t const gpregret = NRF_POWER->GPREGRET; @@ -293,13 +298,13 @@ static void check_dfu_mode(void) frst_skip = (PIN_DFU_ACTIVATE == BUTTON_FRESET); #pragma message "FRST is overridden by the DFU activate setting" #endif - + dfu_start = dfu_start || dfu_activate; // DFU activation via the designated pin takes precedence if (!dfu_activate_present || !dfu_activate) { // skip dfu entirely - if (dfu_skip) return; + if (dfu_skip) return false; /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ // DFU button pressed @@ -357,8 +362,6 @@ static void check_dfu_mode(void) useSerialTransport(); } - NRFX_DELAY_US(500); // wait for the pin state is stable - // Enter DFU mode accordingly to input if ( dfu_start || !valid_app ) @@ -388,7 +391,7 @@ static void check_dfu_mode(void) else { // No timeout if bootloader requires user action (double-reset). - bootloader_dfu_start(_ota_dfu, 100000, false); + bootloader_dfu_start(_ota_dfu, 0, false); } if ( _ota_dfu ) @@ -400,6 +403,7 @@ static void check_dfu_mode(void) channel_teardown(); } } + return dfu_activate; } diff --git a/src/nrfx_config.h b/src/nrfx_config.h index d745cf7b..e0da8738 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -16,11 +16,19 @@ #define NRFX_PWM2_ENABLED 0 #define NRFX_PWM3_ENABLED 0 +#if DFU_EXTERNAL_FLASH +#define NRFX_QSPI_ENABLED 1 +#define NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRF_QSPI_HAS_XIP_ENC 0 +#define NRF_QSPI_HAS_DMA_ENC 0 +#endif + // UART -// mdm #ifdef NRF52832_XXAA -//#error mdm hey +// todo mdm #ifdef NRF52832_XXAA #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 +#define NRF_REGULATORS_HAS_POFCON 0 +#define USE_WORKAROUND_FOR_ANOMALY_121 0 #define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED diff --git a/src/nrfx_glue.h b/src/nrfx_glue.h index 0d18d234..d382989d 100644 --- a/src/nrfx_glue.h +++ b/src/nrfx_glue.h @@ -175,12 +175,12 @@ static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number) /** * @brief Macro for entering into a critical section. */ -#define NRFX_CRITICAL_SECTION_ENTER() // CRITICAL_REGION_ENTER() +#define NRFX_CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER() /** * @brief Macro for exiting from a critical section. */ -#define NRFX_CRITICAL_SECTION_EXIT() // CRITICAL_REGION_EXIT() +#define NRFX_CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT() //------------------------------------------------------------------------------ From 0d29fa017bc016d9b901aa60f4ca05ebefb99f46 Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Tue, 20 Sep 2022 17:07:34 -0700 Subject: [PATCH 4/8] ensure the QSPI flash is initialized. Adjust the QSPI interrupt priority. --- lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c | 2 ++ src/nrfx_config.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index e7f73b34..663edaad 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -565,6 +565,7 @@ uint32_t dfu_erase_pkt_handle(dfu_erase_packet_t * p_packet) return NRF_ERROR_NOT_SUPPORTED; } + dfu_init_qspi_flash(); while (m_erase_pkt->length) { if (m_erase_pkt->length < 4096) { return NRF_ERROR_INVALID_LENGTH; @@ -587,6 +588,7 @@ uint32_t dfu_write_pkt_handle(dfu_write_packet_t * p_packet) if (p_packet->memory_region != DFU_MEMORY_EXTERNAL_FLASH) { return NRF_ERROR_NOT_SUPPORTED; } + dfu_init_qspi_flash(); unsigned retries = 5; diff --git a/src/nrfx_config.h b/src/nrfx_config.h index e0da8738..19d5b5ea 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -18,7 +18,7 @@ #if DFU_EXTERNAL_FLASH #define NRFX_QSPI_ENABLED 1 -#define NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY 8 #define NRF_QSPI_HAS_XIP_ENC 0 #define NRF_QSPI_HAS_DMA_ENC 0 #endif From 0c2fe0d3f812cb9c387336a0dc20324c34b766a9 Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Thu, 20 Oct 2022 15:56:34 -0700 Subject: [PATCH 5/8] revert lib/nrfx to 2.0.0 - causes compilation errors on nRF52832. code cleanup. --- .gitignore | 2 -- Makefile | 34 +++++++++++++------ lib/nrfx | 2 +- lib/sdk/components/libraries/hci/hci_slip.c | 2 +- lib/sdk/components/libraries/hci/hci_slip.h | 2 +- .../bootloader_dfu/dfu_single_bank.c | 16 --------- .../bootloader_dfu/dfu_transport_serial.c | 3 -- .../libraries/bootloader_dfu/dfu_types.h | 4 +-- src/boards/boards.h | 4 --- src/boards/feather_nrf52840_express/board.h | 2 -- src/boards/feather_nrf52840_express/board.mk | 3 +- src/main.c | 20 +++++++++-- src/nrfx_config.h | 6 ++-- 13 files changed, 51 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 50cfbe7e..1c244fca 100644 --- a/.gitignore +++ b/.gitignore @@ -65,5 +65,3 @@ TAGS .DS_Store Makefile.user -venv -venv2 diff --git a/Makefile b/Makefile index b28ae127..3f39a7c8 100644 --- a/Makefile +++ b/Makefile @@ -122,9 +122,8 @@ else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) endif -ifeq ($(DFU_EXTERNAL_FLASH),1) - CFLAGS += -DDFU_EXTERNAL_FLASH -endif +DFU_EXTERNAL_FLASH ?= 0 +CFLAGS += -DDFU_EXTERNAL_FLASH=$(DFU_EXTERNAL_FLASH) #------------------------------------------------------------------------------ # SOURCE FILES @@ -146,7 +145,6 @@ C_SRC += $(NRFX_PATH)/drivers/src/nrfx_nvmc.c ifeq ($(DFU_EXTERNAL_FLASH),1) C_SRC += $(NRFX_PATH)/drivers/src/nrfx_qspi.c -# C_SRC += src/amd5.c endif C_SRC += $(NRFX_PATH)/mdk/system_$(MCU_SUB_VARIANT).c @@ -173,9 +171,25 @@ C_SRC += $(SDK_PATH)/libraries/hci/hci_slip.c C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.c C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c -# UART or USB Serial -ifdef USE_USART -$(info nrF52 UART) + +DFU_PIN_ACTIVATION ?= 0 +ifeq ($(DFU_PIN_ACTIVATION),1) + BOARD_USE_UART = 1 +endif + +ifneq ($(MCU_SUB_VARIANT),nrf52) + BOARD_USE_USB_CDC = 1 +endif + +ifeq ($(MCU_SUB_VARIANT),nrf52) + BOARD_USE_UART = 1 +endif + +BOARD_USE_UART ?= 0 +BOARD_USE_USB_CDC ?= 0 +CFLAGS += -DBOARD_USE_UART=$(BOARD_USE_UART) + +ifeq ($(BOARD_USE_UART),1) C_SRC += $(SDK_PATH)/libraries/uart/app_uart.c C_SRC += $(SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c C_SRC += $(SDK_PATH)/drivers_nrf/common/nrf_drv_common.c @@ -183,9 +197,9 @@ C_SRC += $(SDK_PATH)/drivers_nrf/common/nrf_drv_common.c IPATH += $(SDK11_PATH)/libraries/util IPATH += $(SDK_PATH)/drivers_nrf/common IPATH += $(SDK_PATH)/drivers_nrf/uart +endif -# else - +ifeq ($(BOARD_USE_USB_CDC),1) # pinconfig is required for 840 for CF2 C_SRC += src/boards/$(BOARD)/pinconfig.c @@ -206,7 +220,7 @@ C_SRC += \ $(TUSB_PATH)/class/msc/msc_device.c \ $(TUSB_PATH)/tusb.c -# +# endif #------------------------------------------------------------------------------ diff --git a/lib/nrfx b/lib/nrfx index f5a9b04b..7a4c9d94 160000 --- a/lib/nrfx +++ b/lib/nrfx @@ -1 +1 @@ -Subproject commit f5a9b04bacdd46cf6206f5813cd7e078ce5d553e +Subproject commit 7a4c9d946cf1801771fc180acdbf7b878f270093 diff --git a/lib/sdk/components/libraries/hci/hci_slip.c b/lib/sdk/components/libraries/hci/hci_slip.c index ed6c0d44..c47fc364 100644 --- a/lib/sdk/components/libraries/hci/hci_slip.c +++ b/lib/sdk/components/libraries/hci/hci_slip.c @@ -453,7 +453,7 @@ static uint32_t slip_uart_open(void) { else { return slip_uart_open_usb_cdc(); } - #elif USE_USB + #elif USE_SERIAL return slip_uart_open_serial(); #else return slip_uart_open_usb_cdc(); diff --git a/lib/sdk/components/libraries/hci/hci_slip.h b/lib/sdk/components/libraries/hci/hci_slip.h index 107ef134..da8a1216 100644 --- a/lib/sdk/components/libraries/hci/hci_slip.h +++ b/lib/sdk/components/libraries/hci/hci_slip.h @@ -71,7 +71,7 @@ /** * @brief Enable UART interface with DFU_ACTIVATION present for MCU to MCU transfers */ -#define USE_SERIAL PIN_DFU_ACTIVATE_PRESENT +#define USE_SERIAL (PIN_DFU_ACTIVATE_PRESENT || BOARD_USE_UART) #define USE_RUNTIME_SELECTION (USE_USB && USE_SERIAL) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index 663edaad..13cde008 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -26,7 +26,6 @@ #include "sdk_common.h" #if DFU_EXTERNAL_FLASH #include "nrfx_qspi.h" -//#include "amd5.h" #endif #include "boards.h" @@ -614,15 +613,6 @@ uint32_t dfu_write_pkt_handle(dfu_write_packet_t * p_packet) return error; } -/* -void compute_md5(uint8_t digest[16], uint32_t address, uint32_t length) { - struct MD5Context context; - MD5Init(&context); - MD5Update(&context, (const uint8_t*)(address+XIP_BASE), length); - MD5Final(digest, &context); -} -*/ - uint32_t dfu_checksum_pkt_handle(dfu_checksum_packet_t * p_packet) { VERIFY_PARAM_NOT_NULL(p_packet); @@ -631,12 +621,6 @@ uint32_t dfu_checksum_pkt_handle(dfu_checksum_packet_t * p_packet) return NRF_ERROR_NOT_SUPPORTED; } - // uint8_t computed_md5[16]; - // compute_md5(computed_md5, p_packet->address, p_packet->length); - // if (memcmp(computed_md5, p_packet->md5, sizeof(computed_md5))) { - // return NRF_ERROR_INVALID_DATA; - // } - return NRF_SUCCESS; } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c index cf6c7e96..840c7985 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_serial.c @@ -118,9 +118,6 @@ static uint32_t data_queue_element_free(uint8_t element_index) data_queue_element_init (element_index); m_data_queue.count--; retval = hci_transport_rx_pkt_consume((p_data - 4)); - if (retval) { - retval = hci_transport_rx_pkt_consume((p_data - 4)); - } APP_ERROR_CHECK(retval); } CRITICAL_REGION_EXIT(); diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index caafb660..a23d777b 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -90,7 +90,7 @@ static inline bool is_sd_existed(void) #define DFU_INIT_RX 0x00 /**< Op Code identifies for receiving init packet. */ #define DFU_INIT_COMPLETE 0x01 /**< Op Code identifies for transmission complete of init packet. */ -#ifdef DFU_EXTERNAL_FLASH +#if DFU_EXTERNAL_FLASH #define EXTERNAL_FLASH_BEGIN_PACKET 0x10 #define EXTERNAL_FLASH_ERASE_PACKET 0x11 #define EXTERNAL_FLASH_CHECKSUM_PACKET 0x12 @@ -160,7 +160,7 @@ typedef struct /**@brief Update complete handler type. */ typedef void (*dfu_complete_handler_t)(dfu_update_status_t dfu_update_status); -#ifdef DFU_EXTERNAL_FLASH +#if DFU_EXTERNAL_FLASH typedef enum { diff --git a/src/boards/boards.h b/src/boards/boards.h index 7afd223d..5513f6d8 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -71,10 +71,6 @@ #define PIN_DFU_ACTIVATE_PRESENT 0 #endif -#ifndef DFU_EXTERNAL_FLASH -#define DFU_EXTERNAL_FLASH 0 -#endif - // The primary LED is usually Red but not in all cases. #define LED_PRIMARY 0 // The secondary LED, when available, is usually blue. diff --git a/src/boards/feather_nrf52840_express/board.h b/src/boards/feather_nrf52840_express/board.h index 22136dea..2f676efd 100644 --- a/src/boards/feather_nrf52840_express/board.h +++ b/src/boards/feather_nrf52840_express/board.h @@ -82,8 +82,6 @@ /*------------------------------------------------------------------*/ /* QSPI external flash *------------------------------------------------------------------*/ -#define DFU_EXTERNAL_FLASH 1 - #define QSPI_DATA0 _PINNUM(0, 17) #define QSPI_DATA1 _PINNUM(0, 22) #define QSPI_DATA2 _PINNUM(0, 23) diff --git a/src/boards/feather_nrf52840_express/board.mk b/src/boards/feather_nrf52840_express/board.mk index 17fda8c3..dbd68b5a 100644 --- a/src/boards/feather_nrf52840_express/board.mk +++ b/src/boards/feather_nrf52840_express/board.mk @@ -1,3 +1,4 @@ MCU_SUB_VARIANT = nrf52840 -USE_USART = 1 +DFU_PIN_ACTIVATION = 1 DFU_EXTERNAL_FLASH = 1 + diff --git a/src/main.c b/src/main.c index 767f3718..9f315218 100644 --- a/src/main.c +++ b/src/main.c @@ -176,6 +176,11 @@ bool is_ota(void) return _ota_dfu; } +/** + * @brief Perform DFU if requested via flags, button pushes or the DFU activation pin. + * + * @return true DFU was requested via the activation pin. + */ static bool check_dfu_mode(void); static uint32_t ble_stack_init(void); @@ -250,9 +255,13 @@ int main(void) // clear in case we kept DFU_DBL_RESET_APP there (*dbl_reset_mem) = 0; + // register the app uint32_t app_addr = bootloader_app_register(); if (!dfu_activate) { - // jump to app + // jump to app when DFU not enabled via the activation pin (preserving previous behavior) + // otherwise, simply reset, allowing the host MCU to control the behavior on boot via the activation pin. + // The host MCU may keep the device in bootloader mode via the DFU activation pin when there are more + // binaries to flash (e.g. QSPI flash data) bootloader_util_app_start(app_addr); } } @@ -260,6 +269,12 @@ int main(void) NVIC_SystemReset(); } +/** + * @brief Runs DFU if requested by flags, or via the DFU activation pin. + * + * @return true DFU was requested via the activation pin + * @return false DFU was not requested, or if it was, not via the activation pin. + */ static bool check_dfu_mode(void) { uint32_t const gpregret = NRF_POWER->GPREGRET; @@ -358,10 +373,11 @@ static bool check_dfu_mode(void) /* * Enable UART for MCU to MCU transfers. */ +#if PIN_DFU_ACTIVATE_PRESENT if (dfu_activate) { useSerialTransport(); } - +#endif // Enter DFU mode accordingly to input if ( dfu_start || !valid_app ) diff --git a/src/nrfx_config.h b/src/nrfx_config.h index 19d5b5ea..b0cdf287 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -24,16 +24,14 @@ #endif // UART -// todo mdm #ifdef NRF52832_XXAA +#if BOARD_USE_UART #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 -#define NRF_REGULATORS_HAS_POFCON 0 -#define USE_WORKAROUND_FOR_ANOMALY_121 0 #define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED #define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED #define NRFX_UART_DEFAULT_CONFIG_BAUDRATE NRF_UART_BAUDRATE_115200 -// #endif +#endif #endif From 7b78218995d10cea1aa6aadb3673d0645ef4e938 Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Fri, 21 Oct 2022 10:05:54 -0700 Subject: [PATCH 6/8] remove unneeded changes to the LED signalling --- src/boards/boards.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index b9f3dde7..8a94affe 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -273,30 +273,16 @@ void led_state(uint32_t state) switch (state) { case STATE_USB_MOUNTED: new_rgb_color = 0x00ff00; // green - primary_cycle_length = 3000; - break; - - case STATE_UART_ACTIVE: - new_rgb_color = 0x00ffff; // cyan - primary_cycle_length = 3000; break; case STATE_BOOTLOADER_STARTED: - new_rgb_color = 0x000001; // red - primary_cycle_length = 300; - break; - case STATE_UART_TIMEOUT: - new_rgb_color = 0x202020; // grey - primary_cycle_length = 300; - break; - case STATE_USB_UNMOUNTED: - new_rgb_color = 0x200000; // dark red + new_rgb_color = 0xff0000; // red primary_cycle_length = 300; break; case STATE_WRITING_STARTED: - temp_color = 0xffff00; // yellow + temp_color = 0xff0000; // red primary_cycle_length = 100; break; @@ -306,7 +292,7 @@ void led_state(uint32_t state) break; case STATE_BLE_CONNECTED: - new_rgb_color = 0xff00ff; // purple + new_rgb_color = 0x0000ff; // green #ifdef LED_SECONDARY_PIN secondary_cycle_length = 3000; #else @@ -323,6 +309,14 @@ void led_state(uint32_t state) #endif break; + case STATE_UART_ACTIVE: + new_rgb_color = 0x00ffff; // cyan + break; + + case STATE_UART_TIMEOUT: + new_rgb_color = 0x202020; // grey + break; + default: break; } From 047531ae28a12a5a3df637214afeddad3309ca6b Mon Sep 17 00:00:00 2001 From: Matthew McGowan Date: Fri, 21 Oct 2022 10:31:56 -0700 Subject: [PATCH 7/8] fix: typo in function name --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index e4875d8f..f5e5bc63 100644 --- a/src/main.c +++ b/src/main.c @@ -96,7 +96,7 @@ void channel_init(bool cdc_only) { usb_init(cdc_only); } #elif USE_USB - usb_cdc_init(cdc_only); + usb_init(cdc_only); #elif USE_SERIAL uart_init(cdc_only); #endif From 256e174940ef2dd19d7ef6bf246d0c77d57e61b7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Mar 2023 23:47:36 +0700 Subject: [PATCH 8/8] make some changes for quick reset when dfu activation --- Makefile | 38 +++++-------- .../libraries/bootloader_dfu/bootloader.c | 6 +- .../libraries/bootloader_dfu/bootloader.h | 2 +- src/boards/boards.c | 3 + src/main.c | 56 +++++++------------ 5 files changed, 41 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index d883466d..43d67d61 100644 --- a/Makefile +++ b/Makefile @@ -114,16 +114,20 @@ ifeq ($(MCU_SUB_VARIANT),nrf52) DFU_DEV_REV = 0xADAF CFLAGS += -DNRF52 -DNRF52832_XXAA -DS132 DFU_APP_DATA_RESERVED=7*4096 + BOARD_USE_USB = 0 + BOARD_USE_UART = 1 else ifeq ($(MCU_SUB_VARIANT),nrf52833) SD_NAME = s140 DFU_DEV_REV = 52833 CFLAGS += -DNRF52833_XXAA -DS140 DFU_APP_DATA_RESERVED=7*4096 + BOARD_USE_USB = 1 else ifeq ($(MCU_SUB_VARIANT),nrf52840) SD_NAME = s140 DFU_DEV_REV = 52840 CFLAGS += -DNRF52840_XXAA -DS140 DFU_APP_DATA_RESERVED=10*4096 + BOARD_USE_USB = 1 else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) endif @@ -131,6 +135,14 @@ endif DFU_EXTERNAL_FLASH ?= 0 CFLAGS += -DDFU_EXTERNAL_FLASH=$(DFU_EXTERNAL_FLASH) +DFU_PIN_ACTIVATION ?= 0 +ifeq ($(DFU_PIN_ACTIVATION),1) + BOARD_USE_UART = 1 +endif + +BOARD_USE_UART ?= 0 +CFLAGS += -DBOARD_USE_UART=$(BOARD_USE_UART) + #------------------------------------------------------------------------------ # SOURCE FILES #------------------------------------------------------------------------------ @@ -177,24 +189,6 @@ C_SRC += $(SDK_PATH)/libraries/hci/hci_slip.c C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.c C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c - -DFU_PIN_ACTIVATION ?= 0 -ifeq ($(DFU_PIN_ACTIVATION),1) - BOARD_USE_UART = 1 -endif - -ifneq ($(MCU_SUB_VARIANT),nrf52) - BOARD_USE_USB_CDC = 1 -endif - -ifeq ($(MCU_SUB_VARIANT),nrf52) - BOARD_USE_UART = 1 -endif - -BOARD_USE_UART ?= 0 -BOARD_USE_USB_CDC ?= 0 -CFLAGS += -DBOARD_USE_UART=$(BOARD_USE_UART) - ifeq ($(BOARD_USE_UART),1) C_SRC += $(SDK_PATH)/libraries/uart/app_uart.c C_SRC += $(SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c @@ -205,8 +199,8 @@ IPATH += $(SDK_PATH)/drivers_nrf/common IPATH += $(SDK_PATH)/drivers_nrf/uart endif -ifeq ($(BOARD_USE_USB_CDC),1) -# pinconfig is required for 840 for CF2 +ifeq ($(BOARD_USE_USB),1) +# pinconfig is required for CF2 C_SRC += src/boards/$(BOARD)/pinconfig.c # USB Application ( MSC + UF2 ) @@ -225,13 +219,9 @@ C_SRC += \ $(TUSB_PATH)/class/cdc/cdc_device.c \ $(TUSB_PATH)/class/msc/msc_device.c \ $(TUSB_PATH)/tusb.c - -# endif -#------------------------------------------------------------------------------ # Assembly Files -#------------------------------------------------------------------------------ ASM_SRC = $(NRFX_PATH)/mdk/gcc_startup_$(MCU_SUB_VARIANT).S #------------------------------------------------------------------------------ diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 98d8adba..875ab6c4 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -354,7 +354,7 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout return err_code; } -uint32_t bootloader_app_register(void) +void bootloader_app_start(void) { // Disable all interrupts NVIC->ICER[0]=0xFFFFFFFF; @@ -396,7 +396,9 @@ uint32_t bootloader_app_register(void) // MBR use first 4-bytes of SRAM to store foward address *(uint32_t *)(0x20000000) = app_addr; } - return app_addr; + + // jump to app + bootloader_util_app_start(app_addr); } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h index 05306ae8..2cf52f72 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h @@ -51,7 +51,7 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout * address. * */ -uint32_t bootloader_app_register(void); +void bootloader_app_start(void); /**@brief Function for retrieving the bootloader settings. * diff --git a/src/boards/boards.c b/src/boards/boards.c index 63a0e2e4..c9314976 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -68,14 +68,17 @@ void board_init(void) NRF_CLOCK->TASKS_LFCLKSTART = 1UL; button_init(BUTTON_DFU, BUTTON_DFU_PULL); + #if defined(PIN_DFU_ACTIVATE) #if PIN_DFU_ACTIVATE!=BUTTON_FRESET button_init(BUTTON_FRESET, BUTTON_FRESET_PULL); #endif #endif + #if defined(PIN_DFU_ACTIVATE) button_init(PIN_DFU_ACTIVATE, PIN_DFU_ACTIVATE_PULL); #endif + NRFX_DELAY_US(100); // wait for the pin state is stable #if LEDS_NUMBER > 0 diff --git a/src/main.c b/src/main.c index f5e5bc63..5cf705fe 100644 --- a/src/main.c +++ b/src/main.c @@ -179,12 +179,7 @@ bool is_ota(void) return _ota_dfu; } -/** - * @brief Perform DFU if requested via flags, button pushes or the DFU activation pin. - * - * @return true DFU was requested via the activation pin. - */ -static bool check_dfu_mode(void); +static void check_dfu_mode(void); static uint32_t ble_stack_init(void); // The SoftDevice must only be initialized if a chip reset has occurred. @@ -230,7 +225,7 @@ int main(void) // Check all inputs and enter DFU if needed // Return when DFU process is complete (or not entered at all) - bool dfu_activate = check_dfu_mode(); + check_dfu_mode(); // Reset peripherals board_teardown(); @@ -258,27 +253,15 @@ int main(void) // clear in case we kept DFU_DBL_RESET_APP there (*dbl_reset_mem) = 0; - // register the app - uint32_t app_addr = bootloader_app_register(); - if (!dfu_activate) { - // jump to app when DFU not enabled via the activation pin (preserving previous behavior) - // otherwise, simply reset, allowing the host MCU to control the behavior on boot via the activation pin. - // The host MCU may keep the device in bootloader mode via the DFU activation pin when there are more - // binaries to flash (e.g. QSPI flash data) - bootloader_util_app_start(app_addr); - } + // start application + bootloader_app_start(); } NVIC_SystemReset(); } -/** - * @brief Runs DFU if requested by flags, or via the DFU activation pin. - * - * @return true DFU was requested via the activation pin - * @return false DFU was not requested, or if it was, not via the activation pin. - */ -static bool check_dfu_mode(void) +// Perform DFU if requested via flags, button pushes or the DFU activation pin. +static void check_dfu_mode(void) { uint32_t const gpregret = NRF_POWER->GPREGRET; @@ -302,16 +285,15 @@ static bool check_dfu_mode(void) // Clear GPREGRET if it is our values if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; + // skip dfu entirely + if (dfu_skip) return; + // dfu activation pin for external control of DFU bool dfu_activate = false; - bool dfu_activate_present = false; bool frst_skip = false; #if PIN_DFU_ACTIVATE_PRESENT - NRFX_DELAY_US(50000); // wait for the pin state is stable - dfu_activate = button_pressed(PIN_DFU_ACTIVATE, PIN_DFU_ACTIVATE_PULL); - dfu_activate_present = true; // when the FRST button is defined the same as the DFU activation line, FRST is not used. frst_skip = (PIN_DFU_ACTIVATE == BUTTON_FRESET); #pragma message "FRST is overridden by the DFU activate setting" @@ -320,10 +302,7 @@ static bool check_dfu_mode(void) dfu_start = dfu_start || dfu_activate; // DFU activation via the designated pin takes precedence - if (!dfu_activate_present || !dfu_activate) { - // skip dfu entirely - if (dfu_skip) return false; - + if (!PIN_DFU_ACTIVATE_PRESENT || !dfu_activate) { /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ // DFU button pressed dfu_start = dfu_start || button_pressed(BUTTON_DFU, BUTTON_DFU_PULL); @@ -371,11 +350,7 @@ static bool check_dfu_mode(void) (*dbl_reset_mem) = 0; } - NRFX_DELAY_US(500); // wait for the pin state is stable - - /* - * Enable UART for MCU to MCU transfers. - */ + // Enable UART for MCU to MCU transfers. #if PIN_DFU_ACTIVATE_PRESENT if (dfu_activate) { useSerialTransport(); @@ -422,7 +397,14 @@ static bool check_dfu_mode(void) channel_teardown(); } } - return dfu_activate; + + // Simply reset, allowing the host MCU to control the behavior on boot via the activation pin. + // The host MCU may keep the device in bootloader mode via the DFU activation pin when there are more + // binaries to flash (e.g. QSPI flash data) + if (PIN_DFU_ACTIVATE_PRESENT && dfu_activate) + { + NVIC_SystemReset(); + } }