1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! Furi Event Flag.
use core::ptr::NonNull;
use crate::furi::Error;
use crate::furi::time::FuriDuration;
use flipperzero_sys as sys;
use flipperzero_sys::furi::Status;
pub struct EventFlag {
raw: NonNull<sys::FuriEventFlag>,
}
impl EventFlag {
pub fn new() -> Self {
Self {
// SAFETY: Alloc always returns valid non-null pointer or triggers `furi_crash`.
raw: unsafe { NonNull::new_unchecked(sys::furi_event_flag_alloc()) },
}
}
/// Get pointer to raw [`sys::FuriEventFlag`].
///
/// This pointer must not be `free`d or otherwise invalidated.
/// It must not be referenced after [`EventFlag`] has been dropped.
pub fn as_ptr(&self) -> *mut sys::FuriEventFlag {
self.raw.as_ptr()
}
/// Set flags.
///
/// # Warning
/// The result of this function can be flags that you've just asked to
/// set or not if someone was waiting for them and asked to clear it.
/// It is highly recommended to read the `furi_event_flag_set`
/// and `xEventGroupSetBits`` source code.
pub fn set(&self, flags: u32) -> Result<u32, Error> {
Status::from(unsafe { sys::furi_event_flag_set(self.as_ptr(), flags) })
.into_result()
.map(|s| s as u32)
}
/// Clear flags
pub fn clear(&self, flags: u32) -> Result<u32, Error> {
Status::from(unsafe { sys::furi_event_flag_clear(self.as_ptr(), flags) })
.into_result()
.map(|s| s as u32)
}
/// Get flags.
pub fn get(&self) -> u32 {
unsafe { sys::furi_event_flag_get(self.as_ptr()) }
}
/// Wait for up-to `timeout` for a change to any of the specified notification `flags`.
///
/// If `clear`, then the specified flags will be cleared after a notification is received.
pub fn wait_any_flags(
&self,
flags: u32,
clear: bool,
timeout: FuriDuration,
) -> Result<u32, Error> {
let mut options = sys::FuriFlagWaitAny;
if !clear {
options |= sys::FuriFlagNoClear;
}
Status::from(unsafe {
sys::furi_event_flag_wait(self.as_ptr(), flags, options.0, timeout.0)
})
.into_result()
.map(|s| s as u32)
}
/// Wait for up-to `timeout` for a change to all of the specified notification `flags`.
///
/// If `clear`, then the specified flags will be cleared after a notification is received.
pub fn wait_all_flags(
&self,
flags: u32,
clear: bool,
timeout: FuriDuration,
) -> Result<u32, Error> {
let mut options = sys::FuriFlagWaitAll;
if !clear {
options |= sys::FuriFlagNoClear;
}
Status::from(unsafe {
sys::furi_event_flag_wait(self.as_ptr(), flags, options.0, timeout.0)
})
.into_result()
.map(|s| s as u32)
}
}
impl Default for EventFlag {
fn default() -> Self {
Self::new()
}
}
impl Drop for EventFlag {
fn drop(&mut self) {
// SAFETY: Pointer is valid and non-null
unsafe { sys::furi_event_flag_free(self.as_ptr()) }
}
}