drv_iwdt.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-03-03 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_iwdt_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 -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. IWDG_Write_Enable(IWDG_WRITEACCESS_ENABLE);
  35. IWDG_SetPrescaler(IWDG_PRESCALER_256);
  36. IWDG_SetReloadValue(0xfff);
  37. IWDG_Write_Enable(IWDG_WRITEACCESS_DISABLE);
  38. return 0;
  39. }
  40. static rt_err_t gd32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
  41. {
  42. rt_uint32_t param;
  43. switch (cmd)
  44. {
  45. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  46. IWDG_ReloadCounter();
  47. break;
  48. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  49. param = *(rt_uint32_t *) arg;
  50. if ((param > g_wdt_dev.max_threshold_s) || \
  51. (param < g_wdt_dev.min_threshold_s))
  52. {
  53. LOG_E("invalid param@%u.", param);
  54. return -E2BIG;
  55. }
  56. else
  57. {
  58. g_wdt_dev.current_threshold_s = param;
  59. }
  60. IWDG_Write_Enable(IWDG_WRITEACCESS_ENABLE);
  61. IWDG_SetReloadValue(param * 40000 >> 8);
  62. IWDG_Write_Enable(IWDG_WRITEACCESS_DISABLE);
  63. break;
  64. case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
  65. *(rt_uint32_t *)arg = g_wdt_dev.current_threshold_s;
  66. break;
  67. case RT_DEVICE_CTRL_WDT_START:
  68. IWDG_Enable();
  69. break;
  70. default:
  71. LOG_W("This command is not supported.");
  72. return -RT_ERROR;
  73. }
  74. return RT_EOK;
  75. }
  76. static struct rt_watchdog_ops g_wdt_ops = {
  77. gd32_iwdt_init,
  78. gd32_iwdt_control,
  79. };
  80. static int rt_hw_iwdt_init(void)
  81. {
  82. rt_err_t ret;
  83. g_wdt_dev.wdt.ops = &g_wdt_ops;
  84. /* register watchdog device */
  85. if (rt_hw_watchdog_register(&g_wdt_dev.wdt, "iwdt", \
  86. RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
  87. {
  88. LOG_E("wdt device register failed.");
  89. return -RT_ERROR;
  90. }
  91. LOG_D("wdt device register success.");
  92. return ret;
  93. }
  94. INIT_BOARD_EXPORT(rt_hw_iwdt_init);
  95. #endif