Skip to content
Merged
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
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ it and is upstream Adafruit history, kept for provenance.
- A device with no valid application that is plugged into a USB host comes up as a UF2 drive showing NO FIRMWARE instead of waiting for a phone. On battery (no VBUS) it goes straight to the BLE OTA wait, and with VBUS but no host enumerating within 3 s (a charger or power bank) it falls through to the same wait. A cabled board with no application returns to the drive after an aborted copy, and after an eject on boards built with `UF2_EXIT_ON_EJECT` (`mesh_tracker_x1`, `t1000_e`). When the cable is pulled while the drive is up (VBUS gone for 250 ms), it goes to the BLE OTA wait. Plugging a cable into a board with no application that is waiting for BLE, with no phone connected, brings the drive up (VBUS present for 250 ms); a cable already present when the wait began, or a phone connected, leaves the wait alone.
- A UF2 application copy marks `bank_0` invalid when its first application block arrives, so a cable pulled mid-copy leaves the device with no application instead of an old `bank_0` marked valid over a half-written image. The completion path records the real application size as before.
- A bootloader self-update whose staged image would overwrite the tail of the installed application (one larger than 744 KB on S140 6.1.1 or 740 KB on 7.3.0) marks `bank_0` invalid first, so the device comes up in DFU with no application instead of booting a corrupted one.
- A central that disconnects mid-transfer can start a fresh BLE DFU without the board being reset.
- DFU screens on I2C mono OLEDs (SSD1306 and SH1106), with a four-line layout: title, mode, version, and banner. A board opts in by defining `DISPLAY_PIN_SDA` in its `board.h`; `boards.h` rejects a board that also defines `DISPLAY_PIN_SCK`, since TWIM0 and SPIM0 share a peripheral. The bootloader probes 0x3C and 0x3D and reads the controller type off the panel, and a board with no panel shows nothing and otherwise behaves as before. Enabled on `wiscore_rak4631_board`, `wiscore_rak3401`, `wio_tracker_l1`, `promicro_nrf52840`, `xiao_nrf52840_ble`, and `xiao_nrf52840_ble_sense`, for about 2 KB of bootloader flash each. Verified on the RAK4631 and the Wio Tracker L1; the other four follow their firmware variants' pins. On the RAK4631 and RAK3401, DFU raises the switched 3V3_S rail (WB_IO2) that feeds the WisBlock slots, and lowers it again when no panel answers.
- Fixed an out-of-bounds write in `printicon()` on the 160x80 `heltec_t096` and `heltec_t1`, where the third drag icon ran past the end of `frame_buf`. Those boards place it inside the panel, and `printicon()` skips any icon that would land outside.
- Fixed BLE OTA started from an application's buttonless DFU falling back to the application after about 10 s. The 0xB1 entry now restarts through the 0xA8 path, so the bootloader initializes the SoftDevice itself; the peer data for reconnection survives the reset.
Expand Down
3 changes: 3 additions & 0 deletions lib/sdk11/components/drivers_nrf/pstorage/pstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ uint32_t pstorage_load(uint8_t * p_dest,
*/
uint32_t pstorage_clear(pstorage_handle_t * p_base_id, pstorage_size_t size);

/**@brief Drops buffered stores that wait on a lazy erase, without calling their callbacks. */
void pstorage_discard_pending(void);

/**@brief Function for getting the number of pending operations with the module.
*
* @param[out] p_count Number of storage operations pending with the module. If 0, there are no
Expand Down
14 changes: 14 additions & 0 deletions lib/sdk11/components/drivers_nrf/pstorage/pstorage_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,20 @@ uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
}


void pstorage_discard_pending(void)
{
// The head entry stays when its store is in flight; its completion pops it.
uint8_t keep = m_processing_pending ? 1 : 0;

while (m_pending_count > keep)
{
m_pending_write_idx = (m_pending_write_idx + PENDING_PACKET_COUNT - 1) % PENDING_PACKET_COUNT;
m_pending_packets[m_pending_write_idx].valid = false;
m_pending_count--;
}
}


/**
* @}
*/
3 changes: 3 additions & 0 deletions lib/sdk11/components/libraries/bootloader_dfu/dfu.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ uint32_t dfu_image_activate(void);
*/
void dfu_reset(void);

/**@brief Abandons an unfinished transfer so a new start packet is accepted, without a system reset. */
void dfu_reset_session(void);

/**@brief Function for validating that new bootloader has been correctly installed.
*
* @return NRF_SUCCESS if install was successful. NRF_ERROR_NULL if the images differs.
Expand Down
17 changes: 17 additions & 0 deletions lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,23 @@ uint32_t dfu_image_activate()
}


void dfu_reset_session(void)
{
if (m_dfu_state == DFU_STATE_IDLE || m_dfu_state == DFU_STATE_INIT_ERROR) return;

// Issued flash ops finish on their own: a stale store is dropped by the RX_DATA_PKT gate, and a
// stale clear can only report a page that is erased and queued ahead of every new store.
pstorage_discard_pending();

dfu_page_erased = NULL;
dfu_image_page_count = 0;
m_init_packet_length = 0;
m_image_crc = 0;
m_data_received = 0;
m_dfu_state = DFU_STATE_IDLE;
}


void dfu_reset(void)
{
dfu_update_status_t update_status;
Expand Down
19 changes: 19 additions & 0 deletions lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,24 @@ static void accum_flush(ble_dfu_t * p_dfu)
m_accum_bytes_pending = 0;
}

/**@brief Drops the unfinished transfer so the next connection can start over. */
static void session_reset(void)
{
dfu_reset_session();
(void) hci_mem_pool_open();

m_num_of_firmware_bytes_rcvd = 0;
m_pkt_notif_target = 0;
m_pkt_notif_target_cnt = 0;
m_pkt_rcpt_notif_enabled = false;
m_pkt_type = PKT_TYPE_INVALID;
mp_final_packet = NULL;
m_accum_len = 0;
m_accum_active = false;
m_accum_bytes_pending = 0;
m_reported_image_size = 0;
}

/**@brief Function for processing application data written by the peer to the DFU Packet
* Characteristic.
*
Expand Down Expand Up @@ -934,6 +952,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
// disconnect triggered by the DFU Controller before the firmware update was
// complete).
// Restart advertising so that the DFU Controller can reconnect if possible.
session_reset();
advertising_start();
}

Expand Down
Loading