From f74f6e8c55de0a462c950ad85b17261c650cb021 Mon Sep 17 00:00:00 2001 From: sundm75 Date: Wed, 8 May 2019 08:15:20 +0800 Subject: [PATCH] [bsp][ls1c] Add watchdog library function and driver . --- bsp/ls1cdev/drivers/drv_wdt.c | 199 ++++++++++++++++++++++++++++++ bsp/ls1cdev/drivers/drv_wdt.h | 23 ++++ bsp/ls1cdev/libraries/ls1c_wdog.c | 91 ++++++++++++++ bsp/ls1cdev/libraries/ls1c_wdog.h | 32 +++++ 4 files changed, 345 insertions(+) create mode 100644 bsp/ls1cdev/drivers/drv_wdt.c create mode 100644 bsp/ls1cdev/drivers/drv_wdt.h create mode 100644 bsp/ls1cdev/libraries/ls1c_wdog.c create mode 100644 bsp/ls1cdev/libraries/ls1c_wdog.h diff --git a/bsp/ls1cdev/drivers/drv_wdt.c b/bsp/ls1cdev/drivers/drv_wdt.c new file mode 100644 index 0000000000..4a42220000 --- /dev/null +++ b/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 +#include + +#ifdef RT_USING_WDT + +#include +#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 diff --git a/bsp/ls1cdev/drivers/drv_wdt.h b/bsp/ls1cdev/drivers/drv_wdt.h new file mode 100644 index 0000000000..a017edb19a --- /dev/null +++ b/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_ */ diff --git a/bsp/ls1cdev/libraries/ls1c_wdog.c b/bsp/ls1cdev/libraries/ls1c_wdog.c new file mode 100644 index 0000000000..4034281d10 --- /dev/null +++ b/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; +} diff --git a/bsp/ls1cdev/libraries/ls1c_wdog.h b/bsp/ls1cdev/libraries/ls1c_wdog.h new file mode 100644 index 0000000000..a4717eedbf --- /dev/null +++ b/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_ */ + -- GitLab