Parcourir la source

[bsp][ls1c] Add watchdog library function and driver .

sundm75 il y a 6 ans
Parent
commit
f74f6e8c55

+ 199 - 0
bsp/ls1cdev/drivers/drv_wdt.c

@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-06     sundm75       first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#ifdef  RT_USING_WDT
+
+#include <drivers/watchdog.h>
+#include "drv_wdt.h"
+
+#include "ls1c_wdog.h"
+#include "ls1c_clock.h"
+
+typedef enum
+{
+    RESTENABLE      = 0x0,
+    INTERRUPTENABLE = 0x1,
+}wdt_enable_mode;
+
+static rt_uint32_t heartbeat = 0;
+
+static rt_err_t wdt_stop(void)
+{
+    rt_err_t ret = RT_EOK;
+
+    Wdog_Reset();
+    ret = (rt_err_t) Wdog_Disable();
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("Wdog_Disable error!\n");
+        return RT_ERROR;
+    }
+    return ret;
+}
+
+static rt_err_t wdt_start(int mode)
+{
+    rt_err_t ret = RT_EOK;
+    wdt_enable_mode wdt_mode = RESTENABLE;
+
+    ret = (rt_err_t) Wdog_Disable();
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("Wdog_Disable error!\n");
+        return RT_ERROR;
+    }
+
+    if((mode == RESTENABLE) || (mode == INTERRUPTENABLE))
+    {
+        wdt_mode = mode;
+    }
+    Wdog_Enable();
+    Wdog_Set();
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("Wdog_Enable error!\n");
+        return RT_ERROR;
+    }
+
+    return ret;
+}
+
+static rt_err_t wdt_keepalive(void)
+{
+    rt_err_t ret = RT_EOK;
+    rt_uint32_t index = 0;
+
+    index = heartbeat * clk_get_apb_rate();
+    ret = (rt_err_t) Wdog_LoadValue(index);
+    Wdog_Set();
+    if (ret != 0)
+    {
+        rt_kprintf("LS1C_Wdog_ClrTimeout error!\n");
+        return RT_ERROR;
+    }
+
+    return ret;
+}
+
+static rt_uint32_t wdt_get_timeleft(void)
+{
+    rt_uint32_t  cnt = 0;
+    rt_uint32_t second  = 0;
+
+    cnt =  (rt_uint32_t) Wdog_GetValue();
+    second = cnt/clk_get_apb_rate();
+
+    return second;
+}
+
+static rt_err_t wdt_set_timeout(rt_uint32_t second)
+{
+    rt_err_t ret = RT_EOK;
+    rt_uint32_t index = 0;
+
+    index = second * clk_get_apb_rate();
+    ret = (rt_err_t) Wdog_LoadValue(index);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("Wdog_LoadValue error!\n");
+        return RT_ERROR;
+    }
+    return ret;
+}
+
+static rt_err_t watchdog_init(rt_watchdog_t *wdt)
+{
+    struct wdt_driver *wdt_drv = wdt->parent.user_data;
+    if (wdt_drv->in_use) return -RT_EBUSY;
+
+    Wdog_Init();
+
+    return RT_EOK;
+}
+
+static rt_err_t watchdog_ctrl(rt_watchdog_t *wdt, int cmd, void *arg)
+{
+    rt_uint32_t val;
+    int mode;
+
+    switch (cmd)
+    {
+        case RT_DEVICE_CTRL_WDT_START:
+            mode = *((int *)(arg));
+            wdt_start(mode);
+            break;
+
+        case RT_DEVICE_CTRL_WDT_STOP:
+            Wdog_Disable();
+            break;
+
+        case RT_DEVICE_CTRL_WDT_KEEPALIVE:
+            wdt_keepalive();
+            break;
+
+        case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
+            heartbeat = *((rt_uint32_t *)(arg));
+            wdt_set_timeout(heartbeat);
+            break;
+
+        case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
+            arg = &heartbeat;
+            break;
+
+        case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
+            val = (rt_uint32_t) wdt_get_timeleft();
+            arg = &val;
+            break;
+
+        default:
+            return -RT_EIO;
+    }
+    return RT_EOK;
+}
+
+struct rt_watchdog_ops watchdog_ops = 
+{
+    .init = &watchdog_init, 
+    .control = &watchdog_ctrl,
+};
+
+int wdt_exit(void *priv_data) 
+{ 
+    return 0;     
+}
+
+int rt_hw_wdt_init(void)
+{
+    rt_watchdog_t *wdt_dev;
+    struct wdt_driver *wdt_drv;
+
+    wdt_drv = (struct wdt_driver *)rt_malloc(sizeof(struct wdt_driver));
+    rt_memset(wdt_drv, 0, sizeof(struct wdt_driver));
+
+    wdt_dev = (rt_watchdog_t *)rt_malloc(sizeof(rt_watchdog_t));
+
+    if (wdt_dev == RT_NULL)
+    {
+        rt_kprintf("ERROR: %s rt_watchdog_t malloc failed\n", __func__);
+    }
+
+    wdt_dev->ops = &watchdog_ops;
+
+    rt_hw_watchdog_register(wdt_dev, "wdt", RT_DEVICE_OFLAG_RDWR, wdt_drv);
+
+    return 0;
+}
+
+INIT_BOARD_EXPORT(rt_hw_wdt_init);
+
+#endif

