Skip to content

Commit 88747ca

Browse files
committed
Add blocking version of rtic_sync::arbiter::{i2c,spi}::ArbiterDevice
1 parent 861a63d commit 88747ca

File tree

2 files changed

+153
-6
lines changed

2 files changed

+153
-6
lines changed

rtic-sync/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ For each category, _Added_, _Changed_, _Fixed_ add new entries at the top!
1414

1515
### Added
1616

17+
- Add `arbiter::{i2c, spi}::BlockingArbiterDevice` that helps during initialization of RTIC apps. After initialization is complete, convert an `BlockingArbiterDevice` into an `ArbiterDevice` using `BlockingArbiterDevice::into_non_blocking()`
1718
- `defmt v0.3` derives added and forwarded to `embedded-hal(-x)` crates.
1819
- signal structure
1920

rtic-sync/src/arbiter.rs

Lines changed: 152 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,10 @@ impl<'a, T> DerefMut for ExclusiveAccess<'a, T> {
195195
pub mod spi {
196196
use super::Arbiter;
197197
use embedded_hal::digital::OutputPin;
198+
use embedded_hal::spi::SpiBus as BlockingSpiBus;
198199
use embedded_hal_async::{
199200
delay::DelayNs,
200-
spi::{ErrorType, Operation, SpiBus, SpiDevice},
201+
spi::{ErrorType, Operation, SpiBus as AsyncSpiBus, SpiDevice},
201202
};
202203
use embedded_hal_bus::spi::DeviceError;
203204

@@ -226,7 +227,7 @@ pub mod spi {
226227
impl<'a, Word, BUS, CS, D> SpiDevice<Word> for ArbiterDevice<'a, BUS, CS, D>
227228
where
228229
Word: Copy + 'static,
229-
BUS: SpiBus<Word>,
230+
BUS: AsyncSpiBus<Word>,
230231
CS: OutputPin,
231232
D: DelayNs,
232233
{
@@ -271,6 +272,89 @@ pub mod spi {
271272
Ok(())
272273
}
273274
}
275+
276+
/// [`Arbiter`]-based shared bus implementation.
277+
pub struct BlockingArbiterDevice<'a, BUS, CS, D> {
278+
bus: &'a Arbiter<BUS>,
279+
cs: CS,
280+
delay: D,
281+
}
282+
283+
impl<'a, BUS, CS, D> BlockingArbiterDevice<'a, BUS, CS, D> {
284+
/// Create a new [`BlockingArbiterDevice`].
285+
pub fn new(bus: &'a Arbiter<BUS>, cs: CS, delay: D) -> Self {
286+
Self { bus, cs, delay }
287+
}
288+
289+
/// Create an `ArbiterDevice` from an `BlockingArbiterDevice`.
290+
pub fn into_non_blocking(self) -> ArbiterDevice<'a, BUS, CS, D>
291+
where
292+
BUS: AsyncSpiBus,
293+
{
294+
ArbiterDevice {
295+
bus: self.bus,
296+
cs: self.cs,
297+
delay: self.delay,
298+
}
299+
}
300+
}
301+
302+
impl<'a, BUS, CS, D> ErrorType for BlockingArbiterDevice<'a, BUS, CS, D>
303+
where
304+
BUS: ErrorType,
305+
CS: OutputPin,
306+
{
307+
type Error = DeviceError<BUS::Error, CS::Error>;
308+
}
309+
310+
impl<'a, Word, BUS, CS, D> SpiDevice<Word> for BlockingArbiterDevice<'a, BUS, CS, D>
311+
where
312+
Word: Copy + 'static,
313+
BUS: BlockingSpiBus<Word>,
314+
CS: OutputPin,
315+
D: DelayNs,
316+
{
317+
async fn transaction(
318+
&mut self,
319+
operations: &mut [Operation<'_, Word>],
320+
) -> Result<(), DeviceError<BUS::Error, CS::Error>> {
321+
let mut bus = self.bus.access().await;
322+
323+
self.cs.set_low().map_err(DeviceError::Cs)?;
324+
325+
let op_res = 'ops: {
326+
for op in operations {
327+
let res = match op {
328+
Operation::Read(buf) => bus.read(buf),
329+
Operation::Write(buf) => bus.write(buf),
330+
Operation::Transfer(read, write) => bus.transfer(read, write),
331+
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf),
332+
Operation::DelayNs(ns) => match bus.flush() {
333+
Err(e) => Err(e),
334+
Ok(()) => {
335+
self.delay.delay_ns(*ns).await;
336+
Ok(())
337+
}
338+
},
339+
};
340+
if let Err(e) = res {
341+
break 'ops Err(e);
342+
}
343+
}
344+
Ok(())
345+
};
346+
347+
// On failure, it's important to still flush and deassert CS.
348+
let flush_res = bus.flush();
349+
let cs_res = self.cs.set_high();
350+
351+
op_res.map_err(DeviceError::Spi)?;
352+
flush_res.map_err(DeviceError::Spi)?;
353+
cs_res.map_err(DeviceError::Cs)?;
354+
355+
Ok(())
356+
}
357+
}
274358
}
275359

