zencan_node/
node_state.rs

1//! Implements node state struct
2use zencan_common::nmt::NmtState;
3use zencan_common::AtomicCell;
4
5use crate::object_dict::ObjectFlagSync;
6
7use crate::pdo::Pdo;
8use crate::storage::StorageContext;
9
10pub trait NmtStateAccess: Send + Sync {
11    fn nmt_state(&self) -> NmtState;
12}
13
14impl NmtStateAccess for AtomicCell<NmtState> {
15    fn nmt_state(&self) -> NmtState {
16        self.load()
17    }
18}
19
20/// The NodeState provides config-dependent storage to the [`Node`](crate::Node) object
21///
22/// The node state has to get instantiated (statically) by zencan-build, based on the device config
23/// via the [`NodeStateAccess`] trait.
24/// file. It is then provided to the node by the application when it is instantiated, and accessed
25#[allow(missing_debug_implementations)]
26pub struct NodeState<'a> {
27    /// Pdo control objects for receive PDOs
28    rpdos: &'a [Pdo<'a>],
29    /// Pdo control objects for transmit PDOs
30    tpdos: &'a [Pdo<'a>],
31    /// A global flag used by all objects to synchronize their event flag A/B swapping
32    object_flag_sync: ObjectFlagSync,
33    /// State shared between the [`StorageCommandObject`](crate::storage::StorageCommandObject) and
34    /// [`Node`](crate::node::Node) for indicating when a store objects command has been recieved.
35    storage_context: StorageContext,
36    /// Global storage for the NMT state
37    nmt_state: AtomicCell<NmtState>,
38}
39
40impl NmtStateAccess for NodeState<'_> {
41    fn nmt_state(&self) -> NmtState {
42        self.nmt_state.load()
43    }
44}
45
46impl<'a> NodeState<'a> {
47    /// Create a new NodeState object
48    pub const fn new(rpdos: &'a [Pdo<'a>], tpdos: &'a [Pdo<'a>]) -> Self {
49        let object_flag_sync = ObjectFlagSync::new();
50        let storage_context = StorageContext::new();
51
52        Self {
53            rpdos,
54            tpdos,
55            object_flag_sync,
56            storage_context,
57            nmt_state: AtomicCell::new(NmtState::Bootup),
58        }
59    }
60
61    /// Access the RPDOs as a const function
62    pub const fn rpdos(&self) -> &'a [Pdo<'a>] {
63        self.rpdos
64    }
65
66    /// Access the TPDOs as a const function
67    pub const fn tpdos(&self) -> &'a [Pdo<'a>] {
68        self.tpdos
69    }
70
71    /// Access the pdo_sync as a const function
72    ///
73    /// This is required so that it can be shared with the objects in generated code
74    pub const fn object_flag_sync(&'a self) -> &'a ObjectFlagSync {
75        &self.object_flag_sync
76    }
77
78    /// Access the storage_context as a const function
79    pub const fn storage_context(&'a self) -> &'a StorageContext {
80        &self.storage_context
81    }
82
83    /// Set the NMT state
84    ///
85    /// This method is intended only for the `Node` object to update the global node nmt state
86    pub(crate) fn set_nmt_state(&self, nmt_state: NmtState) {
87        self.nmt_state.store(nmt_state);
88    }
89}