1#![no_std]
2
3#[cfg(not(feature = "rt-crate-cortex-m-rt"))]
4compile_error!("This crate requires any rt-crate-* to be enabled (when using build-rs feature)! *currently only rt-crate-cortex-m-rt is supported*");
5
6
7#[cfg(feature = "build-rs")]
8mod build_rs;
9
10use core::marker::PhantomData;
11#[cfg(feature = "build-rs")]
12pub use build_rs::*;
13
14use core::sync::atomic::AtomicBool;
15
16pub mod meta;
17
18#[cfg(not(feature = "build-rs"))]
19pub mod device;
20
21#[derive(Copy, Clone)]
22pub enum CellType {
23 Primary,
24 NonPrimary
25}
26
27#[derive(PartialEq, Copy, Clone)]
28pub enum HeaderType {
29 Actual,
30 Dummy
31}
32
33pub unsafe trait WithSignature {
34 const VALID_SIGNATURE: u32;
35}
36
37pub unsafe trait Cell: WithSignature {
38 const CUR_META: meta::CellDefMeta;
39 const CELLS_META: &'static [meta::CellDefMeta];
40 const DEVICE_CONFIG: meta::DeviceConfigMeta;
41 fn check_signature(&self, init_memory: bool) -> bool;
42 fn static_sha256(&self) -> [u8; 32] {
43 Self::CUR_META.struct_sha256
44 }
45}
46
47pub struct CellWrapper<T, K>
50where T: 'static {
51 header: &'static T,
52 header_type: HeaderType,
53 is_init: AtomicBool,
54 _phantom: PhantomData<K>
55}
56
57pub struct Forward;
58pub struct Backward;
59
60impl<T> core::ops::Deref for CellWrapper<T, Forward>
61 where T: Cell + 'static {
62 type Target = T;
63 fn deref(&self) -> &Self::Target {
64 if !self.is_init.load(core::sync::atomic::Ordering::Relaxed) {
65 if self.ensure_init().is_some() {
67 self.is_init.store(true, core::sync::atomic::Ordering::Relaxed);
68 return self.header;
69 }
70 panic!("CellWrapper initialization failed!");
71 }
72 self.header
73 }
74}
75
76
77impl<T> core::ops::Deref for CellWrapper<T, Backward>
78 where T: Cell + 'static {
79 type Target = T;
80 fn deref(&self) -> &Self::Target {
81 if !self.is_init.load(core::sync::atomic::Ordering::Relaxed) {
82 if self.ensure_init().is_some() {
84 self.is_init.store(true, core::sync::atomic::Ordering::Relaxed);
85 return self.header;
86 }
87 panic!("CellWrapper initialization failed!");
88 }
89 self.header
90 }
91}
92
93
94impl<T, K> CellWrapper<T, K>
95 where T: Cell + 'static {
96 pub const unsafe fn _new_uninit(h: &'static T) -> Self {
97 Self {
98 header: h,
99 header_type: HeaderType::Actual,
100 is_init: AtomicBool::new(false),
101 _phantom: PhantomData
102 }
103 }
104
105 pub const fn new_dummy(dummy_header: &'static T) -> Self {
106 Self {
107 header: dummy_header,
108 header_type: HeaderType::Dummy,
109 is_init: AtomicBool::new(true),
110 _phantom: PhantomData
111 }
112 }
113}
114
115
116impl<T> CellWrapper<T, Forward>
117 where T: Cell + 'static {
118 pub unsafe fn _new_init(h: &'static T) -> Option<Self> {
119 if !h.check_signature(true) {
120 return None;
121 }
122
123 Some(Self {
124 header: h,
125 header_type: HeaderType::Actual,
126 is_init: AtomicBool::new(true),
127 _phantom: PhantomData
128 })
129 }
130
131 pub fn ensure_init(&self) -> Option<()> {
133 if self.is_init.load(core::sync::atomic::Ordering::Relaxed) {
134 return Some(());
135 }
136 if !self.header.check_signature(true) {
138 return None;
139 }
140 self.is_init.store(true, core::sync::atomic::Ordering::Relaxed);
141 Some(())
142 }
143
144 pub fn is_dummy(&self) -> bool {
145 self.header_type == HeaderType::Dummy
146 }
147}
148
149
150
151impl<T> CellWrapper<T, Backward>
152 where T: Cell + 'static {
153 pub unsafe fn _new_init(h: &'static T) -> Option<Self> {
154 if !h.check_signature(false) {
155 return None;
156 }
157
158 Some(Self {
159 header: h,
160 header_type: HeaderType::Actual,
161 is_init: AtomicBool::new(true),
162 _phantom: PhantomData
163 })
164 }
165
166 pub fn ensure_init(&self) -> Option<()> {
168 if self.is_init.load(core::sync::atomic::Ordering::Relaxed) {
169 return Some(());
170 }
171 if !self.header.check_signature(false) {
173 return None;
174 }
175 self.is_init.store(true, core::sync::atomic::Ordering::Relaxed);
176 Some(())
177 }
178
179 pub fn is_dummy(&self) -> bool {
180 self.header_type == HeaderType::Dummy
181 }
182}