276360
/// I2C bus sharing using [`Arbiter`]
@@ -323,8 +407,8 @@ pub mod spi {
323407
/// ```
324408
pub mod i2c {
325409
use super::Arbiter;
326-
use embedded_hal::i2c::{AddressMode, ErrorType, Operation};
327-
use embedded_hal_async::i2c::I2c;
410+
use embedded_hal::i2c::{AddressMode, ErrorType, I2c as BlockingI2c, Operation};
411+
use embedded_hal_async::i2c::I2c as AsyncI2c;
328412

329413
/// [`Arbiter`]-based shared bus implementation for I2C.
330414
pub struct ArbiterDevice<'a, BUS> {
@@ -345,9 +429,9 @@ pub mod i2c {
345429
type Error = BUS::Error;
346430
}
347431

348-
impl<'a, BUS, A> I2c<A> for ArbiterDevice<'a, BUS>
432+
impl<'a, BUS, A> AsyncI2c<A> for ArbiterDevice<'a, BUS>
349433
where
350-
BUS: I2c<A>,
434+
BUS: AsyncI2c<A>,
351435
A: AddressMode,
352436
{
353437
async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
@@ -379,6 +463,68 @@ pub mod i2c {
379463
bus.transaction(address, operations).await
380464
}
381465
}
466+
467+
/// [`Arbiter`]-based shared bus implementation for I2C.
468+
pub struct BlockingArbiterDevice<'a, BUS> {
469+
bus: &'a Arbiter<BUS>,
470+
}
471+
472+
impl<'a, BUS> BlockingArbiterDevice<'a, BUS> {
473+
/// Create a new [`BlockingArbiterDevice`] for I2C.
474+
pub fn new(bus: &'a Arbiter<BUS>) -> Self {
475+
Self { bus }
476+
}
477+
478+
/// Create an `ArbiterDevice` from an `BlockingArbiterDevice`.
479+
pub fn into_non_blocking(self) -> ArbiterDevice<'a, BUS>
480+
where
481+
BUS: AsyncI2c,
482+
{
483+
ArbiterDevice { bus: self.bus }
484+
}
485+
}
486+
487+
impl<'a, BUS> ErrorType for BlockingArbiterDevice<'a, BUS>
488+
where
489+
BUS: ErrorType,
490+
{
491+
type Error = BUS::Error;
492+
}
493+
494+
impl<'a, BUS, A> AsyncI2c<A> for BlockingArbiterDevice<'a, BUS>
495+
where
496+
BUS: BlockingI2c<A>,
497+
A: AddressMode,
498+
{
499+
async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
500+
let mut bus = self.bus.access().await;
501+
bus.read(address, read)
502+
}
503+
504+
async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
505+
let mut bus = self.bus.access().await;
506+
bus.write(address, write)
507+
}
508+
509+
async fn write_read(
510+
&mut self,
511+
address: A,
512+
write: &[u8],
513+
read: &mut [u8],
514+
) -> Result<(), Self::Error> {
515+
let mut bus = self.bus.access().await;
516+
bus.write_read(address, write, read)
517+
}
518+
519+
async fn transaction(
520+
&mut self,
521+
address: A,
522+
operations: &mut [Operation<'_>],
523+
) -> Result<(), Self::Error> {
524+
let mut bus = self.bus.access().await;
525+
bus.transaction(address, operations)
526+
}
527+
}
382528
}
383529

384530
#[cfg(test)]

0 commit comments

Comments
 (0)