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 | 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 = 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 = 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 | - `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 */ |   FLASH (rx) : ORIGIN = 0x74000, LENGTH = 0xA000 /* 40 KB */ | ||||||
|  |  | ||||||
|   /** RAM Region for bootloader. */ |   /** 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 |   /** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information | ||||||
|    *  from application to bootloader when using buttonluss DFU OTA.  |    *  from application to bootloader when using buttonluss DFU OTA.  | ||||||
| @@ -67,6 +70,11 @@ SECTIONS | |||||||
|     KEEP(*(.uicrMbrParamsPageAddress)) |     KEEP(*(.uicrMbrParamsPageAddress)) | ||||||
|   } > UICR_MBR_PARAM_PAGE |   } > UICR_MBR_PARAM_PAGE | ||||||
|    |    | ||||||
|  |   .dbl_reset(NOLOAD) : | ||||||
|  |   { | ||||||
|  |  | ||||||
|  |   } > DBL_RESET   | ||||||
|  |  | ||||||
|   /* No init RAM section in bootloader. Used for bond information exchange. */ |   /* No init RAM section in bootloader. Used for bond information exchange. */ | ||||||
|   .noinit(NOLOAD) : |   .noinit(NOLOAD) : | ||||||
|   { |   { | ||||||
|   | |||||||
| @@ -17,11 +17,15 @@ MEMORY | |||||||
|   /* Avoid conflict with NOINIT for OTA bond sharing */ |   /* Avoid conflict with NOINIT for OTA bond sharing */ | ||||||
|   RAM (rwx) :  ORIGIN = 0x20008000, LENGTH = 0x20040000-0x20008000 |   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 |   /** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information | ||||||
|    *  from application to bootloader when using buttonluss DFU OTA.  |    *  from application to bootloader when using buttonluss DFU OTA.  | ||||||
|    */ |    */ | ||||||
|   NOINIT (rwx) :  ORIGIN = 0x20007F80, LENGTH = 0x80 |   NOINIT (rwx) :  ORIGIN = 0x20007F80, LENGTH = 0x80 | ||||||
|    |    | ||||||
|  |  | ||||||
|   /** Location of bootloader setting in flash. */ |   /** Location of bootloader setting in flash. */ | ||||||
|   BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x000FF000, LENGTH = 0x1000 |   BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x000FF000, LENGTH = 0x1000 | ||||||
|  |  | ||||||
| @@ -68,11 +72,17 @@ SECTIONS | |||||||
|     KEEP(*(.uicrMbrParamsPageAddress)) |     KEEP(*(.uicrMbrParamsPageAddress)) | ||||||
|   } > UICR_MBR_PARAM_PAGE |   } > UICR_MBR_PARAM_PAGE | ||||||
|  |  | ||||||
|  |   .dbl_reset(NOLOAD) : | ||||||
|  |   { | ||||||
|  |  | ||||||
|  |   } > DBL_RESET | ||||||
|  |  | ||||||
|   /* No init RAM section in bootloader. Used for bond information exchange. */ |   /* No init RAM section in bootloader. Used for bond information exchange. */ | ||||||
|   .noinit(NOLOAD) : |   .noinit(NOLOAD) : | ||||||
|   { |   { | ||||||
|  |  | ||||||
|   } > NOINIT |   } > NOINIT | ||||||
|  |  | ||||||
|   /* other placements follow here... */ |   /* 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_SERIAL_ONLY_RESET     0x4e | ||||||
| #define DFU_MAGIC_UF2_RESET             0x57 | #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 BOOTLOADER_VERSION_REGISTER     NRF_TIMER2->CC[0] | ||||||
| #define DFU_SERIAL_STARTUP_INTERVAL     1000 | #define DFU_SERIAL_STARTUP_INTERVAL     1000 | ||||||
|  |  | ||||||
| @@ -119,6 +123,8 @@ STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000); | |||||||
| void adafruit_factory_reset(void); | void adafruit_factory_reset(void); | ||||||
| static uint32_t softdev_init(bool init_softdevice); | 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 | // true if ble, false if serial | ||||||
| bool _ota_dfu = false; | bool _ota_dfu = false; | ||||||
| bool _ota_connected = false; | bool _ota_connected = false; | ||||||
| @@ -146,7 +152,8 @@ int main(void) | |||||||
|   bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET); |   bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET); | ||||||
|  |  | ||||||
|   // start either serial, uf2 or ble |   // 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 |   // Clear GPREGRET if it is our values | ||||||
|   if (dfu_start) NRF_POWER->GPREGRET = 0; |   if (dfu_start) NRF_POWER->GPREGRET = 0; | ||||||
| @@ -174,7 +181,34 @@ int main(void) | |||||||
|   // DFU + FRESET are pressed --> OTA |   // DFU + FRESET are pressed --> OTA | ||||||
|   _ota_dfu = _ota_dfu  || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ; |   _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 ) |     if ( _ota_dfu ) | ||||||
|     { |     { | ||||||
| @@ -204,15 +238,6 @@ int main(void) | |||||||
|       usb_teardown(); |       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 |   // Adafruit Factory reset | ||||||
|   if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) |   if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user