ove/
eventgroup.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//! Event group (bitfield synchronization) for oveRTOS.
8//!
9//! An [`EventGroup`] holds a set of bits that any thread or ISR can set or clear.
10//! Other threads can block until specific bit patterns appear, enabling fine-grained
11//! inter-task signalling without dedicated queues.
12
13use core::fmt;
14
15use crate::bindings;
16use crate::error::{Error, Result};
17
18/// Flags controlling [`EventGroup::wait_bits`] behavior.
19///
20/// Flags can be combined with the `|` operator.
21#[derive(Clone, Copy, Debug, Default)]
22pub struct WaitFlags(u32);
23
24impl WaitFlags {
25    /// No flags — wait for any bit, don't clear on exit.
26    pub const NONE: Self = Self(0);
27    /// Wait for ALL specified bits (vs any).
28    pub const WAIT_ALL: Self = Self(0x01);
29    /// Clear matched bits on successful wait.
30    pub const CLEAR_ON_EXIT: Self = Self(0x02);
31}
32
33impl core::ops::BitOr for WaitFlags {
34    type Output = Self;
35    fn bitor(self, rhs: Self) -> Self { Self(self.0 | rhs.0) }
36}
37
38/// Deprecated alias for [`WaitFlags::WAIT_ALL`].
39#[deprecated(note = "use WaitFlags::WAIT_ALL instead")]
40pub const EG_WAIT_ALL: WaitFlags = WaitFlags::WAIT_ALL;
41/// Deprecated alias for [`WaitFlags::CLEAR_ON_EXIT`].
42#[deprecated(note = "use WaitFlags::CLEAR_ON_EXIT instead")]
43pub const EG_CLEAR_ON_EXIT: WaitFlags = WaitFlags::CLEAR_ON_EXIT;
44
45/// Event group — a set of named bits that can be set, cleared, and waited on.
46pub struct EventGroup {
47    handle: bindings::ove_eventgroup_t,
48}
49
50impl EventGroup {
51    /// Create a new event group via heap allocation (only in heap mode).
52    #[cfg(not(zero_heap))]
53    pub fn new() -> Result<Self> {
54        let mut handle: bindings::ove_eventgroup_t = core::ptr::null_mut();
55        let rc = unsafe { bindings::ove_eventgroup_create(&mut handle) };
56        Error::from_code(rc)?;
57        Ok(Self { handle })
58    }
59
60    /// Create from caller-provided static storage.
61    ///
62    /// # Safety
63    /// Caller must ensure `storage` outlives the `EventGroup`.
64    #[cfg(zero_heap)]
65    pub unsafe fn from_static(
66        storage: *mut bindings::ove_eventgroup_storage_t,
67    ) -> Result<Self> {
68        let mut handle: bindings::ove_eventgroup_t = core::ptr::null_mut();
69        let rc = unsafe { bindings::ove_eventgroup_init(&mut handle, storage) };
70        Error::from_code(rc)?;
71        Ok(Self { handle })
72    }
73
74    /// Set bits in the event group. Returns the bits value after setting.
75    pub fn set_bits(&self, bits: u32) -> u32 {
76        unsafe { bindings::ove_eventgroup_set_bits(self.handle, bits) }
77    }
78
79    /// Clear bits in the event group. Returns the bits value before clearing.
80    pub fn clear_bits(&self, bits: u32) -> u32 {
81        unsafe { bindings::ove_eventgroup_clear_bits(self.handle, bits) }
82    }
83
84    /// Wait for the specified bits to be set in the event group.
85    ///
86    /// `flags` is a combination of [`WaitFlags::WAIT_ALL`] and [`WaitFlags::CLEAR_ON_EXIT`].
87    /// Returns the bits value at the moment the wait condition was satisfied.
88    ///
89    /// # Errors
90    /// Returns [`Error::Timeout`] if the bits are not set within `timeout_ms`.
91    pub fn wait_bits(&self, bits: u32, flags: WaitFlags, timeout_ms: u32) -> Result<u32> {
92        let mut result: u32 = 0;
93        let rc = unsafe {
94            bindings::ove_eventgroup_wait_bits(
95                self.handle,
96                bits,
97                flags.0,
98                timeout_ms,
99                &mut result,
100            )
101        };
102        Error::from_code(rc)?;
103        Ok(result)
104    }
105
106    /// Set bits from an ISR context. Returns the bits value after setting.
107    pub fn set_bits_from_isr(&self, bits: u32) -> u32 {
108        unsafe { bindings::ove_eventgroup_set_bits_from_isr(self.handle, bits) }
109    }
110
111    /// Get current bits value.
112    pub fn get_bits(&self) -> u32 {
113        unsafe { bindings::ove_eventgroup_get_bits(self.handle) }
114    }
115}
116
117impl fmt::Debug for EventGroup {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        f.debug_struct("EventGroup")
120            .field("handle", &format_args!("{:p}", self.handle))
121            .finish()
122    }
123}
124
125impl Drop for EventGroup {
126    fn drop(&mut self) {
127        if self.handle.is_null() { return; }
128        #[cfg(not(zero_heap))]
129        unsafe { bindings::ove_eventgroup_destroy(self.handle) }
130        #[cfg(zero_heap)]
131        unsafe { bindings::ove_eventgroup_deinit(self.handle) }
132    }
133}
134
135// SAFETY: Wraps a ove handle. Set/clear/wait are thread-safe RTOS calls.
136// Create/destroy are single-threaded (lifecycle guarantee).
137unsafe impl Send for EventGroup {}
138unsafe impl Sync for EventGroup {}