Skip to content

Commit f1b4740

Browse files
authored
Merge pull request #196 from lyusupov/BUTTON_DFU_WAKEUP
Improvement/fix of system wake up by BUTTON_DFU GPIO
2 parents 5e6690e + 0098324 commit f1b4740

File tree

1 file changed

+69
-59
lines changed

1 file changed

+69
-59
lines changed

src/main.c

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,20 @@ void usb_teardown(void);
9797
*/
9898

9999
/* Magic that written to NRF_POWER->GPREGRET by application when it wish to go into DFU
100-
* - DFU_MAGIC_OTA_APPJUM used by BLEDfu service : SD is already init
101-
* - DFU_MAGIC_OTA_RESET entered by soft reset : SD is not init
102-
* - DFU_MAGIC_SERIAL_ONLY_RESET with CDC interface only
103-
* - DFU_MAGIC_UF2_RESET with CDC and MSC interfaces
100+
* - DFU_MAGIC_OTA_APPJUM : used by BLEDfu service, SD is already inited
101+
* - DFU_MAGIC_OTA_RESET : entered by soft reset, SD is not inited yet
102+
* - DFU_MAGIC_SERIAL_ONLY_RESET : with CDC interface only
103+
* - DFU_MAGIC_UF2_RESET : with CDC and MSC interfaces
104+
* - DFU_MAGIC_SKIP : skip DFU entirely including double reset delay
104105
*
105106
* Note: for DFU_MAGIC_OTA_APPJUM Softdevice must not initialized.
106107
* since it is already in application. In all other case of OTA SD must be initialized
107108
*/
108-
#define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1
109+
#define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1
109110
#define DFU_MAGIC_OTA_RESET 0xA8
110111
#define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e
111112
#define DFU_MAGIC_UF2_RESET 0x57
113+
#define DFU_MAGIC_SKIP 0x6d
112114

113115
#define DFU_DBL_RESET_MAGIC 0x5A1AD5 // SALADS
114116
#define DFU_DBL_RESET_APP 0x4ee5677e
@@ -176,8 +178,10 @@ int main(void)
176178
bool dfu_start = _ota_dfu || serial_only_dfu || uf2_dfu ||
177179
(((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk));
178180

181+
bool const dfu_skip = (NRF_POWER->GPREGRET == DFU_MAGIC_SKIP);
182+
179183
// Clear GPREGRET if it is our values
180-
if (dfu_start) NRF_POWER->GPREGRET = 0;
184+
if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0;
181185

182186
// Save bootloader version to pre-defined register, retrieved by application
183187
// TODO move to CF2
@@ -200,79 +204,85 @@ int main(void)
200204
}
201205

202206
/*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
203-
// DFU button pressed
204-
dfu_start = dfu_start || button_pressed(BUTTON_DFU);
207+
if ( !dfu_skip )
208+
{
209+
// DFU button pressed
210+
dfu_start = dfu_start || (button_pressed(BUTTON_DFU) && !dfu_skip);
205211

206-
// DFU + FRESET are pressed --> OTA
207-
_ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
212+
// DFU + FRESET are pressed --> OTA
213+
_ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
208214

209-
bool const valid_app = bootloader_app_is_valid();
210-
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
215+
bool const valid_app = bootloader_app_is_valid();
216+
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
211217

212-
if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET())
213-
dfu_start = 1;
218+
if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1;
214219

215-
// App mode: register 1st reset and DFU startup (nrf52832)
216-
if ( ! (just_start_app || dfu_start || !valid_app) )
217-
{
218-
// Register our first reset for double reset detection
219-
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
220+
// App mode: register 1st reset and DFU startup (nrf52832)
221+
if ( ! (just_start_app || dfu_start || !valid_app) )
222+
{
223+
// Register our first reset for double reset detection
224+
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
220225

221226
#ifdef NRF52832_XXAA
222-
/* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
223-
* to support auto programming from Arduino IDE
224-
*
225-
* Note: Supposedly during this time if RST is press, it will count as double reset.
226-
* However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
227-
*/
228-
bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false);
227+
/* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
228+
* to support auto programming from Arduino IDE
229+
*
230+
* Note: Supposedly during this time if RST is press, it will count as double reset.
231+
* However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
232+
*/
233+
bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false);
229234
#else
230-
// if RST is pressed during this delay --> if will enter dfu
231-
NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
235+
// if RST is pressed during this delay --> if will enter dfu
236+
NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
232237
#endif
233-
}
234-
235-
if (APP_ASKS_FOR_SINGLE_TAP_RESET())
236-
(*dbl_reset_mem) = DFU_DBL_RESET_APP;
237-
else
238-
(*dbl_reset_mem) = 0;
239-
240-
if ( dfu_start || !valid_app )
241-
{
242-
if ( _ota_dfu )
243-
{
244-
led_state(STATE_BLE_DISCONNECTED);
245-
softdev_init(!sd_inited);
246-
sd_inited = true;
247-
}
248-
else
249-
{
250-
led_state(STATE_USB_UNMOUNTED);
251-
usb_init(serial_only_dfu);
252238
}
253239

254-
// Initiate an update of the firmware.
255-
if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu)
240+
if (APP_ASKS_FOR_SINGLE_TAP_RESET())
256241
{
257-
// If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app.
258-
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 3000, true) );
242+
(*dbl_reset_mem) = DFU_DBL_RESET_APP;
259243
}
260244
else
261245
{
262-
// No timeout if bootloader requires user action (double-reset).
263-
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0, false) );
246+
(*dbl_reset_mem) = 0;
264247
}
265248

266-
if ( _ota_dfu )
267-
{
268-
sd_softdevice_disable();
269-
}else
249+
if ( dfu_start || !valid_app )
270250
{
271-
usb_teardown();
251+
if ( _ota_dfu )
252+
{
253+
led_state(STATE_BLE_DISCONNECTED);
254+
softdev_init(!sd_inited);
255+
sd_inited = true;
256+
}
257+
else
258+
{
259+
led_state(STATE_USB_UNMOUNTED);
260+
usb_init(serial_only_dfu);
261+
}
262+
263+
// Initiate an update of the firmware.
264+
if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu)
265+
{
266+
// If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app.
267+
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 3000, true) );
268+
}
269+
else
270+
{
271+
// No timeout if bootloader requires user action (double-reset).
272+
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0, false) );
273+
}
274+
275+
if ( _ota_dfu )
276+
{
277+
sd_softdevice_disable();
278+
}else
279+
{
280+
usb_teardown();
281+
}
272282
}
273283
}
274284

275-
// Reset Board
285+
// Reset peripherals
276286
board_teardown();
277287

278288
/* Jump to application if valid

0 commit comments

Comments
 (0)