From 2812f962d9e8031e22e0e315111a6fbbdf603645 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= <ondra@ondrovo.com>
Date: Wed, 28 Feb 2018 08:17:21 +0100
Subject: [PATCH] added watchdog

---
 USB/usb_device.c     |  1 +
 gex_hooks.c          | 12 ++++++++++
 platform/plat_init.c |  3 +++
 platform/watchdog.c  | 57 ++++++++++++++++++++++++++++++++++++++++++++
 platform/watchdog.h  | 32 +++++++++++++++++++++++++
 tasks/task_main.c    |  3 +++
 tasks/task_msg.c     |  3 +++
 vfs/vfs_user.c       |  2 +-
 8 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 platform/watchdog.c
 create mode 100644 platform/watchdog.h

diff --git a/USB/usb_device.c b/USB/usb_device.c
index 9ead3f0..2a9ca90 100644
--- a/USB/usb_device.c
+++ b/USB/usb_device.c
@@ -66,6 +66,7 @@ PCD_HandleTypeDef hpcd_USB_FS;
 /* init function */                                        
 void MX_USB_DEVICE_Init(void)
 {
+  dbg("USB device init ...");
   /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
   
   /* USER CODE END USB_DEVICE_Init_PreTreatment */
diff --git a/gex_hooks.c b/gex_hooks.c
index e60f4bb..ab4f9df 100644
--- a/gex_hooks.c
+++ b/gex_hooks.c
@@ -43,6 +43,18 @@ void GEX_PreInit(void)
     dbg("\r\n\033[37;1m*** GEX "GEX_VERSION" on "GEX_PLATFORM" ***\033[m");
     dbg("Build "__DATE__" "__TIME__);
 
+    PRINTF("Reset cause:");
+    if (LL_RCC_IsActiveFlag_LPWRRST()) PRINTF(" LPWR");
+    if (LL_RCC_IsActiveFlag_WWDGRST()) PRINTF(" WWDG");
+    if (LL_RCC_IsActiveFlag_IWDGRST()) PRINTF(" IWDG");
+    if (LL_RCC_IsActiveFlag_SFTRST()) PRINTF(" SFT");
+    if (LL_RCC_IsActiveFlag_PORRST()) PRINTF(" POR");
+    if (LL_RCC_IsActiveFlag_PINRST()) PRINTF(" PIN");
+    if (LL_RCC_IsActiveFlag_OBLRST()) PRINTF(" OBL");
+    if (LL_RCC_IsActiveFlag_V18PWRRST()) PRINTF(" V18PWR");
+    PUTNL();
+    LL_RCC_ClearResetFlags();
+
     plat_init();
 
     MX_USB_DEVICE_Init();
diff --git a/platform/plat_init.c b/platform/plat_init.c
index f233d6d..0ef548e 100644
--- a/platform/plat_init.c
+++ b/platform/plat_init.c
@@ -15,6 +15,7 @@
 #include "debug_uart.h"
 #include "irq_dispatcher.h"
 #include "timebase.h"
+#include "watchdog.h"
 
 void plat_init(void)
 {
@@ -39,4 +40,6 @@ void plat_init(void)
     settings_load(); // XXX maybe this should be moved to the main task
 
     comm_init();
+
+    wd_init();
 }
diff --git a/platform/watchdog.c b/platform/watchdog.c
new file mode 100644
index 0000000..2e66ce6
--- /dev/null
+++ b/platform/watchdog.c
@@ -0,0 +1,57 @@
+//
+// Created by MightyPork on 2018/02/27.
+//
+
+#include "platform.h"
+#include "watchdog.h"
+
+static volatile uint16_t suspend_depth = 0;
+static volatile bool restart_pending = false;
+
+void wd_init(void)
+{
+    dbg("IWDG init, time 2s");
+
+    LL_IWDG_Enable(IWDG);
+    LL_IWDG_EnableWriteAccess(IWDG);
+    LL_IWDG_SetPrescaler(IWDG, LL_IWDG_PRESCALER_32); // 0.8 ms
+    LL_IWDG_SetReloadCounter(IWDG, 2500); // 2s.  max 4095
+    while (!LL_IWDG_IsReady(IWDG));
+
+    // reload
+    LL_IWDG_ReloadCounter(IWDG);
+}
+
+void wd_suspend(void)
+{
+    vPortEnterCritical();
+    if (suspend_depth < 0xFFFF) {
+        suspend_depth++;
+    }
+    vPortExitCritical();
+}
+
+void wd_resume(void)
+{
+    vPortEnterCritical();
+    if (suspend_depth > 0) {
+        suspend_depth--;
+
+        if (suspend_depth == 0 && restart_pending) {
+            restart_pending = false;
+            LL_IWDG_ReloadCounter(IWDG);
+        }
+    }
+    vPortExitCritical();
+}
+
+void wd_restart(void)
+{
+    vPortEnterCritical();
+    if (suspend_depth == 0) {
+        LL_IWDG_ReloadCounter(IWDG);
+    } else {
+        restart_pending = true;
+    }
+    vPortExitCritical();
+}
diff --git a/platform/watchdog.h b/platform/watchdog.h
new file mode 100644
index 0000000..8927dfa
--- /dev/null
+++ b/platform/watchdog.h
@@ -0,0 +1,32 @@
+//
+// Created by MightyPork on 2018/02/27.
+//
+
+#ifndef GEX_F072_WATCHDOG_H
+#define GEX_F072_WATCHDOG_H
+
+/**
+ * Initialize the application watchdog
+ */
+void wd_init(void);
+
+/**
+ * Suspend watchdog restarts until resumed
+ * (used in other tasks to prevent the main task clearing the wd if the other task is locked up)
+ *
+ * The suspend/resume calls can be stacked.
+ */
+void wd_suspend(void);
+
+/**
+ * Resume restarts
+ */
+void wd_resume(void);
+
+/**
+ * Restart the wd. If restarts are suspended, postpone the restart until resumed
+ * and then restart immediately.
+ */
+void wd_restart(void);
+
+#endif //GEX_F072_WATCHDOG_H
diff --git a/tasks/task_main.c b/tasks/task_main.c
index 0653154..342e51e 100644
--- a/tasks/task_main.c
+++ b/tasks/task_main.c
@@ -4,6 +4,7 @@
 
 #include "platform.h"
 #include "platform/lock_jumper.h"
+#include "platform/watchdog.h"
 #include "status_led.h"
 #include "utils/stacksmon.h"
 #include "vfs/vfs_manager.h"
@@ -45,6 +46,8 @@ void TaskMain(void const * argument)
 
             cnt++;
             Indicator_Heartbeat();
+
+            wd_restart();
         }
 
         // if no message and it just timed out, go wait some more...