+ 23 - 0
bsp/ls1cdev/drivers/drv_wdt.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-06     sundm75       first version
+ */
+
+#ifndef WDT_H_
+#define WDT_H_
+
+struct wdt_driver
+{
+    unsigned long in_use;
+
+    void* priv;
+};
+
+int rt_hw_wdt_init(void);
+
+#endif /* WDT_H_ */

+ 91 - 0
bsp/ls1cdev/libraries/ls1c_wdog.c

@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-06     sundm75       first version
+ */
+
+#include "ls1c.h"
+#include "ls1c_wdog.h"
+
+/*
+系统先配置看门狗使能位 WDT_EN;
+然后配置看门狗计数器的初始值 WDT_TIMER;
+当设置 WDT_SET 后,计数器开始减计数;
+当还没有减到 0 时,重置看门狗计数器,系统不会重启;
+当看门狗计数器减到 0 时,则系统重启。
+*/
+
+static unsigned int WDT_timer = 0;
+
+/* 暂时为空 */
+unsigned int Wdog_Init(void)              
+{
+    return 0;
+}
+
+/* 配置看门狗使能寄存器(WDT_EN) */
+unsigned int Wdog_Enable(void)       
+{
+    unsigned int ctrl;
+    ctrl = (WDT_EN);
+    ctrl |= 0x01;
+
+    WDT_EN = ctrl;
+    return 0;
+}
+
+/* 配置看门狗失能寄存器(WDT_EN) */
+unsigned int Wdog_Disable(void)           
+{
+    unsigned int ctrl;
+    ctrl = (WDT_EN);
+    ctrl &= ~0x01;
+    WDT_EN = ctrl;
+    return 0;
+}
+
+/* 配置看门狗设置寄存器 (WDT_SET) */
+unsigned int Wdog_Set(void)               
+{
+    unsigned int ctrl;
+    ctrl = (WDT_SET);
+    ctrl |= 0x01;
+    WDT_SET = ctrl;
+    return 0;
+}
+
+/* 配置看门狗设置寄存器 (WDT_SET) */
+unsigned int Wdog_Reset(void)             
+{
+    unsigned int ctrl;
+    ctrl = (WDT_SET);
+    ctrl &= ~0x01;
+    WDT_SET = ctrl;
+    return 0;
+}
+
+/* 获得看门狗计数器(WDT_timer) 的值*/
+unsigned int Wdog_GetValue(void)          
+{
+    unsigned int cnt;
+    cnt = (WDT_TIMER);
+    return cnt;
+}
+
+/* 配置看门狗计数器(WDT_timer)的值*/
+unsigned int Wdog_LoadValue(unsigned int cnt)    
+{
+    WDT_TIMER = cnt;
+    WDT_timer = cnt;
+    return 0;
+}
+
+/* 获得看门狗计数器设定值 */
+unsigned int Wdog_GetPreValue(void)    
+{
+    return WDT_timer;
+}

+ 32 - 0
bsp/ls1cdev/libraries/ls1c_wdog.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-05-06     sundm75       first version
+ */
+
+#ifndef _LS1C_WDOG_H_
+#define _LS1C_WDOG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned int Wdog_Init(void);                   // 暂时为空
+unsigned int Wdog_Enable(void);                 // 看门狗使能寄存器(WDT_EN)
+unsigned int Wdog_Disable(void);                // 看门狗失能寄存器(WDT_EN)
+unsigned int Wdog_Set(void);                    // 看门狗设置寄存器 (WDT_SET)
+unsigned int Wdog_Reset(void);                  // 看门狗设置寄存器 (WDT_SET)
+unsigned int Wdog_GetValue(void);               // 获得看门狗计数器(WDT_timer)
+unsigned int Wdog_LoadValue(unsigned int cnt);  // 设置看门狗计数器(WDT_timer)
+unsigned int Wdog_GetPreValue(void);            // 获得看门狗计数器设定值
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LS1C_WDOG_H_ */
+