embedded-hal
embedded-hal copied to clipboard
How do I share an I2c bus between tasks?
I'm trying to setup an embedded project with the async/await approach (using a simple executor, no big framework like Embassy). I have two modules which need to asynchronously manage two i2c devices on the same bus, so they need ownership of an I2c instance.
When I try to create two RefCellDevices and move them to the respective modules I incur in the following compilation error:
// 12c0 is the original I2c bus
let i2c_bus = RefCell::new(i2c0);
// First RefCellDevice, to be owned by the main thread
let mut rtc = Rx8010sj::new(embedded_hal_bus::i2c::RefCellDevice::new(&i2c_bus));
log::info!("RTC stopped: {}", rtc.is_stopped().unwrap());
rtc.set_stopped(false).unwrap();
// Second RefCellDevice, to be sent to a different task
let (mut leds, task) = leds::Driver::start(
embedded_hal_bus::i2c::RefCellDevice::new(&i2c_bus),
);
spawner.spawn_local(task).unwrap();
local_executor.run();
error[E0597]: `i2c_bus` does not live long enough
--> src/lib.rs:68:51
|
49 | let i2c_bus = RefCell::new(i2c0);
| ------- binding `i2c_bus` declared here
...
68 | embedded_hal_bus::i2c::RefCellDevice::new(&i2c_bus),
| ------------------------------------------^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `i2c_bus` is borrowed for `'static`
...
89 | }
| - `i2c_bus` dropped here while still borrowed
I think understand the problem: i2c_bus is owned by the main function and the compiler thinks it will be dropped at the end even if the main function never returns. Thus I cannot send the i2c_bus reference to the leds task because it doesn't live long enough.
I can create a (late initialized) static instance for i2c_bus and it works but obviously it uses unsafe code.
Alternatively I can Box the RefCellDevice and immediately leak it, but again it doesn't seem a perfect solution.
What is the preferred way to fix this?
you can use shared-bus however the support for embedded-hal 1.0 is not complete, but for 0.2 it worked perfectly for me (stm32f4 and freeRTOS-rust)