Safety systems implementation: IWDG Hardware Watchdog (50ms timeout, config.h WATCHDOG_TIMEOUT_MS): - safety_init() configures IWDG at PSC/32 (0.8ms tick), reload=62 - safety_refresh() must be called every loop iteration - Cannot be disabled once started — MCU resets if loop hangs - Started after 3s USB init delay (avoids spurious startup reset) Arm Hold Interlock (3s, config.h ARMING_HOLD_MS): - Arm command starts a hold timer, not immediate motor enable - Motors only enable after ARMING_HOLD_MS consecutive hold - Disarm or tilt > 10° cancels pending arm - Prevents accidental arm from single keypress Tilt Fault Alert: - safety_alert_tilt_fault() fires one-shot buzzer on TILT_FAULT edge - Rider hears alarm when tilt cutoff triggers - Edge-detected (buzzer only fires once per fault event) RC Timeout (infrastructure): - safety_rc_alive() checks crsf_state.last_rx_ms vs RC_TIMEOUT_MS - RC disarm wired but guarded (no CRSF yet) — remove guard when wired - Compatible with future CRSF implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
52 lines
1.4 KiB
C
52 lines
1.4 KiB
C
#ifndef SAFETY_H
|
|
#define SAFETY_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
/*
|
|
* SaltyLab Safety Systems
|
|
*
|
|
* Covers:
|
|
* - IWDG hardware watchdog (MCU reset if main loop hangs)
|
|
* - RC signal timeout monitoring
|
|
* - Tilt fault alert via buzzer
|
|
* - Arm hold interlock (must hold arm for ARMING_HOLD_MS)
|
|
*/
|
|
|
|
/*
|
|
* safety_init() — call once in main() after HAL_Init().
|
|
* Starts IWDG with WATCHDOG_TIMEOUT_MS timeout from config.h.
|
|
* Starts ARMING_HOLD_MS countdown from config.h.
|
|
*/
|
|
void safety_init(void);
|
|
|
|
/*
|
|
* safety_refresh() — call every main loop iteration.
|
|
* Resets IWDG counter. If not called within WATCHDOG_TIMEOUT_MS,
|
|
* the MCU will reset (independent of software — cannot be disabled).
|
|
*/
|
|
void safety_refresh(void);
|
|
|
|
/*
|
|
* safety_rc_alive() — returns true if RC receiver has sent a frame
|
|
* within RC_TIMEOUT_MS. Call from the balance loop.
|
|
*/
|
|
bool safety_rc_alive(uint32_t now);
|
|
|
|
/*
|
|
* safety_alert_tilt_fault() — one-shot buzzer beep for tilt fault.
|
|
* Safe to call repeatedly; only fires once per fault.
|
|
*/
|
|
void safety_alert_tilt_fault(bool faulted);
|
|
|
|
/*
|
|
* safety_arm_interlock() — returns true once arm button has been
|
|
* held for ARMING_HOLD_MS from the moment safety_arm_start() was called.
|
|
*/
|
|
void safety_arm_start(uint32_t now); /* Call when arm requested */
|
|
bool safety_arm_ready(uint32_t now); /* Poll until true, then arm */
|
|
void safety_arm_cancel(void); /* Cancel pending arm */
|
|
|
|
#endif /* SAFETY_H */
|