drv_wdt.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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-02-22 airm2m first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <board.h>
  13. #ifdef BSP_USING_WDT
  14. #define LOG_TAG "drv.wdt"
  15. #include "drv_log.h"
  16. struct watchdog_device
  17. {
  18. rt_watchdog_t parent;
  19. IWDG_TypeDef *instance;
  20. rt_uint32_t prescaler;
  21. rt_uint32_t reload;
  22. rt_uint16_t is_start;
  23. };
  24. static struct watchdog_device watchdog_dev;
  25. static rt_err_t air32_wdt_init(rt_watchdog_t *wdt)
  26. {
  27. return RT_EOK;
  28. }
  29. static rt_err_t air32_wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
  30. {
  31. struct watchdog_device *wdt_dev;
  32. wdt_dev = (struct watchdog_device *)wdt;
  33. switch (cmd)
  34. {
  35. /* feed the watchdog */
  36. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  37. IWDG_ReloadCounter();
  38. break;
  39. /* set watchdog timeout */
  40. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  41. wdt_dev->reload = (*((rt_uint32_t *)arg)) * 40000 / 256;
  42. if (wdt_dev->reload > 0xFFF)
  43. {
  44. LOG_E("wdg set timeout parameter too large, please less than %ds", 0xFFF * 256 / 40000);
  45. return -RT_EINVAL;
  46. }
  47. if (wdt_dev->is_start)
  48. {
  49. IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
  50. IWDG_SetPrescaler(wdt_dev->prescaler);
  51. IWDG_SetReload(wdt_dev->reload);
  52. IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);
  53. IWDG_Enable();
  54. }
  55. break;
  56. case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
  57. (*((rt_uint32_t *)arg)) = wdt_dev->reload * 256 / 40000;
  58. break;
  59. case RT_DEVICE_CTRL_WDT_START:
  60. IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
  61. IWDG_SetPrescaler(wdt_dev->prescaler);
  62. IWDG_SetReload(wdt_dev->reload);
  63. IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);
  64. IWDG_Enable();
  65. wdt_dev->is_start = 1;
  66. break;
  67. default:
  68. LOG_W("This command is not supported.");
  69. return -RT_ERROR;
  70. }
  71. return RT_EOK;
  72. }
  73. static struct rt_watchdog_ops watchdog_ops =
  74. {
  75. .init = air32_wdt_init,
  76. .control = air32_wdt_control,
  77. };
  78. int rt_hw_wdt_init(void)
  79. {
  80. watchdog_dev.instance = IWDG;
  81. watchdog_dev.prescaler = IWDG_Prescaler_256;
  82. watchdog_dev.reload = 0x0000FFF;
  83. watchdog_dev.is_start = 0;
  84. watchdog_dev.parent.ops = &watchdog_ops;
  85. /* register watchdog device */
  86. if (rt_hw_watchdog_register(&watchdog_dev.parent, "wdt", 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 RT_EOK;
  93. }
  94. INIT_BOARD_EXPORT(rt_hw_wdt_init);
  95. #endif /* BSP_USING_IWDT */