mcu_hi3321_watch/tjd/driver/watchdog/watchdog_api.c
2025-05-26 20:15:20 +08:00

155 lines
4.1 KiB
C

/*----------------------------------------------------------------------------
* Copyright (c) Fenda Technologies Co., Ltd. 2020. All rights reserved.
*
* Description: watchdog_api.c
*
* Author: saimen
*
* Create: 2022-7-16
*--------------------------------------------------------------------------*/
//lib
#include <stdlib.h>
#include <string.h>
//os
#include "FreeRTOS.h"
#include "task.h"
//sdk
//#include "apollo4b.h"//uninclude am_hal_lib
#include "am_mcu_apollo.h"
//drv
#include "sys_config.h"
//#include "sys_restart.h"
#include "watchdog_api.h"
#include "rtc_api.h"
//user
#define ENABLE_STATIC_PRINT false
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
#define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__)
#if ENABLE_STATIC_PRINT
#define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)
#else
#define static_print_info(...)
#endif
#define MCU_WDT_RST_TIMES (15) // Note: max value, 16*16 >= 256;
#define MCU_WDT_ISR_TIMES (MCU_WDT_RST_TIMES - 2) // seconds
static uint32_t g_ui32ResetStatus = 0;
am_hal_wdt_config_t g_watchdog_config =
{
// Set the clock for 16HZ
.eClockSource = AM_HAL_WDT_16HZ,
// Enable the interrupt, and set it for 3/4 of a second.
.bInterruptEnable = true,
.ui32InterruptValue = (16 * MCU_WDT_ISR_TIMES),
// Enable the reset, and set it for 15 seconds.
.bResetEnable = true,
.ui32ResetValue = (16 * MCU_WDT_RST_TIMES),
// No DSP.
.bAlertOnDSPReset = false,
};
void am_watchdog_isr(void)
{
uint32_t ui32Status;
#if defined(AM_PART_APOLLO4)
// am_hal_wdt_interrupt_status_get();
// am_hal_wdt_interrupt_clear();
am_hal_wdt_interrupt_status_get(AM_HAL_WDT_MCU, &ui32Status, true);
am_hal_wdt_interrupt_clear(AM_HAL_WDT_MCU, ui32Status);
#else
am_hal_wdt_int_clear();
#endif
static_print_remind("am_watchdog_isr... \r\n");
/*Note:
不使用正常重启流程保存数据,是因为正常保存流程涉及到文件操作,文件操作需要使用动态内存申请,动态内存申请本身就会引发
堵塞导致看门狗超时,最终导致保存失败;
*/
#include "log_api.h"
uint32_t timestamp = rtc_api_get_utc_timestamp();
log_api_record_error(timestamp, EVT_DRIVE_ERROR, INFO1_MCU, INFO2_MCU_WDT_ISR, 0, NULL); //硬狗超时
#include "sys_restart.h"
//sys_anomaly_data_save();
extern uint32_t HardFault_Handler(void);
HardFault_Handler();
static_print_remind("wdt data recover end\r\n");
while(1); //等待看门狗重启设备
}
void watchdog_api_init(void)
{
#if 0
#if defined(AM_PART_APOLLO4)
am_hal_wdt_start(AM_HAL_WDT_MCU, true);
#else
// am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0);
am_hal_wdt_init(&g_sWatchdogConfig);
am_hal_wdt_start();
#endif
#if AM_CMSIS_REGS
NVIC_EnableIRQ(WDT_IRQn);
#else
am_hal_interrupt_enable(AM_HAL_INTERRUPT_WATCHDOG);
#endif
#else
am_hal_reset_status_t sStatus;
am_hal_reset_status_get(&sStatus);
g_ui32ResetStatus = sStatus.eStatus;
static_print_remind("Reset Status Register = 0x%x\r\n",
g_ui32ResetStatus);
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0);
//
// Configure the watchdog.
//
am_hal_wdt_config(AM_HAL_WDT_MCU, &g_watchdog_config);
am_hal_wdt_interrupt_enable(AM_HAL_WDT_MCU, AM_HAL_WDT_INTERRUPT_MCU);
//
// Enable the interrupt for the watchdog in the NVIC.
//
NVIC_SetPriority(WDT_IRQn, AM_IRQ_PRIORITY_DEFAULT-2);
NVIC_EnableIRQ(WDT_IRQn);
am_hal_interrupt_master_enable();
//
// Enable the watchdog.
//
am_hal_wdt_start(AM_HAL_WDT_MCU, false);
#endif
}
uint8_t watchdog_api_get_status(void)
{
#if AM_CMSIS_REGS
return WDT->CFG | WDT_CFG_WDTEN_Msk;
#else
return (AM_REG(WDT, CFG) & AM_REG_WDT_CFG_WDTEN(AM_REG_WDT_CFG_WDTEN_M));
#endif
}
uint32_t watchdog_api_get_rst_ms(void)
{
return MCU_WDT_ISR_TIMES*1000;
}
void watchdog_api_feed(void)
{
am_hal_wdt_restart(AM_HAL_WDT_MCU);
}