ove/
watchdog.rs

1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! Hardware watchdog timer for oveRTOS.
8//!
9//! A [`Watchdog`] triggers a system reset if its countdown is not refreshed by
10//! calling [`Watchdog::feed`] within the configured timeout. Start with
11//! [`Watchdog::start`] and call `feed` periodically from a health-check thread.
12
13use crate::bindings;
14use crate::error::{Error, Result};
15
16/// RAII watchdog timer.
17pub struct Watchdog {
18    handle: bindings::ove_watchdog_t,
19}
20
21impl Watchdog {
22    /// Create a new watchdog via heap allocation (only in heap mode).
23    #[cfg(not(zero_heap))]
24    pub fn new(timeout_ms: u32) -> Result<Self> {
25        let mut handle: bindings::ove_watchdog_t = core::ptr::null_mut();
26        let rc = unsafe { bindings::ove_watchdog_create(&mut handle, timeout_ms) };
27        Error::from_code(rc)?;
28        Ok(Self { handle })
29    }
30
31    /// Create from caller-provided static storage.
32    ///
33    /// # Safety
34    /// Caller must ensure `storage` outlives the `Watchdog`.
35    #[cfg(zero_heap)]
36    pub unsafe fn from_static(
37        storage: *mut bindings::ove_watchdog_storage_t,
38        timeout_ms: u32,
39    ) -> Result<Self> {
40        let mut handle: bindings::ove_watchdog_t = core::ptr::null_mut();
41        let rc = unsafe { bindings::ove_watchdog_init(&mut handle, storage, timeout_ms) };
42        Error::from_code(rc)?;
43        Ok(Self { handle })
44    }
45
46    /// Start the watchdog timer. The system will reset if [`feed`](Watchdog::feed)
47    /// is not called within `timeout_ms` milliseconds.
48    ///
49    /// # Errors
50    /// Returns an error if the watchdog hardware could not be started.
51    pub fn start(&self) -> Result<()> {
52        let rc = unsafe { bindings::ove_watchdog_start(self.handle) };
53        Error::from_code(rc)
54    }
55
56    /// Feed (kick) the watchdog to reset its countdown and prevent a system reset.
57    ///
58    /// # Errors
59    /// Returns an error if the watchdog hardware rejects the feed command.
60    pub fn feed(&self) -> Result<()> {
61        let rc = unsafe { bindings::ove_watchdog_feed(self.handle) };
62        Error::from_code(rc)
63    }
64}
65
66impl Drop for Watchdog {
67    fn drop(&mut self) {
68        if self.handle.is_null() { return; }
69        #[cfg(not(zero_heap))]
70        unsafe { bindings::ove_watchdog_destroy(self.handle) }
71        #[cfg(zero_heap)]
72        unsafe { bindings::ove_watchdog_deinit(self.handle) }
73    }
74}
75
76// SAFETY: Watchdog wraps an opaque RTOS handle. Feed/start are thread-safe
77// RTOS calls. Create/destroy are single-threaded (lifecycle guarantee).
78unsafe impl Send for Watchdog {}
79unsafe impl Sync for Watchdog {}