broken usage example for i2c sharing
pdgilbert opened this issue · comments
I have been trying to compile the Arbiter
i2c
usage example in rtic-rs/rtic/rtic-sync/src/arbiter.rs
. It has some typos which suggest it has never been tested. With some fixes and adjustments for different hals I have made progress but have a problem with an unsatisfied trait bounds for &mut Ens160<ArbiterDevice<'static, I2c<I2C1>>>
. I have tried with both release and git versions of rtic-sync
and also tried with both stm32f4xx_hal
and a version of stm32g4xx_hal
that uses embedded-hal-1.0.0
. I think the problem is possibly a bug in rtic-sync
or elsewhere, but maybe that I am just not bringing the proper trait into scope. Below are results for the git versions using stm32f4xx_hal
.
Click to expand code
// I2C bus sharing using [`Arbiter`]
//
// An Example how to use it in RTIC application:
#![deny(unsafe_code)]
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#[cfg(debug_assertions)]
use panic_semihosting as _;
#[cfg(not(debug_assertions))]
use panic_halt as _;
use rtic::app;
#[cfg_attr(feature = "stm32f4xx", app(device = stm32f4xx_hal::pac, dispatchers = [TIM2, TIM3]))]
mod app {
use core::mem::MaybeUninit;
use rtic_sync::arbiter::{i2c::ArbiterDevice, Arbiter};
// Instantiate an Arbiter with a static lifetime.
static ARBITER: Arbiter<u32> = Arbiter::new(32);
use ens160::{Ens160, AirQualityIndex, ECo2};
pub use stm32f4xx_hal::{
pac::{I2C1, TIM2, TIM5},
i2c::I2c,
gpio::GpioExt,
rcc::{Clocks, RccExt},
timer::TimerExt,
prelude::*,
};
pub type I2c1Type = I2c<I2C1>;
#[shared]
struct Shared {}
#[local]
struct Local {
ens160: Ens160<ArbiterDevice<'static, I2c1Type>>,
}
#[init(local = [
i2c_arbiter: MaybeUninit<Arbiter<I2c1Type>> = MaybeUninit::uninit(),
])]
fn init(cx: init::Context) -> (Shared, Local) {
let rcc = cx.device.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let gpiob = cx.device.GPIOB.split();
let scl = gpiob.pb8.into_alternate_open_drain();
let sda = gpiob.pb9.into_alternate_open_drain();
let i2c = I2c::new(cx.device.I2C1, (scl, sda), 400.kHz(), &clocks);
let i2c_arbiter = cx.local.i2c_arbiter.write(Arbiter::new(i2c));
let ens160 = Ens160::new(ArbiterDevice::new(i2c_arbiter), 0x52);
i2c_sensors::spawn(i2c_arbiter).ok();
(Shared {}, Local { ens160 })
}
#[task(local = [ens160])]
async fn i2c_sensors(cx: i2c_sensors::Context, i2c: &'static Arbiter<I2c1Type>) {
//async fn i2c_sensors(cx: i2c_sensors::Context, i2c: &'static Arbiter<I2c<'static, I2c1Type>>) {
loop {
// Read ENS160 sensor.
let eco2 = cx.local.ens160.eco2().await;
}
}
}
Click to expand compiling error
$ cargo build --no-default-features --target thumbv7em-none-eabihf --features stm32f411,stm32f4xx --example ens160_f4
Compiling rust-integration-testing-of-examples v0.3.0 (dev-testing)
warning: unused imports: `AirQualityIndex`, `ECo2`
--> examples/ens160_f4.rs:27:26
|
27 | use ens160::{Ens160, AirQualityIndex, ECo2};
| ^^^^^^^^^^^^^^^ ^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0599]: the method `eco2` exists for mutable reference `&mut Ens160<ArbiterDevice<'static, I2c<I2C1>>>`, but its trait bounds were not satisfied
--> examples/ens160_f4.rs:75:40
|
75 | let eco2 = cx.local.ens160.eco2().await;
| ^^^^ method cannot be called on `&mut Ens160<ArbiterDevice<'static, I2c<I2C1>>>` due to unsatisfied trait bounds
|
::: /home/paul/.cargo/git/checkouts/rtic-98d87eafbe677b11/22ac33a/rtic-sync/src/arbiter.rs:330:5
|
330 | pub struct ArbiterDevice<'a, BUS> {
| --------------------------------- doesn't satisfy `_: I2c`
|
= note: the full type name has been written to 'dev-testing/target/thumbv7em-none-eabihf/debug/examples/ens160_f4-64d1daf9f661405a.long-type-16809872599107602039.txt'
= note: the following trait bounds were not satisfied:
`rtic_sync::arbiter::i2c::ArbiterDevice<'static, stm32f4xx_hal::i2c::I2c<I2C1>>: stm32f4xx_hal::embedded_hal::i2c::I2c`
For more information about this error, try `rustc --explain E0599`.
warning: `rust-integration-testing-of-examples` (example "ens160_f4") generated 1 warning
error: could not compile `rust-integration-testing-of-examples` (example "ens160_f4") due to 1 previous error; 1 warning emitted
Is this a bug or am I missing something simple?
(This issue is somewhat related to #886 where @perlindgren and @korken89 suggested this example.)
Hi,
The error you are getting is because the trait I2c
is the async trait.
You seem to be providing a sync implementation. Hope that helps!
Thanks @korken89. I'm new to many pieces of this, so pretty confused. I think you are suggesting I should
use embedded_hal_async::i2c::I2c;
rather than
use stm32f4xx_hal::i2c::I2c;
If so, that gets me back to all the errors that had me looking for a working example of arbiter
with embedded-hal 1.0
and rtic
. Is the example in rtic-sync
(https://github.com/rtic-rs/rtic/blob/master/rtic-sync/src/arbiter.rs#L276) supposed to use an async I2c
trait?
A pointer to a working stm32*-hal
arbiter
example would be helpful, for me and in documentation. Actually, any working example of embedded-hal 1.0
, rtic v2
,stm32*-hal
with shared I2C
bus would help me. (I have lots of rtic
shared I2C
bus examples that do not work after shifting to embedded-hal 1.0
.)
@pdgilbert have you managed to make Arbiter
work and have shared access to I2C? If so, could you please open a PR with an example?
No I have not got Arbiter
compiling. I finally had to put it aside to do other work, and was hoping someone else would get a working usage example. Shared access to an I2C bus in rtic
is the main broken piece in my crate/hal testing with eh-1
(https://github.com/pdgilbert/rust-integration-testing/actions/) . In testing with stm32g4xx_hal
I have 68 examples compiling of the 72 I had compiling prior to switching to eh-1
. The 5 failing are because of this problem. In testing with stm32f4xx_hal
I have 61 examples compiling of the 72. The additional failures are because stm32f4xx_hal
does not yet support eh-1
Read/Write style. (Someone please correct me if I am wrong on that.) Also beware that hardware testing suggests that "compiling" is not the same as "working".