瀏覽代碼

Merge pull request #4414 from iysheng/wdg

[bsp][gd32103c-eval] Add watchdog driver
Bernard Xiong 4 年之前
父節點
當前提交
d6b4f77188
共有 4 個文件被更改,包括 119 次插入1 次删除
  1. 4 1
      bsp/gd32103c-eval/Kconfig
  2. 1 0
      bsp/gd32103c-eval/README.md
  3. 3 0
      bsp/gd32103c-eval/drivers/SConscript
  4. 111 0
      bsp/gd32103c-eval/drivers/drv_iwdt.c

+ 4 - 1
bsp/gd32103c-eval/Kconfig

@@ -96,5 +96,8 @@ menu "On-chip Peripheral Drivers"
                 bool "using hwtimer7"
                 default n
         endif
-
+    config BSP_USING_WDT
+        bool "Enable Watchdog Timer"
+        select RT_USING_WDT
+        default n
 endmenu

+ 1 - 0
bsp/gd32103c-eval/README.md

@@ -48,6 +48,7 @@ msh />
 | GPIO      | 支持     |          GPIOA~G           |
 | ADC       | 支持     |          ADC0~1            |
 | HWTIMER   | 支持     |          TIMER0~7          |
+| WDT       | 支持     |    Free watchdog timer     |
 | IIC       | 未支持   |          I2C0~1            |
 | SPI       | 未支持   |          SPI0~2            |
 | ETH       | 未支持   |                            |

+ 3 - 0
bsp/gd32103c-eval/drivers/SConscript

@@ -24,6 +24,9 @@ if GetDepend('RT_USING_ADC'):
 if GetDepend('RT_USING_HWTIMER'):
     src += ['drv_hwtimer.c']
 
+if GetDepend('RT_USING_WDT'):
+    src += ['drv_iwdt.c']
+
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
 
 Return('group')

+ 111 - 0
bsp/gd32103c-eval/drivers/drv_iwdt.c

@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2021-03-03     iysheng           first version
+ */
+
+#include <board.h>
+
+#define DBG_TAG             "drv.wdt"
+#define DBG_LVL             DBG_INFO
+#include <rtdbg.h>
+
+#ifdef RT_USING_WDT
+
+typedef struct {
+    struct rt_watchdog_device wdt;
+    rt_uint32_t min_threshold_s;
+    rt_uint32_t max_threshold_s;
+    rt_uint32_t current_threshold_s;
+} gd32_wdt_device_t;
+
+static gd32_wdt_device_t g_wdt_dev;
+
+static rt_err_t gd32_iwdt_init(rt_watchdog_t *wdt)
+{
+    rcu_osci_on(RCU_IRC40K);
+    if (ERROR == rcu_osci_stab_wait(RCU_IRC40K))
+    {
+        LOG_E("failed init IRC40K clock for free watchdog.");
+        return -EINVAL;
+    }
+
+    g_wdt_dev.min_threshold_s = 1;
+    g_wdt_dev.max_threshold_s = (0xfff << 8) / 40000;
+    LOG_I("threshold section [%u, %d]", \
+        g_wdt_dev.min_threshold_s, g_wdt_dev.max_threshold_s);
+
+    IWDG_Write_Enable(IWDG_WRITEACCESS_ENABLE);
+    IWDG_SetPrescaler(IWDG_PRESCALER_256);
+    IWDG_SetReloadValue(0xfff);
+    IWDG_Write_Enable(IWDG_WRITEACCESS_DISABLE);
+
+    return 0;
+}
+
+static rt_err_t gd32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
+{
+    rt_uint32_t param;
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_WDT_KEEPALIVE:
+        IWDG_ReloadCounter();
+        break;
+    case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
+        param = *(rt_uint32_t *) arg;
+        if ((param > g_wdt_dev.max_threshold_s) || \
+            (param < g_wdt_dev.min_threshold_s))
+        {
+            LOG_E("invalid param@%u.", param);
+            return -E2BIG;
+        }
+        else
+        {
+            g_wdt_dev.current_threshold_s = param;
+        }
+        IWDG_Write_Enable(IWDG_WRITEACCESS_ENABLE);
+        IWDG_SetReloadValue(param * 40000 >> 8);
+        IWDG_Write_Enable(IWDG_WRITEACCESS_DISABLE);
+        break;
+    case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
+        *(rt_uint32_t *)arg = g_wdt_dev.current_threshold_s;
+        break;
+    case RT_DEVICE_CTRL_WDT_START:
+        IWDG_Enable();
+        break;
+    default:
+        LOG_W("This command is not supported.");
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+static struct rt_watchdog_ops g_wdt_ops = {
+    gd32_iwdt_init,
+    gd32_iwdt_control,
+};
+
+static int rt_hw_iwdt_init(void)
+{
+    rt_err_t ret;
+
+    g_wdt_dev.wdt.ops = &g_wdt_ops;
+    /* register watchdog device */
+    if (rt_hw_watchdog_register(&g_wdt_dev.wdt, "iwdt", \
+        RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
+    {
+        LOG_E("wdt device register failed.");
+        return -RT_ERROR;
+    }
+    LOG_D("wdt device register success.");
+
+    return ret;
+}
+INIT_BOARD_EXPORT(rt_hw_iwdt_init);
+#endif