diff --git a/tasks/task_msg.c b/tasks/task_msg.c
index 5764788..59fccf5 100644
--- a/tasks/task_msg.c
+++ b/tasks/task_msg.c
@@ -3,6 +3,7 @@
 //
 
 #include "platform.h"
+#include "platform/watchdog.h"
 #include "comm/messages.h"
 #include "task_msg.h"
 
@@ -85,7 +86,9 @@ void TaskMsgJob(const void *argument)
             #if CDC_LOOPBACK_TEST
                 TF_WriteImpl(comm, slot.msg.data, slot.msg.len);
             #else
+                wd_suspend();
                 TF_Accept(comm, slot.msg.data, slot.msg.len);
+                wd_resume();
             #endif
         }
 
diff --git a/vfs/vfs_user.c b/vfs/vfs_user.c
index d0b2809..5f0b511 100644
--- a/vfs/vfs_user.c
+++ b/vfs/vfs_user.c
@@ -68,7 +68,7 @@ static uint32_t read_file_pinout_txt(uint32_t sector_offset, uint8_t *data, uint
 
 void vfs_user_build_filesystem(void)
 {
-    dbg("Rebuilding VFS...");
+    vfs_printf("Rebuilding VFS...");
 
     // Setup the filesystem based on target parameters
     vfs_init(daplink_drive_name, 0/*unused "disk size"*/);