drv_wdt.c 3.0 KB
Newer Older
S
sheltonyu 已提交
1
/*
mysterywolf's avatar
mysterywolf 已提交
2
 * Copyright (c) 2006-2021, RT-Thread Development Team
S
sheltonyu 已提交
3 4 5 6 7
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author            Notes
8
 * 2022-03-15     shelton           first version
S
sheltonyu 已提交
9 10 11
 */

#include <drivers/watchdog.h>
12
#include "board.h"
S
sheltonyu 已提交
13 14 15

#ifdef RT_USING_WDT

16
#define LICK_VALUE                      40000
S
sheltonyu 已提交
17 18

//#define DRV_DEBUG
19
#define LOG_TAG                         "drv.wdt"
S
sheltonyu 已提交
20 21 22 23
#include <drv_log.h>

struct at32_wdt_obj
{
24 25 26
    wdt_type *wdt_x;
    wdt_division_type div;
    rt_uint32_t reload;
S
sheltonyu 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
    rt_uint16_t is_start;
};
static struct at32_wdt_obj at32_wdt;
static struct rt_watchdog_ops ops;
static rt_watchdog_t watchdog;

static rt_err_t wdt_init(rt_watchdog_t *wdt)
{
    return RT_EOK;
}

static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
{
    switch (cmd)
    {
42
    /* feed the watchdog */
S
sheltonyu 已提交
43
    case RT_DEVICE_CTRL_WDT_KEEPALIVE:
44
        wdt_counter_reload();
S
sheltonyu 已提交
45
        break;
46
    /* set watchdog timeout */
S
sheltonyu 已提交
47
    case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
48 49
#if defined(LICK_VALUE)
        if(LICK_VALUE)
S
sheltonyu 已提交
50
        {
51
            at32_wdt.reload = (*((rt_uint32_t*)arg)) * LICK_VALUE / 256 ;
S
sheltonyu 已提交
52 53 54
        }
        else
        {
55
            LOG_E("Please define the value of LICK_VALUE!");
S
sheltonyu 已提交
56
        }
57
        if(at32_wdt.reload > 0xFFF)
S
sheltonyu 已提交
58
        {
59
            LOG_E("wdg set timeout parameter too large, please less than %ds",0xFFF * 256 / LICK_VALUE);
S
sheltonyu 已提交
60 61 62
            return -RT_EINVAL;
        }
#else
63
  #error "Please define the value of LICK_VALUE!"
S
sheltonyu 已提交
64 65 66
#endif
        if(at32_wdt.is_start)
        {
67 68 69 70 71
            wdt_register_write_enable(TRUE);
            wdt_divider_set(at32_wdt.div);
            wdt_reload_value_set(at32_wdt.reload);
            wdt_register_write_enable(FALSE);
            wdt_enable();
S
sheltonyu 已提交
72 73 74
        }
        break;
    case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
75 76
#if defined(LICK_VALUE)
        if(LICK_VALUE)
S
sheltonyu 已提交
77
        {
78
            (*((rt_uint32_t*)arg)) = at32_wdt.reload * 256 / LICK_VALUE;
S
sheltonyu 已提交
79 80 81
        }
        else
        {
82
            LOG_E("Please define the value of LICK_VALUE!");
S
sheltonyu 已提交
83 84
        }
#else
85
  #error "Please define the value of LICK_VALUE!"
S
sheltonyu 已提交
86 87 88
#endif
        break;
    case RT_DEVICE_CTRL_WDT_START:
89 90 91 92 93
        wdt_register_write_enable(TRUE);
        wdt_divider_set(at32_wdt.div);
        wdt_reload_value_set(at32_wdt.reload);
        wdt_register_write_enable(FALSE);
        wdt_enable();
S
sheltonyu 已提交
94 95 96 97 98 99 100 101 102 103 104
        at32_wdt.is_start = 1;
        break;
    default:
        LOG_W("This command is not supported.");
        return -RT_ERROR;
    }
    return RT_EOK;
}

int rt_hw_wdt_init(void)
{
105 106 107
    at32_wdt.wdt_x = WDT;
    at32_wdt.div = WDT_CLK_DIV_256;
    at32_wdt.reload = 0x00000FFF;
S
sheltonyu 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121
    at32_wdt.is_start = 0;

    ops.init = &wdt_init;
    ops.control = &wdt_control;
    watchdog.ops = &ops;
    /* register watchdog device */
    if (rt_hw_watchdog_register(&watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
    {
        LOG_E("wdt device register failed.");
        return -RT_ERROR;
    }
    LOG_D("wdt device register success.");
    return RT_EOK;
}
122

S
sheltonyu 已提交
123 124 125
INIT_BOARD_EXPORT(rt_hw_wdt_init);

#endif /* RT_USING_WDT */