shared-bus-rtic

Provides macros and type definitions for using shared-bus in an RTIC application

Description

This crate provides a convenience wrapper for using the shared-bus crate with RTIC applications.

Note that all of the drivers that use the same underlying bus must be stored within a single resource (e.g. as one larger struct) within the RTIC resources. This ensures that RTIC will prevent one driver from interrupting another while they are using the same underlying bus.

This crate also provides convenience types for working with shared-bus RTIC resources.

Usage Example

```rust

use sharedbusrtic::BusProxy;

struct SharedBusResources { device: Device>, other_device: OtherDevice>, }

// ...

// Replace this type with the type of your bus (e.g. hal::i2c::I2c<...>). type BusType = ();

struct Resources { sharedbusresources: SharedBusResources, }

[init] fn init(c: init::Context) -> init::LateResources {

let manager = shared_bus_rtic::new!(bus, BusType);
let device = Device::new(manager.acquire());
let other_device = OtherDevice::new(manager.acquire());

init::LateResources {
    shared_bus_resources: SharedBusResources { device, other_device },
}

} ```

Valid Example

```rust struct SharedBusResources { deviceonsharedbus: Device, otherdeviceonshared_bus: OtherDevice, }

// ...

struct Resources { sharedbusresources: SharedBusResources, }

[task(resources=[sharedbusresources], priority=5)

pub fn highprioritytask(c: highprioritytask::Context) { // Good - This task cannot interrupt the lower priority task that is using the bus because of a // resource lock. c.resources.sharedbusresources.deviceonshared_bus.read(); }

[task(resources=[sharedbusresources], priority=0)

pub fn lowprioritytask(c: lowprioritytask::Context) { // Good - RTIC properly locks the entire shared bus from concurrent access. c.resources.sharedbusresources.lock(|bus| bus.otherdeviceonsharedbus.read()); } ```

In the above example, it can be seen that both devices on the bus are stored as a single resource (in a shared struct). Because of this, RTIC properly locks the resource when either the high or low priority task is using the bus.

BAD EXAMPLE

```rust struct Resources { // INVALID - DO NOT DO THIS. deviceonsharedbus: Device, otherdeviceonshared_bus: OtherDevice, }

[task(resources=[deviceonshared_bus], priority=5)

pub fn highprioritytask(c: highprioritytask::Context) { // ERROR: This task might interrupt the read on the other device!!! c.resources.deviceonshared_bus.read(); }

[task(resources=[otherdeviceonsharedbus], priority=0)

pub fn lowprioritytask(c: lowprioritytask::Context) { // Attempt to read data from the device. c.resources.otherdeviceonsharedbus.read(); } ```

In the above incorrect example, RTIC may interrupt the low priority task to complete the high priority task. However, the low priority task may be using the shared bus. In this case, the communication may be corrupted by multiple devices using the bus at the same time.

Details

In order to use shared-bus with RTIC, the underlying BusManager object that shared-bus creates has to be stored with a 'static lifetime (to ensure that references it gives out are always valid). This crate provides a macro to declare a global static to store the BusManager into.