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 "config.h"
#include "crsf.h"
#include "watchdog.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 */
static uint32_t s_arm_start_ms = 0;
static bool s_arm_pending = false;
@ -36,15 +25,13 @@ static bool s_was_faulted = false;
static EstopSource s_estop_source = ESTOP_CLEAR;
void safety_init(void) {
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER;
hiwdg.Init.Reload = IWDG_RELOAD;
hiwdg.Init.Window = IWDG_WINDOW_DISABLE;
HAL_IWDG_Init(&hiwdg); /* Starts watchdog immediately */
/* Initialize IWDG via watchdog module (Issue #300) with ~2s timeout */
watchdog_init(2000);
}
void safety_refresh(void) {
if (hiwdg.Instance) HAL_IWDG_Refresh(&hiwdg);
/* Feed the watchdog timer */
watchdog_kick();
}
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 */
}
/* 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
* ================================================================ */