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 {}