Skip to content

Commit 9c60961

Browse files
adri326Dirbaio
authored andcommitted
Add Rc<RefCell<T>>-based implementation of shared I2c buses
1 parent aaa29c0 commit 9c60961

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

embedded-hal-bus/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ async = ["dep:embedded-hal-async"]
2020
defmt-03 = ["dep:defmt-03", "embedded-hal/defmt-03", "embedded-hal-async?/defmt-03"]
2121
# Enables additional utilities requiring a global allocator.
2222
alloc = []
23+
# TODO: remove this
24+
default = ["alloc"]
2325

2426
[dependencies]
2527
embedded-hal = { version = "1.0.0", path = "../embedded-hal" }

embedded-hal-bus/src/i2c/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ mod critical_section;
1010
pub use self::critical_section::*;
1111
mod atomic;
1212
pub use atomic::*;
13+
14+
#[cfg(feature = "alloc")]
15+
mod rc;
16+
#[cfg(feature = "alloc")]
17+
pub use rc::*;

embedded-hal-bus/src/i2c/rc.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
extern crate alloc;
2+
use alloc::rc::Rc;
3+
4+
use core::cell::RefCell;
5+
use embedded_hal::i2c::{ErrorType, I2c};
6+
7+
/// `Rc<RefCell<T>>`-based shared bus [`I2c`] implementation.
8+
/// This is the reference-counting equivalent of [`RefCellDevice`](super::RefCellDevice).
9+
///
10+
/// Sharing is implemented with a [`RefCell`] and ownership is managed by [`Rc`].
11+
/// Like [`RefCellDevice`](super::RefCellDevice), `RcDevice` instances are not [`Send`],
12+
/// so they can only be shared within a single thread (interrupt priority level).
13+
///
14+
/// When this `RcDevice` is dropped, the reference count of the I2C bus will be decremented.
15+
/// Once that reference count hits zero, it will be cleaned up.
16+
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
17+
pub struct RcDevice<Bus> {
18+
bus: Rc<RefCell<Bus>>,
19+
}
20+
21+
impl<Bus> RcDevice<Bus> {
22+
/// Creates a new `RcDevice`.
23+
///
24+
/// This function does not increment the reference count for the bus:
25+
/// you will need to call `Rc::clone(&bus)` if you only have a `&Rc<RefCell<Bus>>`.
26+
#[inline]
27+
pub fn new(bus: Rc<RefCell<Bus>>) -> Self {
28+
Self { bus }
29+
}
30+
}
31+
32+
impl<Bus> ErrorType for RcDevice<Bus>
33+
where
34+
Bus: ErrorType,
35+
{
36+
type Error = Bus::Error;
37+
}
38+
39+
impl<Bus> I2c for RcDevice<Bus>
40+
where
41+
Bus: I2c,
42+
{
43+
#[inline]
44+
fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
45+
let bus = &mut *self.bus.borrow_mut();
46+
bus.read(address, read)
47+
}
48+
49+
#[inline]
50+
fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
51+
let bus = &mut *self.bus.borrow_mut();
52+
bus.write(address, write)
53+
}
54+
55+
#[inline]
56+
fn write_read(
57+
&mut self,
58+
address: u8,
59+
write: &[u8],
60+
read: &mut [u8],
61+
) -> Result<(), Self::Error> {
62+
let bus = &mut *self.bus.borrow_mut();
63+
bus.write_read(address, write, read)
64+
}
65+
66+
#[inline]
67+
fn transaction(
68+
&mut self,
69+
address: u8,
70+
operations: &mut [embedded_hal::i2c::Operation<'_>],
71+
) -> Result<(), Self::Error> {
72+
let bus = &mut *self.bus.borrow_mut();
73+
bus.transaction(address, operations)
74+
}
75+
}

0 commit comments

Comments
 (0)