MCPcopy Index your code
hub / github.com/Rahix/shared-bus

github.com/Rahix/shared-bus @v0.3.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.3.1 ↗ · + Follow
39 symbols 123 edges 8 files 5 documented · 13%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

shared-bus crates.io page docs.rs Continuous Integration

shared-bus is a crate to allow sharing bus peripherals safely between multiple devices.

In the embedded-hal ecosystem, it is convention for drivers to "own" the bus peripheral they are operating on. This implies that only one driver can have access to a certain bus. That, of course, poses an issue when multiple devices are connected to a single bus.

shared-bus solves this by giving each driver a bus-proxy to own which internally manages access to the actual bus in a safe manner. For a more in-depth introduction of the problem this crate is trying to solve, take a look at the blog post.

There are different 'bus managers' for different use-cases:

Sharing within a single task/thread

As long as all users of a bus are contained in a single task/thread, bus sharing is very simple. With no concurrency possible, no special synchronization is needed. This is where a [BusManagerSimple] should be used:

// For example:
let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 90.khz(), clocks, &mut rcc.apb1);

let bus = shared_bus::BusManagerSimple::new(i2c);

let mut proxy1 = bus.acquire_i2c();
let mut my_device = MyDevice::new(bus.acquire_i2c());

proxy1.write(0x39, &[0xc0, 0xff, 0xee]);
my_device.do_something_on_the_bus();

The BusManager::acquire_*() methods can be called as often as needed; each call will yield a new bus-proxy of the requested type.

Sharing across multiple tasks/threads

For sharing across multiple tasks/threads, synchronization is needed to ensure all bus-accesses are strictly serialized and can't race against each other. The synchronization is handled by a platform-specific [BusMutex] implementation. shared-bus already contains some implementations for common targets. For each one, there is also a macro for easily creating a bus-manager with 'static lifetime, which is almost always a requirement when sharing across task/thread boundaries. As an example:

// For example:
let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 90.khz(), clocks, &mut rcc.apb1);

// The bus is a 'static reference -> it lives forever and references can be
// shared with other threads.
let bus: &'static _ = shared_bus::new_std!(SomeI2cBus = i2c).unwrap();

let mut proxy1 = bus.acquire_i2c();
let mut my_device = MyDevice::new(bus.acquire_i2c());

// We can easily move a proxy to another thread:
# let t =
std::thread::spawn(move || {
    my_device.do_something_on_the_bus();
});
# t.join().unwrap();

Those platform-specific bits are guarded by a feature that needs to be enabled. Here is an overview of what's already available:

Mutex Bus Manager 'static Bus Macro Feature Name
std::sync::Mutex [BusManagerStd] [new_std!()] std
cortex_m::interrupt::Mutex [BusManagerCortexM] [new_cortexm!()] cortex-m
shared_bus::XtensaMutex (spin::Mutex in critical section) [BusManagerXtensa]  [new_xtensa!()] xtensa
NA [BusManagerAtomicCheck] [new_atomic_check!()] cortex-m

Supported Busses

Currently, the following busses can be shared with shared-bus:

Bus Proxy Type Acquire Method Comments
I2C [I2cProxy] [.acquire_i2c()]
SPI [SpiProxy] [.acquire_spi()] SPI can only be shared within a single task (See [SpiProxy] for details).
ADC [AdcProxy] [.acquire_adc()]

License

shared-bus is licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Extension points exported contracts — how you extend this code

BusMutex (Interface)
Common interface for mutex implementations. `shared-bus` needs a mutex to ensure only a single device can access the bu [5 …
src/mutex.rs

Core symbols most depended-on inside this repo

lock
called by 15
src/mutex.rs
write
called by 10
src/proxies.rs
clone
called by 8
src/proxies.rs
acquire_i2c
called by 8
src/manager.rs
acquire_adc
called by 8
src/manager.rs
acquire_spi
called by 4
src/manager.rs
read
called by 3
src/proxies.rs
write_read
called by 2
src/proxies.rs

Shape

Function 16
Method 15
Class 7
Interface 1

Languages

Rust100%

Modules by API surface

src/proxies.rs12 symbols
src/mutex.rs7 symbols
tests/i2c.rs6 symbols
tests/adc.rs5 symbols
src/manager.rs5 symbols
tests/spi.rs4 symbols

For agents

$ claude mcp add shared-bus \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact