From d3802b5745a1e74df5dea34b672f2afbd694de00 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 16 Apr 2015 00:57:41 +0200
Subject: [PATCH]  Added "double-tap" feature to bootloader

Bootloader is activated by quickly double tapping to the reset button
---
 bootloaders/zero/main.c                       |  26 ++++++++++++++++++
 bootloaders/zero/main.h                       |  10 +++++++
 bootloaders/zero/samd21_sam_ba.bin            | Bin 6308 -> 6364 bytes
 bootloaders/zero/samd21j18a_flash.ld          |   2 +-
 .../gcc/flash_with_bootloader.ld              |   4 +--
 5 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/bootloaders/zero/main.c b/bootloaders/zero/main.c
index a1c76860..6d2dd05f 100644
--- a/bootloaders/zero/main.c
+++ b/bootloaders/zero/main.c
@@ -97,6 +97,32 @@ static void check_start_application(void)
         led_port->DIRSET.reg = (1<<30);
         led_port->OUTCLR.reg = (1<<30);
   
+#if defined(BOOT_DOUBLE_TAP_ADDRESS)
+	if (PM->RCAUSE.bit.POR)
+	{
+		/* On power-on initialize double-tap */
+		BOOT_DOUBLE_TAP_DATA = 0;
+	}
+	else
+	{
+		if (BOOT_DOUBLE_TAP_DATA == 0) {
+			/* First tap */
+			BOOT_DOUBLE_TAP_DATA = 1;
+
+			for (uint32_t i=0; i<50000; i++) /* 200ms */
+				/* force compiler to not optimize this... */
+				__asm__ __volatile__("");
+
+			/* Timeout happened, continue boot... */
+			BOOT_DOUBLE_TAP_DATA = 0;
+		} else {
+			/* Second tap, stay in bootloader */
+			BOOT_DOUBLE_TAP_DATA = 0;
+			return;
+		}
+	}
+#endif
+
 	uint32_t app_start_address;
 
 	/* Load the Reset Handler address of the application */
diff --git a/bootloaders/zero/main.h b/bootloaders/zero/main.h
index d1d6941a..d5e9a58a 100644
--- a/bootloaders/zero/main.h
+++ b/bootloaders/zero/main.h
@@ -34,6 +34,16 @@
 #define CPU_FREQUENCY                     8000000
 
 #define APP_START_ADDRESS                 0x00002000
+
+/*
+ * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
+ * quickly tapping two times on the reset button.
+ * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
+ * be touched from the loaded application.
+ */
+#define BOOT_DOUBLE_TAP_ADDRESS           0x20007FFC
+#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))
+
 #define BOOT_LOAD_PIN                     PIN_PA21 //Pin 7
 //#define BOOT_LOAD_PIN                     PIN_PA15 //Pin 5
 #define BOOT_PIN_MASK                     (1U << (BOOT_LOAD_PIN & 0x1f))
diff --git a/bootloaders/zero/samd21_sam_ba.bin b/bootloaders/zero/samd21_sam_ba.bin
index 69ced0a312f83d769f7f62e0fe460551481eadce..acad5894ba98254005c34371e58e2619d936876f 100644
GIT binary patch
delta 695
zcmZ2tc*l@$fii<aEe8WbB^XZ>l&)uhaDWsTKqO!aXiu|(Eu6Skov~-)Rc+252?mA`
z1_p(m$()SO>&>?sdp9UuVx5%`m1yY2s3=q+A;aZh;LUh}L5cl=Oa_Av*F{|~$pl6#
z2CY9Ar4qEgB{RHbm@djakV=qwpb6Bg=`)F$O*JY(wP04FbXJzzY^K}%mkTdfGHCN$
zXi&b*+ML*+yxKuJqxmyOhdfaIB*s|@9Pa<W2mP1vW=vF)D%k%yzCURj!v~|^j2{|)
zu*fXVP>`A7F6Pak!FYiYC@)pPpv8KDL4o0e>JNqwJAeIoE?vQ({rV!qhpE3AG@f5z
z1j<MNW!3;?4!AYAFgRMUFgX0FXHW<@%)l^t29pKX2~h@yQlOtj#5Uhzl4D`w5S#pq
zO-b|#P?%SYf#DgDHUQEufb^HihU~&}e}Sw5paz$v|NpZ9F(Xix6^Pk^m|JXe68j;>
z6_Zstl3Az!`S-kMb1z3WBct8spPZLjI6e6p7%X`i7}jpS$`{Sd=&;#P$e4*SWOAy=
zb>0eK*u!wmWKU7|`njA83<rUDBM^TDVty{5MchDV@h~uy0sZV)P^4gJreI`XXv$z<
zU}bD!WopI{!NtoE3B*wh%0SYN!BEc-l(H5IGcfD~;)_816^I2zAhacrj&>|cDb38w
Yw~C02iUq1w6mU{VHfY(*FE*740Jyuc4gdfE

delta 608
zcmca(xWtfefii=FD+dFEBN$H<l&)uhaDWsTKqO!aXiu|(Eu6SkoiSwMRc+1?2?mA`
z1_p(Y$()SO>ovR^l!~`rVpaE?l@OK4k>MyKeL>Z;K}FSf2{W6TPl8@SPa;oNrrQ#x
zC;Vp$*$p`>7&N&q%t~xf-s~Wq(fpaCLk4KVB*s|@4DSEGXZ)A+W>k_Y*#9}cKWQ7o
z2c6%HAF6(^$SlrKkeT5w?9HITcmX6YRl%UedVxWKLGy$B4~7q$fBktbUBRIJ`Xa-J
z{@)B5&o3}4FnkaK$}9uQ9B^xJVQ`#$fyshvf+zz+DbVeAL^lgD%ds$B5S?tquH?1`
zD0~%&*8%YlAl?APdw^JnkwL)%h#4Fh9GRB>|9=!HRshuQ0%WrQ@kt>6ED)au;>)6w
zXR#k*ESMb2k<7aJ&%fs(n~!p2GcvMmHsrd@!YRnlz`)20w0$!#e>5{A$L35SV<twK
z$#X@n^Ev=S6oy?UH;THOq;fJabOLcD5bp)z>p*;#3+PC028J@Adwdg%6bvmCj0_A-
m84NA0Oo7OJ@*hzN$xLAehDIQs3B-GW_$HKQ+^j3Mo(TX3{FTlC

diff --git a/bootloaders/zero/samd21j18a_flash.ld b/bootloaders/zero/samd21j18a_flash.ld
index 8fa81d10..c9385c48 100644
--- a/bootloaders/zero/samd21j18a_flash.ld
+++ b/bootloaders/zero/samd21j18a_flash.ld
@@ -50,7 +50,7 @@ SEARCH_DIR(.)
 MEMORY
 {
   rom (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00040000
-  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */
 }
 
 /* The stack size used by the application. NOTE: you need to adjust according to your application. */
diff --git a/variants/arduino_zero/linker_scripts/gcc/flash_with_bootloader.ld b/variants/arduino_zero/linker_scripts/gcc/flash_with_bootloader.ld
index 867bf41b..083e5606 100644
--- a/variants/arduino_zero/linker_scripts/gcc/flash_with_bootloader.ld
+++ b/variants/arduino_zero/linker_scripts/gcc/flash_with_bootloader.ld
@@ -25,8 +25,8 @@
  */
 MEMORY
 {
-  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000
-  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004         /* Last 4B used by bootloader   */
 }
 
 /* Linker script to place sections and symbol values. Should be used together
-- 
GitLab