Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ dkms.conf

segger/Output
_build/
cmake-build-*/
bin/
*.emSession
*.jlink
Expand All @@ -68,4 +69,3 @@ Makefile.user

# Exclude all SoftDevice S340 files
lib/softdevice/s340*

130 changes: 78 additions & 52 deletions lib/sdk11/components/libraries/bootloader_dfu/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,29 @@ typedef enum
BOOTLOADER_RESET_TO_SELF, /**< Bootloader status field for indicating that a reset has been requested and current update process should be aborted and the bootloader must be reentered. */
} bootloader_status_t;

static pstorage_handle_t m_bootsettings_handle; /**< Pstorage handle to use for registration and identifying the bootloader module on subsequent calls to the pstorage module for load and store of bootloader setting in flash. */
static bootloader_status_t m_update_status; /**< Current update status for the bootloader module to ensure correct behaviour when updating settings and when update completes. */
static bool m_cancel_timeout_on_usb; /**< If set the timeout is cancelled when USB is enumerated. Otherwise, the timeout is only cancelled when DFU update is started. */

APP_TIMER_DEF( _dfu_startup_timer );
volatile bool dfu_startup_packet_received = false;
static pstorage_handle_t m_bootsettings_handle; /**< Pstorage handle to use for registration and identifying the bootloader module on subsequent calls to the pstorage module for load and store of bootloader setting in flash. */
static bootloader_status_t m_update_status; /**< Current update status for the bootloader module to ensure correct behaviour when updating settings and when update completes. */
static bool m_cancel_timeout_on_usb; /**< If set the timeout is cancelled when USB is enumerated. Otherwise, the timeout is only cancelled when DFU update is started. */
static bool m_usb_was_mounted; /**< Tracks whether the USB DFU session was ever enumerated so we can exit when cable is later removed. */
static bool m_startup_dfu_has_activity; /**< Tracks whether any valid serial or UF2 update traffic has started. */

APP_TIMER_DEF( _dfu_startup_timer );

static void bootloader_timeout_startup_dfu(void)
{
if (!m_startup_dfu_has_activity)
{
dfu_update_status_t update_status;
update_status.status_code = DFU_TIMEOUT;

bootloader_dfu_update_process(update_status);
}
}

void bootloader_dfu_activity_mark(void)
{
m_startup_dfu_has_activity = true;
}

/**@brief Function for handling callbacks from pstorage module.
*
Expand All @@ -79,26 +96,20 @@ static void pstorage_callback_handler(pstorage_handle_t * p_handle,
/* Terminate the forced DFU mode on startup if no packets is received
* by put an terminal handler to scheduler
*/
static void dfu_startup_timer_handler(void * p_context)
{
#ifdef NRF_USBD
if (m_cancel_timeout_on_usb && tud_mounted())
{
return;
}
#endif

// nRF52832 forced DFU on startup
// No packets are received within timeout, exit DFU mode
// dfu_startup_packet_received is set by process_dfu_packet() in dfu_transport_serial.c
if (!dfu_startup_packet_received)
{
dfu_update_status_t update_status;
update_status.status_code = DFU_TIMEOUT;

bootloader_dfu_update_process(update_status);
}
}
static void dfu_startup_timer_handler(void * p_context)
{
#ifdef NRF_USBD
if (m_cancel_timeout_on_usb && tud_mounted())
{
m_usb_was_mounted = true;
return;
}
#endif

// nRF52832 forced DFU on startup
// No update activity is received within timeout, exit DFU mode
bootloader_timeout_startup_dfu();
}

