drv_wdt.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-01-25 iysheng first version
  9. */
  10. #include <board.h>
  11. #define DBG_TAG "drv.wdt"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #ifdef RT_USING_WDT
  15. typedef struct {
  16. struct rt_watchdog_device wdt;
  17. rt_uint32_t min_threshold_s;
  18. rt_uint32_t max_threshold_s;
  19. rt_uint32_t current_threshold_s;
  20. } gd32_wdt_device_t;
  21. static gd32_wdt_device_t g_wdt_dev;
  22. static rt_err_t gd32_wdt_init(rt_watchdog_t *wdt)
  23. {
  24. rcu_osci_on(RCU_IRC40K);
  25. if (ERROR == rcu_osci_stab_wait(RCU_IRC40K))
  26. {
  27. LOG_E("failed init IRC40K clock for free watchdog.");
  28. return -RT_EINVAL;
  29. }
  30. g_wdt_dev.min_threshold_s = 1;
  31. g_wdt_dev.max_threshold_s = (0xfff << 8) / 40000;
  32. LOG_I("threshold section [%u, %d]", \
  33. g_wdt_dev.min_threshold_s, g_wdt_dev.max_threshold_s);
  34. fwdgt_write_enable();
  35. fwdgt_config(0xfff, FWDGT_PSC_DIV256);
  36. fwdgt_enable();
  37. return 0;
  38. }
  39. static rt_err_t gd32_wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
  40. {
  41. rt_uint32_t param;
  42. switch (cmd)
  43. {
  44. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  45. fwdgt_counter_reload();
  46. break;
  47. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  48. param = *(rt_uint32_t *) arg;
  49. if ((param > g_wdt_dev.max_threshold_s) || \
  50. (param < g_wdt_dev.min_threshold_s))
  51. {
  52. LOG_E("invalid param@%u.", param);
  53. return -RT_EINVAL;
  54. }
  55. else
  56. {
  57. g_wdt_dev.current_threshold_s = param;
  58. }
  59. fwdgt_write_enable();
  60. fwdgt_config(param * 40000 >> 8, FWDGT_PSC_DIV256);
  61. fwdgt_write_disable();
  62. break;
  63. case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
  64. *(rt_uint32_t *)arg = g_wdt_dev.current_threshold_s;
  65. break;
  66. case RT_DEVICE_CTRL_WDT_START:
  67. fwdgt_enable();
  68. break;
  69. default:
  70. LOG_W("This command is not supported.");
  71. return -RT_ERROR;
  72. }
  73. return RT_EOK;
  74. }
  75. static struct rt_watchdog_ops g_wdt_ops = {
  76. gd32_wdt_init,
  77. gd32_wdt_control,
  78. };
  79. static int rt_hw_wdt_init(void)
  80. {
  81. rt_err_t ret;
  82. g_wdt_dev.wdt.ops = &g_wdt_ops;
  83. /* register watchdog device */
  84. if (rt_hw_watchdog_register(&g_wdt_dev.wdt, "wdt", \
  85. RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
  86. {
  87. LOG_E("wdt device register failed.");
  88. return -RT_ERROR;
  89. }
  90. LOG_D("wdt device register success.");
  91. return ret;
  92. }
  93. INIT_PREV_EXPORT(rt_hw_wdt_init);
  94. #endif