Conversation
The no-init word at 0x20007F7C already survives a pin reset in order to detect a double tap. Make it hold a tap stage rather than a flag, so that a second tap arms DFU_TPL_RESET_MAGIC and waits one more 0.5s window before committing to USB DFU. A third tap inside that window selects BLE OTA DFU instead. The status LED blinks three times faster while the window is open. If it expires the device enters USB DFU exactly as before, just 0.5s later. This gives a route into BLE OTA DFU that does not depend on the running application cooperating, on the application being absent, or on knowing which button to hold. The RAK 4631 and RAK 3401 have no button route at all: BUTTON_1 and BUTTON_2 both sit on P0.08, which is not connected. TRIPLE_TAP_BLE_DFU defaults to 1 and a board can opt out by defining it as 0 in its board.h. It is forced off on nrf52832, where a GPIO reset clears SRAM and the tap state cannot survive, which is the same reason double tap detection is skipped there. Costs 224-240 bytes of flash. All 17 boards were built before and after; the fullest afterwards is heltec_t114 at 91.6% of the 38 KB region.
Dreikor17
force-pushed
the
feature/triple-tap-ble-dfu
branch
from
September 7, 2026 12:19
75ee35f to
1c2ba23
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
Description of Change
Adds a third tap to the reset gesture that already exists:
How it works
The no-init word at
0x20007F7Calready survives a pin reset in order to detect a double tap. It now holds a tap stage rather than a flag:DFU_DBL_RESET_MAGICmeans one tap seen, the newDFU_TPL_RESET_MAGICmeans two. The count has to live in that word because theDBL_RESETregion in the linker script is exactly 4 bytes, and theNOINITblock above it is the OTA bond exchange area.The second tap no longer falls straight through into USB DFU. It arms the third-tap magic and waits one more
DFU_TPL_RESET_DELAY— 0.5s, matching the existing double-tap window. A third tap inside that window is picked up on the next boot and forces_ota_dfu, routing into the BLE OTA path already used byDFU_MAGIC_OTA_RESET(bootloader_dfu_start(true, 0, false)). If the window expires, the device enters USB DFU exactly as before.The status LED blinks three times faster while the window is open, so it is visible that the third tap is available. It is restored before USB DFU starts, so neither destination sees an altered LED state.
Why
Most boards here already have a button route into BLE OTA DFU — either the
BUTTON_DFU+BUTTON_FRESETcombo, or the single-button idiom of pointing both at the same pin so that holding one button on boot enters OTA. This is not trying to replace that.What it adds is a route that needs no button at all, which matters in three cases:
BUTTON_1andBUTTON_2are bothP0.08, which the board.h comment notes is not connected. There is no button route on those two: BLE OTA DFU can only be entered from the running application (buttonless DFU service /GPREGRET), or by having no valid application at all. A device running firmware that exposes no DFU service has no way in short of SWD.Scope
TRIPLE_TAP_BLE_DFUdefaults to1. A board opts out by defining it as0in itsboard.h, which restores an immediate double-tap into USB DFU. It is forced off on nrf52832, where a GPIO reset clears SRAM so the tap state cannot survive — the same reason double-tap detection is already skipped there.Everything new is behind
#if TRIPLE_TAP_BLE_DFU, including the newled_state()case.Happy to narrow this to an opt-in for specific boards if you would rather — that is a one-line change to the default, and the per-board
#definemechanism is already in place.Trade-off
Double tap into USB DFU now takes 0.5s longer, on every board, because the bootloader has to wait to see whether a third tap is coming. That is inherent to the gesture and it is the main cost of this PR.
DFU_TPL_RESET_DELAYis a separate constant fromDFU_DBL_RESET_DELAYif you would prefer a different window.Flash cost
224–240 bytes. All 17 boards built from
masterand from this branch, with__DATE__/__TIME__pinned (src/usb/uf2/compile_date.hbakes them into the UF2 ghost FAT, so builds are otherwise not comparable):The fullest board after the change is
heltec_t114, with about 3.2 KB of the region still free.Testing
check_dfu_mode()and oneled_state()case — but that is reasoning, not evidence, and it is worth saying plainly given this now defaults to on everywhere.-Wall -Wextra -Werror.Also
README gains an Entering DFU mode section describing the tap behaviour, plus short pointers to it from Installation and Troubleshooting.