/**@brief Function for waiting for events.
*
Expand Down Expand Up @@ -126,14 +137,29 @@ static void wait_for_events(void)
// Event received. Process it from the scheduler.
app_sched_execute();

#ifdef NRF_USBD
// skip if usb is not inited ( e.g OTA / finializing sd/bootloader )
if ( tusb_inited() )
{
tud_task();
tud_cdc_write_flush();
}
#endif
#ifdef NRF_USBD
// skip if usb is not inited ( e.g OTA / finializing sd/bootloader )
if ( tusb_inited() )
{
tud_task();
tud_cdc_write_flush();
}

if (m_cancel_timeout_on_usb)
{
if (tusb_inited() && tud_mounted())
{
m_usb_was_mounted = true;
}
else if (m_usb_was_mounted &&
!(NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk))
{
// Only exit startup DFU after USB was actually unplugged, not on a host-side
// re-enumeration or temporary unmount.
bootloader_timeout_startup_dfu();
}
}
#endif

if ((m_update_status == BOOTLOADER_COMPLETE) ||
(m_update_status == BOOTLOADER_TIMEOUT) ||
Expand Down Expand Up @@ -353,31 +379,31 @@ uint32_t bootloader_init(void)
}


uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout_on_usb)
{
uint32_t err_code;

m_cancel_timeout_on_usb = cancel_timeout_on_usb && !ota;

// Clear swap if banked update is used.
err_code = dfu_init();
VERIFY_SUCCESS(err_code);
uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout_on_usb)
{
uint32_t err_code;

m_cancel_timeout_on_usb = cancel_timeout_on_usb && !ota;
m_usb_was_mounted = false;
m_startup_dfu_has_activity = false;

// Clear swap if banked update is used.
err_code = dfu_init();
VERIFY_SUCCESS(err_code);

if ( ota )
{
err_code = dfu_transport_ble_update_start();
}else
{
// DFU mode with timeout can be
// - Forced startup DFU for nRF52832 or
// - Makecode single tap reset but no enumerated (battery power)
if ( timeout_ms )
{
dfu_startup_packet_received = false;

app_timer_create(&_dfu_startup_timer, APP_TIMER_MODE_SINGLE_SHOT, dfu_startup_timer_handler);
app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL);
}
// - Forced startup DFU for nRF52832 or
// - Makecode single tap reset but no enumerated (battery power)
if ( timeout_ms )
{
app_timer_create(&_dfu_startup_timer, APP_TIMER_MODE_SINGLE_SHOT, dfu_startup_timer_handler);
app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL);
}

err_code = dfu_transport_serial_update_start();
}
Expand Down
17 changes: 12 additions & 5 deletions lib/sdk11/components/libraries/bootloader_dfu/bootloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,18 @@ void bootloader_app_start(void);
*/
void bootloader_settings_get(bootloader_settings_t * const p_settings);

/**@brief Function for processing DFU status update.
*
* @param[in] update_status DFU update status.
*/
void bootloader_dfu_update_process(dfu_update_status_t update_status);
/**@brief Function for processing DFU status update.
*
* @param[in] update_status DFU update status.
*/
void bootloader_dfu_update_process(dfu_update_status_t update_status);

/**@brief Mark that startup DFU has received valid update activity.
*
* @details This suppresses the startup timeout or USB unplug fallback that is only
* meant for the "entered bootloader, but never started an update" case.
*/
void bootloader_dfu_activity_mark(void);

/**@brief Function getting state of SoftDevice update in progress.
* After a successfull SoftDevice transfer the system restarts in orderto disable SoftDevice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
*
*/

#include "dfu_transport.h"
#include <stddef.h>
#include "dfu.h"
#include <dfu_types.h>
#include "dfu_transport.h"
#include <stddef.h>
#include "bootloader.h"
#include "dfu.h"
#include <dfu_types.h>
#include "app_error.h"
#include "app_util.h"
#include "hci_transport.h"
Expand Down Expand Up @@ -197,9 +198,8 @@ static void process_dfu_packet(void * p_event_data, uint16_t event_size)
uint32_t index;
dfu_update_packet_t * packet;

// Adafruit modification for startup dfu
extern bool dfu_startup_packet_received;
dfu_startup_packet_received = true;
// Mark that startup DFU has transitioned into a real update flow.
bootloader_dfu_activity_mark();

while (false == DATA_QUEUE_EMPTY())
{
Expand Down
12 changes: 11 additions & 1 deletion src/usb/msc_uf2.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,19 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
uint32_t count = 0;
while ( count < bufsize )
{
int written;

// Consider non-uf2 block write as successful
// only break if write_block is busy with flashing (return 0)
if ( 0 == write_block(lba, buffer, &_wr_state) ) break;
written = write_block(lba, buffer, &_wr_state);
if ( written > 0 )
{
bootloader_dfu_activity_mark();
}
else if ( written == 0 )
{
break;
}

lba++;
buffer += 512;
Expand Down