Skip to main content

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// SAFETY (module-wide contract for the `unsafe { bindings::ove_*(...) }` FFI
17// calls below): any handle passed to the C API is non-null and refers to a
18// live RTOS object — wrapper constructors establish validity via
19// `Error::from_code`, and `Drop` (or an explicit `deinit`) is the only place
20// a handle is released. Pointer and slice arguments reference caller-owned
21// memory valid for the duration of the call; the C side copies whatever it
22// retains and does not alias them past return (verified against the
23// signatures in `include/ove/*.h`). Blocks that deviate — `transmute`, raw
24// pointer casts from user data, slice reconstruction via `from_raw_parts`,
25// or storing a callback across the FFI boundary — carry their own
26// `// SAFETY:` comment.
27
28/// RAII watchdog timer.
29pub struct Watchdog {
30    handle: bindings::ove_watchdog_t,
31}
32
33impl Watchdog {
34    /// Create a new watchdog via heap allocation (only in heap mode).
35    #[cfg(not(zero_heap))]
36    pub fn new(timeout_ms: u32) -> Result<Self> {
37        let mut handle: bindings::ove_watchdog_t = core::ptr::null_mut();
38        let rc = unsafe { bindings::ove_watchdog_create(&mut handle, timeout_ms) };
39        Error::from_code(rc)?;
40        Ok(Self { handle })
41    }
42
43    /// Create from caller-provided static storage.
44    ///
45    /// # Safety
46    /// Caller must ensure `storage` outlives the `Watchdog`.
47    #[cfg(zero_heap)]
48    pub unsafe fn from_static(
49        storage: *mut bindings::ove_watchdog_storage_t,
50        timeout_ms: u32,
51    ) -> Result<Self> {
52        let mut handle: bindings::ove_watchdog_t = core::ptr::null_mut();
53        let rc = unsafe { bindings::ove_watchdog_init(&mut handle, storage, timeout_ms) };
54        Error::from_code(rc)?;
55        Ok(Self { handle })
56    }
57
58    /// Start the watchdog timer. The system will reset if [`feed`](Watchdog::feed)
59    /// is not called within `timeout_ms` milliseconds.
60    ///
61    /// # Errors
62    /// Returns an error if the watchdog hardware could not be started.
63    pub fn start(&self) -> Result<()> {
64        let rc = unsafe { bindings::ove_watchdog_start(self.handle) };
65        Error::from_code(rc)
66    }
67
68    /// Feed (kick) the watchdog to reset its countdown and prevent a system reset.
69    ///
70    /// # Errors
71    /// Returns an error if the watchdog hardware rejects the feed command.
72    pub fn feed(&self) -> Result<()> {
73        let rc = unsafe { bindings::ove_watchdog_feed(self.handle) };
74        Error::from_code(rc)
75    }
76}
77
78crate::ove_handle_impl!(Watchdog, ove_watchdog_destroy, ove_watchdog_deinit);