trussed_core/
interrupt.rs1use core::{
2 fmt::Debug,
3 sync::atomic::{AtomicU8, Ordering::Relaxed},
4};
5
6#[derive(Default, Debug, PartialEq, Eq)]
7pub enum InterruptState {
8 #[default]
9 Idle = 0,
10 Working = 1,
11 Interrupted = 2,
12}
13
14#[derive(Default, Debug, PartialEq, Eq, Clone)]
15pub struct FromU8Error;
16
17impl TryFrom<u8> for InterruptState {
18 type Error = FromU8Error;
19 fn try_from(value: u8) -> Result<Self, Self::Error> {
20 match value {
21 0 => Ok(Self::Idle),
22 1 => Ok(Self::Working),
23 2 => Ok(Self::Interrupted),
24 _ => Err(FromU8Error),
25 }
26 }
27}
28
29impl From<InterruptState> for u8 {
30 fn from(value: InterruptState) -> Self {
31 value as _
32 }
33}
34
35#[derive(Default)]
36pub struct InterruptFlag(AtomicU8);
37
38const CONV_ERROR: &str =
39 "Internal trussed error: InterruptState must always be set to an enum variant";
40
41impl InterruptFlag {
42 pub const fn new() -> Self {
43 Self(AtomicU8::new(0))
44 }
45 fn load(&self) -> InterruptState {
46 self.0.load(Relaxed).try_into().expect(CONV_ERROR)
47 }
48
49 pub fn set_idle(&self) {
50 self.0.store(InterruptState::Idle.into(), Relaxed)
51 }
52 pub fn set_working(&self) {
53 self.0.store(InterruptState::Working.into(), Relaxed)
54 }
55 pub fn interrupt(&self) -> bool {
56 self.0
57 .compare_exchange(
58 InterruptState::Working.into(),
59 InterruptState::Interrupted.into(),
60 Relaxed,
61 Relaxed,
62 )
63 .is_ok()
64 }
65
66 pub fn is_interrupted(&self) -> bool {
67 let res = self.load();
68 res == InterruptState::Interrupted
69 }
70}
71
72impl Debug for InterruptFlag {
73 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
74 self.load().fmt(f)
75 }
76}