|
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