add #26 double reset to DFU, only work with nrf52840 (won't work with nrf52832)
This commit is contained in:
		@@ -32,6 +32,7 @@ Get the code with following command:
 | 
			
		||||
 | 
			
		||||
There are 2 pins **DFU & FRST** that bootloader will check upon reset/power
 | 
			
		||||
 | 
			
		||||
- `Double Reset` Reset twice within 500 ms will enter DFU with UF2 and CDC support (only works with nRF52840)
 | 
			
		||||
- `DFU = Low and FRST = High` Enter DFU with UF2 and CDC support
 | 
			
		||||
- `DFU = Low and FRST = Low` Enter DFU with OTA, can be upgraded with mobile application such as Nordic nrfConnect/Toolbox
 | 
			
		||||
- `DFU = High and FRST = Low` Factory Reset mode, erase firmware application and its data
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,10 @@ MEMORY
 | 
			
		||||
  FLASH (rx) : ORIGIN = 0x74000, LENGTH = 0xA000 /* 40 KB */
 | 
			
		||||
 | 
			
		||||
  /** RAM Region for bootloader. */
 | 
			
		||||
  RAM (rwx) :  ORIGIN = 0x20003000, LENGTH = 0x20007F80-0x20003000
 | 
			
		||||
  RAM (rwx) :  ORIGIN = 0x20003000, LENGTH = 0x20007F7C-0x20003000
 | 
			
		||||
 | 
			
		||||
  /* Location for double reset detection, no init */
 | 
			
		||||
  DBL_RESET (rwx) :  ORIGIN = 0x20007F7C, LENGTH = 0x04
 | 
			
		||||
 | 
			
		||||
  /** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
 | 
			
		||||
   *  from application to bootloader when using buttonluss DFU OTA. 
 | 
			
		||||
@@ -66,6 +69,11 @@ SECTIONS
 | 
			
		||||
  {
 | 
			
		||||
    KEEP(*(.uicrMbrParamsPageAddress))
 | 
			
		||||
  } > UICR_MBR_PARAM_PAGE
 | 
			
		||||
  
 | 
			
		||||
  .dbl_reset(NOLOAD) :
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
  } > DBL_RESET  
 | 
			
		||||
 | 
			
		||||
  /* No init RAM section in bootloader. Used for bond information exchange. */
 | 
			
		||||
  .noinit(NOLOAD) :
 | 
			
		||||
 
 | 
			
		||||
@@ -17,10 +17,14 @@ MEMORY
 | 
			
		||||
  /* Avoid conflict with NOINIT for OTA bond sharing */
 | 
			
		||||
  RAM (rwx) :  ORIGIN = 0x20008000, LENGTH = 0x20040000-0x20008000
 | 
			
		||||
 | 
			
		||||
  /* Location for double reset detection, no init */
 | 
			
		||||
  DBL_RESET (rwx) :  ORIGIN = 0x20007F7C, LENGTH = 0x04
 | 
			
		||||
  
 | 
			
		||||
  /** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
 | 
			
		||||
   *  from application to bootloader when using buttonluss DFU OTA. 
 | 
			
		||||
   */
 | 
			
		||||
  NOINIT (rwx) :  ORIGIN = 0x20007F80, LENGTH = 0x80
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  /** Location of bootloader setting in flash. */
 | 
			
		||||
  BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x000FF000, LENGTH = 0x1000
 | 
			
		||||
@@ -68,11 +72,17 @@ SECTIONS
 | 
			
		||||
    KEEP(*(.uicrMbrParamsPageAddress))
 | 
			
		||||
  } > UICR_MBR_PARAM_PAGE
 | 
			
		||||
 | 
			
		||||
  .dbl_reset(NOLOAD) :
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
  } > DBL_RESET
 | 
			
		||||
 | 
			
		||||
  /* No init RAM section in bootloader. Used for bond information exchange. */
 | 
			
		||||
  .noinit(NOLOAD) :
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
  } > NOINIT
 | 
			
		||||
 | 
			
		||||
  /* other placements follow here... */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/main.c
									
									
									
									
									
								
							@@ -98,6 +98,10 @@ void usb_teardown(void);
 | 
			
		||||
