drv_wdt.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2006-2024 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-11-25 hywing The first version for NXP MCXA153 Board
  9. */
  10. #include <rtthread.h>
  11. #include "drv_wdt.h"
  12. #include "fsl_wwdt.h"
  13. #include "fsl_clock.h"
  14. #ifdef RT_USING_WDT
  15. #define WDT_CLK_FREQ CLOCK_GetWwdtClkFreq()
  16. #define WWDT WWDT0
  17. #define APP_WDT_IRQn WWDT0_IRQn
  18. #define APP_WDT_IRQ_HANDLER WWDT0_IRQHandler
  19. struct mcx_wdt
  20. {
  21. rt_watchdog_t watchdog;
  22. WWDT_Type *wdt_base;
  23. };
  24. static struct mcx_wdt wdt_dev;
  25. void APP_WDT_IRQ_HANDLER(void)
  26. {
  27. uint32_t wdtStatus = WWDT_GetStatusFlags(WWDT);
  28. /*APP_LED_TOGGLE;*/
  29. /* The chip will reset before this happens */
  30. if (wdtStatus & kWWDT_TimeoutFlag)
  31. {
  32. WWDT_ClearStatusFlags(WWDT, kWWDT_TimeoutFlag);
  33. }
  34. /* Handle warning interrupt */
  35. if (wdtStatus & kWWDT_WarningFlag)
  36. {
  37. /* A watchdog feed didn't occur prior to warning timeout */
  38. WWDT_ClearStatusFlags(WWDT, kWWDT_WarningFlag);
  39. /* User code. User can do urgent case before timeout reset.
  40. * IE. user can backup the ram data or ram log to flash.
  41. * the period is set by config.warningValue, user need to
  42. * check the period between warning interrupt and timeout.
  43. */
  44. }
  45. SDK_ISR_EXIT_BARRIER;
  46. }
  47. static rt_err_t wdt_init(rt_watchdog_t *wdt)
  48. {
  49. wwdt_config_t config;
  50. uint32_t wdtFreq;
  51. bool timeOutResetEnable;
  52. /* Enable the WWDT time out to reset the CPU. */
  53. timeOutResetEnable = true;
  54. /* The WDT divides the input frequency into it by 4 */
  55. wdtFreq = WDT_CLK_FREQ / 4;
  56. WWDT_GetDefaultConfig(&config);
  57. /*
  58. * Set watchdog feed time constant to approximately 4s
  59. * Set watchdog warning time to 512 ticks after feed time constant
  60. * Set watchdog window time to 1s
  61. */
  62. config.timeoutValue = wdtFreq * 4;
  63. config.warningValue = 512;
  64. config.windowValue = wdtFreq * 1;
  65. /* Configure WWDT to reset on timeout */
  66. config.enableWatchdogReset = true;
  67. /* Setup watchdog clock frequency(Hz). */
  68. config.clockFreq_Hz = WDT_CLK_FREQ;
  69. WWDT_Init(WWDT, &config);
  70. NVIC_EnableIRQ(APP_WDT_IRQn);
  71. return RT_EOK;
  72. }
  73. void delayWwdtWindow(void)
  74. {
  75. /* For the TV counter register value will decrease after feed watch dog,
  76. * we can use it to as delay. But in user scene, user need feed watch dog
  77. * in the time period after enter Window but before warning intterupt.
  78. */
  79. while (WWDT->TV > WWDT->WINDOW)
  80. {
  81. __NOP();
  82. }
  83. }
  84. static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
  85. {
  86. switch (cmd)
  87. {
  88. case RT_DEVICE_CTRL_WDT_START:
  89. WWDT_Enable(wdt_dev.wdt_base);
  90. return RT_EOK;
  91. case RT_DEVICE_CTRL_WDT_STOP:
  92. WWDT_Disable(wdt_dev.wdt_base);
  93. return RT_EOK;
  94. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  95. delayWwdtWindow();
  96. WWDT_Refresh(wdt_dev.wdt_base);
  97. return RT_EOK;
  98. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  99. if (arg != RT_NULL)
  100. {
  101. uint32_t timeout = *((uint32_t *)arg);
  102. timeout = timeout * WDT_CLK_FREQ / 4;
  103. WWDT_SetTimeoutValue(wdt_dev.wdt_base, timeout);
  104. return RT_EOK;
  105. }
  106. return -RT_ERROR;
  107. default:
  108. return -RT_ERROR;
  109. }
  110. }
  111. static struct rt_watchdog_ops wdt_ops =
  112. {
  113. wdt_init,
  114. wdt_control,
  115. };
  116. int rt_hw_wdt_init(void)
  117. {
  118. wdt_dev.wdt_base = WWDT;
  119. wdt_dev.watchdog.ops = &wdt_ops;
  120. if (rt_hw_watchdog_register(&wdt_dev.watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
  121. {
  122. rt_kprintf("wdt register failed\n");
  123. return -RT_ERROR;
  124. }
  125. return RT_EOK;
  126. }
  127. INIT_BOARD_EXPORT(rt_hw_wdt_init);
  128. #endif /* RT_USING_WDT */