drv_ewdt.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright (c) 2023 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <rthw.h>
  8. #include <rtdevice.h>
  9. #include <rtdbg.h>
  10. #include "board.h"
  11. #include "drv_ewdt.h"
  12. #include "hpm_ewdg_drv.h"
  13. #include "hpm_sysctl_drv.h"
  14. #ifdef BSP_USING_EWDG
  15. #define EWDG_CNT_CLK_FREQ 32768UL
  16. typedef struct hpm_wdog
  17. {
  18. EWDG_Type *wdog_base;
  19. char *device_name;
  20. clock_name_t clock_name;
  21. uint32_t irq_num;
  22. rt_watchdog_t *wdog;
  23. }hpm_wdog_t;
  24. static rt_err_t hpm_wdog_init(rt_watchdog_t *wdt);
  25. static rt_err_t hpm_wdog_open(rt_watchdog_t *wdt, rt_uint16_t oflag);
  26. static rt_err_t hpm_wdog_close(rt_watchdog_t *wdt);
  27. static rt_err_t hpm_wdog_refresh(rt_watchdog_t *wdt);
  28. static rt_err_t hpm_wdog_control(rt_watchdog_t *wdt, int cmd, void *args);
  29. static void hpm_wdog_isr(rt_watchdog_t *wdt);
  30. #if defined(BSP_USING_EWDG0)
  31. rt_watchdog_t wdog0;
  32. void wdog0_isr(void)
  33. {
  34. hpm_wdog_isr(&wdog0);
  35. }
  36. SDK_DECLARE_EXT_ISR_M(IRQn_EWDG0, wdog0_isr)
  37. #endif
  38. #if defined(BSP_USING_EWDG1)
  39. rt_watchdog_t wdog1;
  40. void wdog1_isr(void)
  41. {
  42. hpm_wdog_isr(&wdog1);
  43. }
  44. SDK_DECLARE_EXT_ISR_M(IRQn_EWDG1, wdog1_isr)
  45. #endif
  46. #if defined(BSP_USING_EWDG2)
  47. rt_watchdog_t wdog2;
  48. void wdog2_isr(void)
  49. {
  50. hpm_wdog_isr(&wdog2);
  51. }
  52. SDK_DECLARE_EXT_ISR_M(IRQn_EWDG2, wdog2_isr)
  53. #endif
  54. #if defined(BSP_USING_EWDG3)
  55. rt_watchdog_t wdog3;
  56. void wdog3_isr(void)
  57. {
  58. hpm_wdog_isr(&wdog3);
  59. }
  60. SDK_DECLARE_EXT_ISR_M(IRQn_EWDG3, wdog3_isr)
  61. #endif
  62. static hpm_wdog_t wdogs[] = {
  63. #ifdef BSP_USING_EWDG0
  64. {
  65. .wdog_base = HPM_EWDG0,
  66. .device_name = "wdt0",
  67. .clock_name = clock_watchdog0,
  68. .irq_num = IRQn_EWDG0,
  69. .wdog = &wdog0,
  70. },
  71. #endif
  72. #ifdef BSP_USING_EWDG1
  73. {
  74. .wdog_base = HPM_EWDG1,
  75. .device_name = "wdt1",
  76. .clock_name = clock_watchdog1,
  77. .irq_num = IRQn_EWDG1,
  78. .wdog = &wdog1,
  79. },
  80. #endif
  81. #ifdef BSP_USING_EWDG2
  82. {
  83. .wdog_base = HPM_EWDG2,
  84. .device_name = "wdt2",
  85. .clock_name = clock_watchdog2,
  86. .irq_num = IRQn_EWDG2,
  87. .wdog = &wdog2,
  88. },
  89. #endif
  90. #ifdef BSP_USING_EWDG3
  91. {
  92. .wdog_name = HPM_EWDG3,
  93. .device_name = "wdt3",
  94. .clock_name = clock_watchdog3,
  95. .irq_num = IRQn_EWDG3,
  96. .wdog = &wdog3,
  97. },
  98. #endif
  99. };
  100. static struct rt_watchdog_ops hpm_wdog_ops = {
  101. .init = hpm_wdog_init,
  102. .control = hpm_wdog_control,
  103. };
  104. static rt_err_t hpm_wdog_init(rt_watchdog_t *wdt)
  105. {
  106. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  107. EWDG_Type *base = hpm_wdog->wdog_base;
  108. ewdg_config_t config;
  109. printf("Init Watchdog\n");
  110. ewdg_get_default_config(base, &config);
  111. /* Enable EWDG */
  112. config.enable_watchdog = true;
  113. config.ctrl_config.use_lowlevel_timeout = false;
  114. /* Enable EWDG Timeout Reset */
  115. config.int_rst_config.enable_timeout_reset = true;
  116. /* Set EWDG Count clock source to OSC32 */
  117. config.ctrl_config.cnt_clk_sel = ewdg_cnt_clk_src_ext_osc_clk;
  118. /* Set the EWDG reset timeout to 101ms */
  119. config.cnt_src_freq = EWDG_CNT_CLK_FREQ;
  120. config.ctrl_config.timeout_reset_us = 101UL * 1000UL;
  121. ewdg_init(base, &config);
  122. return RT_EOK;
  123. }
  124. static rt_err_t hpm_wdog_open(rt_watchdog_t *wdt, rt_uint16_t oflag)
  125. {
  126. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  127. EWDG_Type *base = hpm_wdog->wdog_base;
  128. rt_enter_critical();
  129. ewdg_enable(base);
  130. rt_exit_critical();
  131. }
  132. static rt_err_t hpm_wdog_close(rt_watchdog_t *wdt)
  133. {
  134. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  135. EWDG_Type *base = hpm_wdog->wdog_base;
  136. rt_enter_critical();
  137. ewdg_disable(base);
  138. rt_exit_critical();
  139. return RT_EOK;
  140. }
  141. static rt_err_t hpm_wdog_refresh(rt_watchdog_t *wdt)
  142. {
  143. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  144. EWDG_Type *base = hpm_wdog->wdog_base;
  145. rt_enter_critical();
  146. ewdg_refresh(base);
  147. rt_exit_critical();
  148. return RT_EOK;
  149. }
  150. static rt_err_t hpm_wdog_control(rt_watchdog_t *wdt, int cmd, void *args)
  151. {
  152. rt_err_t ret = RT_EOK;
  153. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  154. EWDG_Type *base = hpm_wdog->wdog_base;
  155. ewdg_config_t config;
  156. uint32_t temp;
  157. switch (cmd)
  158. {
  159. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  160. RT_ASSERT(*(uint32_t *)args != 0);
  161. temp = *(uint32_t *)args;
  162. temp *= 1000000U; /* Convert to microseconds */
  163. ewdg_get_default_config(base, &config);
  164. config.enable_watchdog = true;
  165. config.int_rst_config.enable_timeout_reset = true;
  166. config.ctrl_config.use_lowlevel_timeout = false;
  167. uint32_t ewdg_src_clk_freq = EWDG_CNT_CLK_FREQ;
  168. config.ctrl_config.cnt_clk_sel = ewdg_cnt_clk_src_ext_osc_clk;
  169. /* Set the EWDG reset timeout to 1 second */
  170. config.cnt_src_freq = ewdg_src_clk_freq;
  171. config.ctrl_config.timeout_reset_us = temp;
  172. /* Initialize the EWDG */
  173. hpm_stat_t status = ewdg_init(base, &config);
  174. if (status != status_success) {
  175. printf(" EWDG initialization failed, error_code=%d\n", status);
  176. }
  177. /* delay 1ms to ensure above configure take effective*/
  178. rt_thread_mdelay(1);
  179. break;
  180. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  181. hpm_wdog_refresh(wdt);
  182. break;
  183. case RT_DEVICE_CTRL_WDT_START:
  184. hpm_wdog_open(wdt, *(uint16_t*)args);
  185. break;
  186. case RT_DEVICE_CTRL_WDT_STOP:
  187. hpm_wdog_close(wdt);
  188. break;
  189. default:
  190. ret = RT_EINVAL;
  191. break;
  192. }
  193. return RT_EOK;
  194. }
  195. void hpm_wdog_isr(rt_watchdog_t *wdt)
  196. {
  197. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  198. EWDG_Type *base = hpm_wdog->wdog_base;
  199. uint32_t ewdg_stat = ewdg_get_status_flags(base);
  200. if ((ewdg_stat & EWDG_INT_TIMEOUT) != 0) {
  201. ewdg_refresh(base);
  202. }
  203. ewdg_clear_status_flags(base, ewdg_stat);
  204. }
  205. int rt_hw_wdt_init(void)
  206. {
  207. rt_err_t err = RT_EOK;
  208. #if defined(BSP_USING_EWDG)
  209. for (uint32_t i = 0; i < sizeof(wdogs) / sizeof(wdogs[0]); i++)
  210. {
  211. wdogs[i].wdog->ops = &hpm_wdog_ops;
  212. clock_add_to_group(wdogs[i].clock_name, 0);
  213. err = rt_hw_watchdog_register(wdogs[i].wdog, wdogs[i].device_name, RT_DEVICE_FLAG_RDWR, (void *)&wdogs[i]);
  214. if (err != RT_EOK)
  215. {
  216. LOG_E("rt device %s failed, status=%d\n", wdogs[i].device_name, err);
  217. }
  218. }
  219. #endif
  220. return err;
  221. }
  222. INIT_BOARD_EXPORT(rt_hw_wdt_init);
  223. #endif /* RT_USING_WDT */