#define DFU_MAGIC_SERIAL_ONLY_RESET     0x4e
 | 
			
		||||
#define DFU_MAGIC_UF2_RESET             0x57
 | 
			
		||||
 | 
			
		||||
#define DFU_DBL_RESET_MAGIC             0x5A1AD5      // SALADS
 | 
			
		||||
#define DFU_DBL_RESET_DELAY             500
 | 
			
		||||
#define DFU_DBL_RESET_MEM               0x20007F7C
 | 
			
		||||
 | 
			
		||||
#define BOOTLOADER_VERSION_REGISTER     NRF_TIMER2->CC[0]
 | 
			
		||||
#define DFU_SERIAL_STARTUP_INTERVAL     1000
 | 
			
		||||
 | 
			
		||||
@@ -119,6 +123,8 @@ STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
 | 
			
		||||
void adafruit_factory_reset(void);
 | 
			
		||||
static uint32_t softdev_init(bool init_softdevice);
 | 
			
		||||
 | 
			
		||||
uint32_t* dbl_reset_mem = ((uint32_t*)  DFU_DBL_RESET_MEM );
 | 
			
		||||
 | 
			
		||||
// true if ble, false if serial
 | 
			
		||||
bool _ota_dfu = false;
 | 
			
		||||
bool _ota_connected = false;
 | 
			
		||||
@@ -146,7 +152,8 @@ int main(void)
 | 
			
		||||
  bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET);
 | 
			
		||||
 | 
			
		||||
  // start either serial, uf2 or ble
 | 
			
		||||
  bool dfu_start = _ota_dfu || serial_only_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET);
 | 
			
		||||
  bool dfu_start = _ota_dfu || serial_only_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET) ||
 | 
			
		||||
                    (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk));
 | 
			
		||||
 | 
			
		||||
  // Clear GPREGRET if it is our values
 | 
			
		||||
  if (dfu_start) NRF_POWER->GPREGRET = 0;
 | 
			
		||||
@@ -174,7 +181,34 @@ int main(void)
 | 
			
		||||
  // DFU + FRESET are pressed --> OTA
 | 
			
		||||
  _ota_dfu = _ota_dfu  || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
 | 
			
		||||
 | 
			
		||||
  if ( dfu_start || !bootloader_app_is_valid(DFU_BANK_0_REGION_START) )
 | 
			
		||||
 | 
			
		||||
  bool const valid_app = bootloader_app_is_valid(DFU_BANK_0_REGION_START);
 | 
			
		||||
 | 
			
		||||
  // App mode: register 1st reset and DFU startup (nrf52832)
 | 
			
		||||
  if ( ! (dfu_start || !valid_app) )
 | 
			
		||||
  {
 | 
			
		||||
    // Register our first reset for double reset detection
 | 
			
		||||
    (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
 | 
			
		||||
 | 
			
		||||
#ifdef NRF52832_XXAA
 | 
			
		||||
    /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
 | 
			
		||||
     * to support auto programming from Arduino IDE
 | 
			
		||||
     *
 | 
			
		||||
     * Note: Supposedly during this time if RST is press, it will count as double reset.
 | 
			
		||||
     * However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
 | 
			
		||||
     */
 | 
			
		||||
    bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL);
 | 
			
		||||
#else
 | 
			
		||||
    led_on(LED_RED); // turn on LED to signal user
 | 
			
		||||
    // if RST is pressed during this delay --> if will enter dfu
 | 
			
		||||
    NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
 | 
			
		||||
    led_off(LED_RED);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  (*dbl_reset_mem) = 0;
 | 
			
		||||
 | 
			
		||||
  if ( dfu_start || !valid_app )
 | 
			
		||||
  {
 | 
			
		||||
    if ( _ota_dfu )
 | 
			
		||||
    {
 | 
			
		||||
@@ -204,15 +238,6 @@ int main(void)
 | 
			
		||||
      usb_teardown();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#ifdef NRF52832_XXAA
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    /* Adafruit Modification
 | 
			
		||||
     * Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
 | 
			
		||||
     * to support auto programming from Arduino IDE */
 | 
			
		||||
    bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // Adafruit Factory reset
 | 
			
		||||
  if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user