|
7 | 7 |
|
8 | 8 | use crate::sync::atomic::{AtomicUsize, Ordering};
|
9 | 9 |
|
| 10 | +pub mod gpio; |
| 11 | +pub mod flash; |
| 12 | + |
10 | 13 | // Allow dead code, because it isn't required for a given build to have any devices.
|
11 | 14 | /// Device uniqueness.
|
12 | 15 | ///
|
@@ -35,186 +38,3 @@ impl Unique {
|
35 | 38 | self.0.fetch_add(1, Ordering::AcqRel) == 0
|
36 | 39 | }
|
37 | 40 | }
|
38 |
| - |
39 |
| -pub mod gpio { |
40 |
| - //! Most devices in Zephyr operate on a `struct device`. This provides untyped access to |
41 |
| - //! devices. We want to have stronger typing in the Zephyr interfaces, so most of these types |
42 |
| - //! will be wrapped in another structure. This wraps a Gpio device, and provides methods to |
43 |
| - //! most of the operations on gpios. |
44 |
| - //! |
45 |
| - //! Safey: In general, even just using gpio pins is unsafe in Zephyr. The gpio drivers are used |
46 |
| - //! pervasively throughout Zephyr device drivers. As such, most of the calls in this module are |
47 |
| - //! unsafe. |
48 |
| -
|
49 |
| - use crate::raw; |
50 |
| - use super::Unique; |
51 |
| - |
52 |
| - /// Global instance to help make gpio in Rust slightly safer. |
53 |
| - /// |
54 |
| - /// To help with safety, the rust types use a global instance of a gpio-token. Methods will |
55 |
| - /// take a mutable reference to this, which will require either a single thread in the |
56 |
| - /// application code, or something like a mutex or critical section to manage. The operation |
57 |
| - /// methods are still unsafe, because we have no control over what happens with the gpio |
58 |
| - /// operations outside of Rust code, but this will help make the Rust usage at least better. |
59 |
| - pub struct GpioToken(()); |
60 |
| - |
61 |
| - static GPIO_TOKEN: Unique = Unique::new(); |
62 |
| - |
63 |
| - impl GpioToken { |
64 |
| - /// Retrieves the gpio token. This is unsafe because lots of code in zephyr operates on the |
65 |
| - /// gpio drivers. |
66 |
| - pub unsafe fn get_instance() -> Option<GpioToken> { |
67 |
| - if !GPIO_TOKEN.once() { |
68 |
| - return None; |
69 |
| - } |
70 |
| - Some(GpioToken(())) |
71 |
| - } |
72 |
| - } |
73 |
| - |
74 |
| - /// A single instance of a zephyr device to manage a gpio controller. A gpio controller |
75 |
| - /// represents a set of gpio pins, that are generally operated on by the same hardware block. |
76 |
| - pub struct Gpio { |
77 |
| - /// The underlying device itself. |
78 |
| - #[allow(dead_code)] |
79 |
| - pub(crate) device: *const raw::device, |
80 |
| - } |
81 |
| - |
82 |
| - impl Gpio { |
83 |
| - /// Constructor, used by the devicetree generated code. |
84 |
| - /// |
85 |
| - /// TODO: Guarantee single instancing. |
86 |
| - pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device) -> Option<Gpio> { |
87 |
| - if !unique.once() { |
88 |
| - return None; |
89 |
| - } |
90 |
| - Some(Gpio { device }) |
91 |
| - } |
92 |
| - |
93 |
| - /// Verify that the device is ready for use. At a minimum, this means the device has been |
94 |
| - /// successfully initialized. |
95 |
| - pub fn is_ready(&self) -> bool { |
96 |
| - unsafe { |
97 |
| - raw::device_is_ready(self.device) |
98 |
| - } |
99 |
| - } |
100 |
| - } |
101 |
| - |
102 |
| - /// A GpioPin represents a single pin on a gpio device. |
103 |
| - /// |
104 |
| - /// This is a lightweight wrapper around the Zephyr `gpio_dt_spec` structure. Note that |
105 |
| - /// multiple pins may share a gpio controller, and as such, all methods on this are both unsafe, |
106 |
| - /// and require a mutable reference to the [`GpioToken`]. |
107 |
| - #[allow(dead_code)] |
108 |
| - pub struct GpioPin { |
109 |
| - pub(crate) pin: raw::gpio_dt_spec, |
110 |
| - } |
111 |
| - |
112 |
| - impl GpioPin { |
113 |
| - /// Constructor, used by the devicetree generated code. |
114 |
| - /// |
115 |
| - /// TODO: Guarantee single instancing. |
116 |
| - pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device, pin: u32, dt_flags: u32) -> Option<GpioPin> { |
117 |
| - if !unique.once() { |
118 |
| - return None; |
119 |
| - } |
120 |
| - Some(GpioPin { |
121 |
| - pin: raw::gpio_dt_spec { |
122 |
| - port: device, |
123 |
| - pin: pin as raw::gpio_pin_t, |
124 |
| - dt_flags: dt_flags as raw::gpio_dt_flags_t, |
125 |
| - } |
126 |
| - }) |
127 |
| - } |
128 |
| - |
129 |
| - /// Verify that the device is ready for use. At a minimum, this means the device has been |
130 |
| - /// successfully initialized. |
131 |
| - pub fn is_ready(&self) -> bool { |
132 |
| - self.get_gpio().is_ready() |
133 |
| - } |
134 |
| - |
135 |
| - /// Get the underlying Gpio device. |
136 |
| - pub fn get_gpio(&self) -> Gpio { |
137 |
| - Gpio { |
138 |
| - device: self.pin.port, |
139 |
| - } |
140 |
| - } |
141 |
| - |
142 |
| - /// Configure a single pin. |
143 |
| - pub unsafe fn configure(&mut self, _token: &mut GpioToken, extra_flags: raw::gpio_flags_t) { |
144 |
| - // TODO: Error? |
145 |
| - unsafe { |
146 |
| - raw::gpio_pin_configure(self.pin.port, |
147 |
| - self.pin.pin, |
148 |
| - self.pin.dt_flags as raw::gpio_flags_t | extra_flags); |
149 |
| - } |
150 |
| - } |
151 |
| - |
152 |
| - /// Toggle pin level. |
153 |
| - pub unsafe fn toggle_pin(&mut self, _token: &mut GpioToken) { |
154 |
| - // TODO: Error? |
155 |
| - unsafe { |
156 |
| - raw::gpio_pin_toggle_dt(&self.pin); |
157 |
| - } |
158 |
| - } |
159 |
| - } |
160 |
| -} |
161 |
| - |
162 |
| -pub mod flash { |
163 |
| - //! Device wrappers for flash controllers, and flash partitions. |
164 |
| -
|
165 |
| - use crate::raw; |
166 |
| - use super::Unique; |
167 |
| - |
168 |
| - /// A flash controller |
169 |
| - /// |
170 |
| - /// This is a wrapper around the `struct device` in Zephyr that represents a flash controller. |
171 |
| - /// Using the flash controller allows flash operations on the entire device. See |
172 |
| - /// [`FlashPartition`] for a wrapper that limits the operation to a partition as defined in the |
173 |
| - /// DT. |
174 |
| - #[allow(dead_code)] |
175 |
| - pub struct FlashController { |
176 |
| - pub(crate) device: *const raw::device, |
177 |
| - } |
178 |
| - |
179 |
| - impl FlashController { |
180 |
| - /// Constructor, intended to be called by devicetree generated code. |
181 |
| - pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device) -> Option<FlashController> { |
182 |
| - if !unique.once() { |
183 |
| - return None; |
184 |
| - } |
185 |
| - |
186 |
| - Some(FlashController { device }) |
187 |
| - } |
188 |
| - } |
189 |
| - |
190 |
| - /// A wrapper for flash partitions. There is no Zephyr struct that corresponds with this |
191 |
| - /// information, which is typically used in a more direct underlying manner. |
192 |
| - #[allow(dead_code)] |
193 |
| - pub struct FlashPartition { |
194 |
| - /// The underlying controller. |
195 |
| - #[allow(dead_code)] |
196 |
| - pub(crate) controller: FlashController, |
197 |
| - #[allow(dead_code)] |
198 |
| - pub(crate) offset: u32, |
199 |
| - #[allow(dead_code)] |
200 |
| - pub(crate) size: u32, |
201 |
| - } |
202 |
| - |
203 |
| - impl FlashPartition { |
204 |
| - /// Constructor, intended to be called by devicetree generated code. |
205 |
| - pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device, offset: u32, size: u32) -> Option<FlashPartition> { |
206 |
| - if !unique.once() { |
207 |
| - return None; |
208 |
| - } |
209 |
| - |
210 |
| - // The `get_instance` on the flash controller would try to guarantee a unique instance, |
211 |
| - // but in this case, we need one for each device, so just construct it here. |
212 |
| - // TODO: This is not actually safe. |
213 |
| - let controller = FlashController { device }; |
214 |
| - Some(FlashPartition { controller, offset, size }) |
215 |
| - } |
216 |
| - } |
217 |
| - |
218 |
| - // Note that currently, the flash partition shares the controller, so the underlying operations |
219 |
| - // are not actually safe. Need to rethink how to manage this. |
220 |
| -} |
0 commit comments