feat: Integrate IWDG watchdog timer driver (Issue #300)

- Replace safety.c's direct IWDG initialization with watchdog module API
- Use watchdog_init(2000) for ~2s timeout in safety_init()
- Use watchdog_kick() in safety_refresh() to feed the watchdog
- Remove unused watchdog_get_divider() helper function
- Watchdog now configured with automatic prescaler selection

The watchdog module provides a clean, flexible IWDG interface that:
- Automatically calculates prescaler and reload values
- Detects watchdog-triggered resets via watchdog_was_reset_by_watchdog()
- Supports timeout range of ~1ms to ~32 seconds
- Integrates seamlessly with existing safety system

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
sl-mechanical 2026-03-03 17:29:59 -05:00
parent e2587b60fb
commit 5cec6779e5
2 changed files with 5 additions and 28 deletions

View File

@ -12,20 +12,9 @@
#include "safety.h" #include "safety.h"
#include "config.h" #include "config.h"
#include "crsf.h" #include "crsf.h"
#include "watchdog.h"
#include "stm32f7xx_hal.h" #include "stm32f7xx_hal.h"
/* IWDG prescaler 32 → LSI(40kHz)/32 = 1250 ticks/sec → 0.8ms/tick */
#define IWDG_PRESCALER IWDG_PRESCALER_32
/* Integer formula: timeout_ms * LSI_HZ / (prescaler * 1000)
* = WATCHDOG_TIMEOUT_MS * 40000 / (32 * 1000) = WATCHDOG_TIMEOUT_MS * 40 / 32 */
#define IWDG_RELOAD (WATCHDOG_TIMEOUT_MS * 40UL / 32UL)
#if IWDG_RELOAD > 4095
# error "WATCHDOG_TIMEOUT_MS too large for IWDG_PRESCALER_32 — increase prescaler"
#endif
static IWDG_HandleTypeDef hiwdg;
/* Arm interlock */ /* Arm interlock */
static uint32_t s_arm_start_ms = 0; static uint32_t s_arm_start_ms = 0;
static bool s_arm_pending = false; static bool s_arm_pending = false;
@ -36,15 +25,13 @@ static bool s_was_faulted = false;
static EstopSource s_estop_source = ESTOP_CLEAR; static EstopSource s_estop_source = ESTOP_CLEAR;
void safety_init(void) { void safety_init(void) {
hiwdg.Instance = IWDG; /* Initialize IWDG via watchdog module (Issue #300) with ~2s timeout */
hiwdg.Init.Prescaler = IWDG_PRESCALER; watchdog_init(2000);
hiwdg.Init.Reload = IWDG_RELOAD;
hiwdg.Init.Window = IWDG_WINDOW_DISABLE;
HAL_IWDG_Init(&hiwdg); /* Starts watchdog immediately */
} }
void safety_refresh(void) { void safety_refresh(void) {
if (hiwdg.Instance) HAL_IWDG_Refresh(&hiwdg); /* Feed the watchdog timer */
watchdog_kick();
} }
bool safety_rc_alive(uint32_t now) { bool safety_rc_alive(uint32_t now) {

View File

@ -76,16 +76,6 @@ static bool watchdog_calculate_config(uint32_t timeout_ms,
return false; /* No suitable prescaler found */ return false; /* No suitable prescaler found */
} }
/* Get prescaler divider from prescaler value */
static uint16_t watchdog_get_divider(uint8_t prescaler)
{
const uint16_t dividers[] = {4, 8, 16, 32, 64, 128, 256};
if (prescaler < 7) {
return dividers[prescaler];
}
return 256;
}
/* ================================================================ /* ================================================================
* Public API * Public API
* ================================================================ */ * ================================================================ */