boot: zephyr: adding indication LED and detect pin debounce

Add LED support and boot delay serial detect pin operation.

Signed-off-by: Jared Wolff <hello@jaredwolff.com>
diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c
index 747d36c..3f17358 100644
--- a/boot/zephyr/main.c
+++ b/boot/zephyr/main.c
@@ -105,6 +105,49 @@
 
 MCUBOOT_LOG_MODULE_REGISTER(mcuboot);
 
+#ifdef CONFIG_MCUBOOT_INDICATION_LED
+/*
+ * Devicetree helper macro which gets the 'flags' cell from a 'gpios'
+ * property, or returns 0 if the property has no 'flags' cell.
+ */
+#define FLAGS_OR_ZERO(node)                        \
+  COND_CODE_1(DT_PHA_HAS_CELL(node, gpios, flags), \
+              (DT_GPIO_FLAGS(node, gpios)),        \
+              (0))
+
+/*
+ * The led0 devicetree alias is optional. If present, we'll use it
+ * to turn on the LED whenever the button is pressed.
+ */
+
+#define LED0_NODE DT_ALIAS(bootloader_led0)
+
+#if DT_NODE_HAS_STATUS(LED0_NODE, okay) && DT_NODE_HAS_PROP(LED0_NODE, gpios)
+#define LED0_GPIO_LABEL DT_GPIO_LABEL(LED0_NODE, gpios)
+#define LED0_GPIO_PIN DT_GPIO_PIN(LED0_NODE, gpios)
+#define LED0_GPIO_FLAGS (GPIO_OUTPUT | FLAGS_OR_ZERO(LED0_NODE))
+#else 
+/* A build error here means your board isn't set up to drive an LED. */
+#error "Unsupported board: led0 devicetree alias is not defined"
+#endif
+
+const static struct device *led;
+
+void led_init(void)
+{
+    
+  led = device_get_binding(LED0_GPIO_LABEL);
+  if (led == NULL)
+  {
+    BOOT_LOG_ERR("Didn't find LED device %s\n", LED0_GPIO_LABEL);
+    return;
+  }
+
+  gpio_pin_configure(led, LED0_GPIO_PIN, LED0_GPIO_FLAGS);
+
+}
+#endif
+
 void os_heap_init(void);
 
 #if defined(CONFIG_ARM)
@@ -330,6 +373,11 @@
 
     BOOT_LOG_INF("Starting bootloader");
 
+#ifdef CONFIG_MCUBOOT_INDICATION_LED
+    /* LED init */
+    led_init();
+#endif
+
     os_heap_init();
 
     ZEPHYR_BOOT_LOG_START();
@@ -382,12 +430,52 @@
     __ASSERT(rc >= 0, "Error of the reading the detect pin.\n");
     if (detect_value == CONFIG_BOOT_SERIAL_DETECT_PIN_VAL &&
         !boot_skip_serial_recovery()) {
-        BOOT_LOG_INF("Enter the serial recovery mode");
-        rc = boot_console_init();
-        __ASSERT(rc == 0, "Error initializing boot console.\n");
-        boot_serial_start(&boot_funcs);
-        __ASSERT(0, "Bootloader serial process was terminated unexpectedly.\n");
-    }
+            
+#if CONFIG_BOOT_SERIAL_DETECT_DELAY > 0 
+        k_sleep(K_MSEC(50));
+
+        /* Get the uptime for debounce purposes. */
+        int64_t timestamp = k_uptime_get();
+
+        for(;;) {
+            
+#ifdef GPIO_INPUT
+            rc = gpio_pin_get_raw(detect_port, CONFIG_BOOT_SERIAL_DETECT_PIN);
+            detect_value = rc;
+#else
+            rc = gpio_pin_read(detect_port, CONFIG_BOOT_SERIAL_DETECT_PIN,
+                            &detect_value);
+#endif
+            __ASSERT(rc >= 0, "Error of the reading the detect pin.\n");
+
+            /* Get delta from when this started */
+            uint32_t delta = k_uptime_get() -  timestamp;
+
+            /* If not pressed OR if pressed > debounce period stop loop*/
+            if( delta >= CONFIG_BOOT_SERIAL_DETECT_DELAY || 
+                detect_value != CONFIG_BOOT_SERIAL_DETECT_PIN_VAL ) {
+                    break;
+                }
+
+
+            /* Delay 1 ms */
+            k_sleep(K_MSEC(1));
+        }
+#endif 
+
+        /* Then run DFU */
+        if (detect_value == CONFIG_BOOT_SERIAL_DETECT_PIN_VAL) {
+#ifdef CONFIG_MCUBOOT_INDICATION_LED
+            gpio_pin_set(led, LED0_GPIO_PIN, 1);
+#endif
+            BOOT_LOG_INF("Enter the serial recovery mode");
+            rc = boot_console_init();
+            __ASSERT(rc == 0, "Error initializing boot console.\n");
+            boot_serial_start(&boot_funcs);
+            __ASSERT(0, "Bootloader serial process was terminated unexpectedly.\n");
+        
+        }
+}
 #endif
 
 #ifdef CONFIG_BOOT_WAIT_FOR_USB_DFU