123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-03-04 stevetong459 first version
- * 2022-12-26 luobeihai add APM32F0 series MCU support
- * 2023-03-28 luobeihai add APM32E1/S1 series MCU support
- */
- #include <board.h>
- #include <sys/time.h>
- #ifdef RT_USING_WDT
- #define DBG_TAG "drv.wdt"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #ifndef LSI_VALUE
- #define LSI_VALUE ((uint32_t)40000)
- #endif
- #define DRV_WDT_TIME_OUT 0xFFFF
- typedef struct
- {
- struct rt_watchdog_device wdt;
- rt_uint32_t min_threshold;
- rt_uint32_t max_threshold;
- rt_uint32_t current_threshold;
- } apm32_wdt_t;
- static apm32_wdt_t wdt_config;
- static rt_err_t apm32_iwdt_init(rt_watchdog_t *wdt)
- {
- rt_uint32_t counter = 0;
- RCM_EnableLSI();
- while (!RCM_ReadStatusFlag(RCM_FLAG_LSIRDY))
- {
- if (++counter > DRV_WDT_TIME_OUT)
- {
- LOG_E("LSI clock open failed.");
- return -RT_ERROR;
- }
- }
- wdt_config.min_threshold = 1;
- wdt_config.max_threshold = (0xfff << 8) / LSI_VALUE;
- LOG_I("threshold section [%u, %d]", \
- wdt_config.min_threshold,
- wdt_config.max_threshold);
- #if defined(SOC_SERIES_APM32F0)
- while (IWDT_ReadStatusFlag(IWDT_FLAG_DIVU))
- #elif defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1) \
- || defined(SOC_SERIES_APM32F4)
- while (IWDT_ReadStatusFlag(IWDT_FLAG_PSCU))
- #endif
- {
- if (++counter > DRV_WDT_TIME_OUT)
- {
- LOG_E("watchdog prescaler init failed.");
- return -RT_ERROR;
- }
- }
- IWDT_EnableWriteAccess();
- #if defined(SOC_SERIES_APM32F0)
- IWDT_ConfigDivider(IWDT_DIV_256);
- #elif defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1) \
- || defined(SOC_SERIES_APM32F4)
- IWDT_ConfigDivider(IWDT_DIVIDER_256);
- #endif
- IWDT_DisableWriteAccess();
- return RT_EOK;
- }
- /**
- * @brief This function will control watchdog device.
- *
- * @param wdt is a pointer to i2c config class.
- *
- * @return RT_EOK indicates successful , other value indicates failed.
- */
- static rt_err_t apm32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
- {
- volatile rt_uint32_t param, counter = 0;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_WDT_KEEPALIVE:
- IWDT_Refresh();
- break;
- case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
- param = *(rt_uint32_t *) arg;
- if ((param > wdt_config.max_threshold) || \
- (param < wdt_config.min_threshold))
- {
- LOG_E("invalid param@%u.", param);
- return -RT_ERROR;
- }
- else
- {
- wdt_config.current_threshold = param;
- }
- while (IWDT_ReadStatusFlag(IWDT_FLAG_CNTU))
- {
- if (++counter > DRV_WDT_TIME_OUT)
- {
- LOG_E("Update watchdog reload value complete.");
- return -RT_ERROR;
- }
- }
- IWDT_Refresh();
- IWDT_EnableWriteAccess();
- IWDT_ConfigReload(param * LSI_VALUE >> 8);
- IWDT_DisableWriteAccess();
- break;
- case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
- *(rt_uint32_t *)arg = wdt_config.current_threshold;
- break;
- case RT_DEVICE_CTRL_WDT_START:
- IWDT_Enable();
- IWDT_Refresh();
- break;
- default:
- LOG_W("This command is not supported.");
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- static struct rt_watchdog_ops apm32_wdt_ops =
- {
- apm32_iwdt_init,
- apm32_iwdt_control,
- };
- static int rt_hw_wdt_init(void)
- {
- wdt_config.wdt.ops = &apm32_wdt_ops;
- /* register watchdog device */
- if (rt_hw_watchdog_register(&wdt_config.wdt, "wdt", \
- RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
- {
- LOG_E("wdt device register failed.");
- return -RT_ERROR;
- }
- LOG_D("wdt device register success.");
- return RT_EOK;
- }
- INIT_BOARD_EXPORT(rt_hw_wdt_init);
- #endif
|