|
23 | 23 | //! }
|
24 | 24 | //! ```
|
25 | 25 |
|
26 |
| -use core::cell::UnsafeCell; |
27 |
| -use core::future::poll_fn; |
28 |
| -use core::ops::{Deref, DerefMut}; |
29 |
| -use core::pin::Pin; |
30 |
| -use core::task::{Poll, Waker}; |
| 26 | +use core::{ |
| 27 | + cell::UnsafeCell, |
| 28 | + future::poll_fn, |
| 29 | + ops::{Deref, DerefMut}, |
| 30 | + pin::Pin, |
| 31 | + task::{Poll, Waker}, |
| 32 | +}; |
31 | 33 | use portable_atomic::{fence, AtomicBool, Ordering};
|
| 34 | +use rtic_common::{ |
| 35 | + dropper::OnDrop, |
| 36 | + wait_queue::{Link, WaitQueue}, |
| 37 | +}; |
32 | 38 |
|
33 |
| -use rtic_common::dropper::OnDrop; |
34 |
| -use rtic_common::wait_queue::{Link, WaitQueue}; |
| 39 | +pub mod i2c; |
| 40 | +pub mod spi; |
35 | 41 |
|
36 | 42 | /// This is needed to make the async closure in `send` accept that we "share"
|
37 | 43 | /// the link possible between threads.
|
@@ -191,196 +197,6 @@ impl<'a, T> DerefMut for ExclusiveAccess<'a, T> {
|
191 | 197 | }
|
192 | 198 | }
|
193 | 199 |
|
194 |
| -/// SPI bus sharing using [`Arbiter`] |
195 |
| -pub mod spi { |
196 |
| - use super::Arbiter; |
197 |
| - use embedded_hal::digital::OutputPin; |
198 |
| - use embedded_hal_async::{ |
199 |
| - delay::DelayNs, |
200 |
| - spi::{ErrorType, Operation, SpiBus, SpiDevice}, |
201 |
| - }; |
202 |
| - use embedded_hal_bus::spi::DeviceError; |
203 |
| - |
204 |
| - /// [`Arbiter`]-based shared bus implementation. |
205 |
| - pub struct ArbiterDevice<'a, BUS, CS, D> { |
206 |
| - bus: &'a Arbiter<BUS>, |
207 |
| - cs: CS, |
208 |
| - delay: D, |
209 |
| - } |
210 |
| - |
211 |
| - impl<'a, BUS, CS, D> ArbiterDevice<'a, BUS, CS, D> { |
212 |
| - /// Create a new [`ArbiterDevice`]. |
213 |
| - pub fn new(bus: &'a Arbiter<BUS>, cs: CS, delay: D) -> Self { |
214 |
| - Self { bus, cs, delay } |
215 |
| - } |
216 |
| - } |
217 |
| - |
218 |
| - impl<'a, BUS, CS, D> ErrorType for ArbiterDevice<'a, BUS, CS, D> |
219 |
| - where |
220 |
| - BUS: ErrorType, |
221 |
| - CS: OutputPin, |
222 |
| - { |
223 |
| - type Error = DeviceError<BUS::Error, CS::Error>; |
224 |
| - } |
225 |
| - |
226 |
| - impl<'a, Word, BUS, CS, D> SpiDevice<Word> for ArbiterDevice<'a, BUS, CS, D> |
227 |
| - where |
228 |
| - Word: Copy + 'static, |
229 |
| - BUS: SpiBus<Word>, |
230 |
| - CS: OutputPin, |
231 |
| - D: DelayNs, |
232 |
| - { |
233 |
| - async fn transaction( |
234 |
| - &mut self, |
235 |
| - operations: &mut [Operation<'_, Word>], |
236 |
| - ) -> Result<(), DeviceError<BUS::Error, CS::Error>> { |
237 |
| - let mut bus = self.bus.access().await; |
238 |
| - |
239 |
| - self.cs.set_low().map_err(DeviceError::Cs)?; |
240 |
| - |
241 |
| - let op_res = 'ops: { |
242 |
| - for op in operations { |
243 |
| - let res = match op { |
244 |
| - Operation::Read(buf) => bus.read(buf).await, |
245 |
| - Operation::Write(buf) => bus.write(buf).await, |
246 |
| - Operation::Transfer(read, write) => bus.transfer(read, write).await, |
247 |
| - Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await, |
248 |
| - Operation::DelayNs(ns) => match bus.flush().await { |
249 |
| - Err(e) => Err(e), |
250 |
| - Ok(()) => { |
251 |
| - self.delay.delay_ns(*ns).await; |
252 |
| - Ok(()) |
253 |
| - } |
254 |
| - }, |
255 |
| - }; |
256 |
| - if let Err(e) = res { |
257 |
| - break 'ops Err(e); |
258 |
| - } |
259 |
| - } |
260 |
| - Ok(()) |
261 |
| - }; |
262 |
| - |
263 |
| - // On failure, it's important to still flush and deassert CS. |
264 |
| - let flush_res = bus.flush().await; |
265 |
| - let cs_res = self.cs.set_high(); |
266 |
| - |
267 |
| - op_res.map_err(DeviceError::Spi)?; |
268 |
| - flush_res.map_err(DeviceError::Spi)?; |
269 |
| - cs_res.map_err(DeviceError::Cs)?; |
270 |
| - |
271 |
| - Ok(()) |
272 |
| - } |
273 |
| - } |
274 |
| -} |
275 |
| - |
276 |
| -/// I2C bus sharing using [`Arbiter`] |
277 |
| -/// |
278 |
| -/// An Example how to use it in RTIC application: |
279 |
| -/// ```text |
280 |
| -/// #[app(device = some_hal, peripherals = true, dispatchers = [TIM16])] |
281 |
| -/// mod app { |
282 |
| -/// use core::mem::MaybeUninit; |
283 |
| -/// use rtic_sync::{arbiter::{i2c::ArbiterDevice, Arbiter}, |
284 |
| -/// |
285 |
| -/// #[shared] |
286 |
| -/// struct Shared {} |
287 |
| -/// |
288 |
| -/// #[local] |
289 |
| -/// struct Local { |
290 |
| -/// ens160: Ens160<ArbiterDevice<'static, I2c<'static, I2C1>>>, |
291 |
| -/// } |
292 |
| -/// |
293 |
| -/// #[init(local = [ |
294 |
| -/// i2c_arbiter: MaybeUninit<Arbiter<I2c<'static, I2C1>>> = MaybeUninit::uninit(), |
295 |
| -/// ])] |
296 |
| -/// fn init(cx: init::Context) -> (Shared, Local) { |
297 |
| -/// let i2c = I2c::new(cx.device.I2C1); |
298 |
| -/// let i2c_arbiter = cx.local.i2c_arbiter.write(Arbiter::new(i2c)); |
299 |
| -/// let ens160 = Ens160::new(ArbiterDevice::new(i2c_arbiter), 0x52); |
300 |
| -/// |
301 |
| -/// i2c_sensors::spawn(i2c_arbiter).ok(); |
302 |
| -/// |
303 |
| -/// (Shared {}, Local { ens160 }) |
304 |
| -/// } |
305 |
| -/// |
306 |
| -/// #[task(local = [ens160])] |
307 |
| -/// async fn i2c_sensors(cx: i2c_sensors::Context, i2c: &'static Arbiter<I2c<'static, I2C1>>) { |
308 |
| -/// use sensor::Asensor; |
309 |
| -/// |
310 |
| -/// loop { |
311 |
| -/// // Use scope to make sure I2C access is dropped. |
312 |
| -/// { |
313 |
| -/// // Read from sensor driver that wants to use I2C directly. |
314 |
| -/// let mut i2c = i2c.access().await; |
315 |
| -/// let status = Asensor::status(&mut i2c).await; |
316 |
| -/// } |
317 |
| -/// |
318 |
| -/// // Read ENS160 sensor. |
319 |
| -/// let eco2 = cx.local.ens160.eco2().await; |
320 |
| -/// } |
321 |
| -/// } |
322 |
| -/// } |
323 |
| -/// ``` |
324 |
| -pub mod i2c { |
325 |
| - use super::Arbiter; |
326 |
| - use embedded_hal::i2c::{AddressMode, ErrorType, Operation}; |
327 |
| - use embedded_hal_async::i2c::I2c; |
328 |
| - |
329 |
| - /// [`Arbiter`]-based shared bus implementation for I2C. |
330 |
| - pub struct ArbiterDevice<'a, BUS> { |
331 |
| - bus: &'a Arbiter<BUS>, |
332 |
| - } |
333 |
| - |
334 |
| - impl<'a, BUS> ArbiterDevice<'a, BUS> { |
335 |
| - /// Create a new [`ArbiterDevice`] for I2C. |
336 |
| - pub fn new(bus: &'a Arbiter<BUS>) -> Self { |
337 |
| - Self { bus } |
338 |
| - } |
339 |
| - } |
340 |
| - |
341 |
| - impl<'a, BUS> ErrorType for ArbiterDevice<'a, BUS> |
342 |
| - where |
343 |
| - BUS: ErrorType, |
344 |
| - { |
345 |
| - type Error = BUS::Error; |
346 |
| - } |
347 |
| - |
348 |
| - impl<'a, BUS, A> I2c<A> for ArbiterDevice<'a, BUS> |
349 |
| - where |
350 |
| - BUS: I2c<A>, |
351 |
| - A: AddressMode, |
352 |
| - { |
353 |
| - async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { |
354 |
| - let mut bus = self.bus.access().await; |
355 |
| - bus.read(address, read).await |
356 |
| - } |
357 |
| - |
358 |
| - async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { |
359 |
| - let mut bus = self.bus.access().await; |
360 |
| - bus.write(address, write).await |
361 |
| - } |
362 |
| - |
363 |
| - async fn write_read( |
364 |
| - &mut self, |
365 |
| - address: A, |
366 |
| - write: &[u8], |
367 |
| - read: &mut [u8], |
368 |
| - ) -> Result<(), Self::Error> { |
369 |
| - let mut bus = self.bus.access().await; |
370 |
| - bus.write_read(address, write, read).await |
371 |
| - } |
372 |
| - |
373 |
| - async fn transaction( |
374 |
| - &mut self, |
375 |
| - address: A, |
376 |
| - operations: &mut [Operation<'_>], |
377 |
| - ) -> Result<(), Self::Error> { |
378 |
| - let mut bus = self.bus.access().await; |
379 |
| - bus.transaction(address, operations).await |
380 |
| - } |
381 |
| - } |
382 |
| -} |
383 |
| - |
384 | 200 | #[cfg(test)]
|
385 | 201 | mod tests {
|
386 | 202 | use super::*;
|
|
0 commit comments