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);