Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

embedded-hal v1.0.0 and embedded-hal-bus #205

Open
pdgilbert opened this issue Jan 13, 2024 · 4 comments
Open

embedded-hal v1.0.0 and embedded-hal-bus #205

pdgilbert opened this issue Jan 13, 2024 · 4 comments

Comments

@pdgilbert
Copy link

I am using @bugadani 's ehal1 fork of ssd1306 to make some examples work with embedded-hal-1.0.0. One of my main problems has been using ssd1306 with shared-bus. (see stm32-rs/stm32f4xx-hal#722 (comment)). @rursprung pointed out that embedded-hal-bus is a replacement for shared-bus, but so far I have not been able to get the trait formulation and other pieces correct. I am not sure if this is just my newbie understanding, or if something is needed in ssd1306. The documentaion is written for HAL and crate developers, not for naive users. (I need a working example.)

With a local fork of @bugadani 's ehal1 I have modified example/text_i2c.rs and added a few lines to Cargo.toml.

Click to expand modified examples/text_i2c.rs
//! Print "Hello world!" with "Hello rust!" underneath. Uses the `embedded_graphics` crate to draw
//! the text with a 6x10 pixel font.
//!
//! This example is for the STM32F103 "Blue Pill" board and others using I2C1.
//!
//! Wiring connections are as follows for a CRIUS-branded display:
//!
//! ```
//!      Display -> Blue Pill
//! (black)  GND -> GND
//! (red)    +5V -> VCC
//! (yellow) SDA -> PB9
//! (green)  SCL -> PB8
//! ```
//!
//! Build on a Black Pill with 
//!   cargo build --target thumbv7em-none-eabihf --features stm32f4xx-hal --example  text_i2c
//! Build on stm32h742 with 
//!   cargo build --target thumbv7em-none-eabihf --features stm32h7xx-hal --example  text_i2c


#![no_std]
#![no_main]

use cortex_m_rt::{entry, exception, ExceptionFrame};
use embedded_graphics::{
    mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder},
    pixelcolor::BinaryColor,
    prelude::*,
    text::{Baseline, Text},
};
use panic_halt as _;
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};


#[cfg(feature = "stm32f4xx-hal")]
use stm32f4xx_hal as hal;

#[cfg(feature = "stm32h7xx-hal")]
use stm32h7xx_hal as hal;

use hal::{
    i2c::I2c,
    prelude::*,
    pac::{Peripherals, I2C1},
    pac,
};


//use embedded_hal_bus::*;  
//use embedded_hal_bus::i2c;
//use embedded_hal::i2c::I2c;
//use embedded_hal_bus::i2c::I2c;
//use embedded_hal_async::i2c::I2c;
//use embedded_hal::i2c::{I2c, ErrorType as I2cErrorType, SevenBitAddress, TenBitAddress, Operation, Error as I2cError, };


#[cfg(feature = "stm32f4xx-hal")]
fn setup(dp:Peripherals) -> I2c<I2C1> {
    let rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.freeze();
    let gpiob = dp.GPIOB.split();

    let scl = gpiob.pb8.into_alternate_open_drain(); 
    let sda = gpiob.pb9.into_alternate_open_drain(); 

    let r = I2c::new(dp.I2C1, (scl, sda), 400.kHz(), &clocks);
    r
}


#[cfg(feature = "stm32h7xx-hal")]
fn setup(dp:Peripherals) -> I2c<I2C1> {
    let pwr = dp.PWR.constrain();
    let vos = pwr.freeze();
    let rcc = dp.RCC.constrain();
    let ccdr = rcc.sys_ck(160.MHz()).freeze(vos, &dp.SYSCFG);
    let clocks = ccdr.clocks;

    let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);

    let scl = gpiob.pb8.into_alternate().set_open_drain();
    let sda = gpiob.pb9.into_alternate().set_open_drain(); 

    let r = dp.I2C1.i2c((scl, sda), 400.kHz(), ccdr.peripheral.I2C1, &clocks);
    r
}

#[entry]
fn main() -> ! {
    let dp = pac::Peripherals::take().unwrap();
   
    let r = setup(dp);
    
    let interface = I2CDisplayInterface::new(r);
    //  need address and ErrorType
    //pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {

    let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
        .into_buffered_graphics_mode();
    display.init().unwrap();

    let text_style = MonoTextStyleBuilder::new()
        .font(&FONT_6X10)
        .text_color(BinaryColor::On)
        .build();

    Text::with_baseline("Hello world!", Point::zero(), text_style, Baseline::Top)
        .draw(&mut display)
        .unwrap();

    Text::with_baseline("Hello Rust!", Point::new(0, 16), text_style, Baseline::Top)
        .draw(&mut display)
        .unwrap();

    display.flush().unwrap();

    loop {}
}

#[exception]
unsafe fn HardFault(ef: &ExceptionFrame) -> ! {
    panic!("{:#?}", ef);
}

Click to expand Cargo.toml diff
29a30,34
> # Used by text_i2c examples
> embedded-hal-bus = { git = "https://github.com/rust-embedded/embedded-hal/" }
> stm32f4xx-hal = { git = "https://github.com/rursprung/stm32f4xx-hal", features = [ "rt", "stm32f401" ], optional = true, branch = "update-to-eh-1"  } 
> stm32h7xx-hal = { git = "https://github.com/stm32-rs/stm32h7xx-hal",  features = [ "rt", "stm32h742" ], optional = true, branch = "eh-v1.0"}
> 

Without trying to share the bus, the code compiles in ssd1306 with both stm32f4xx-hal and stm32h7xx-hal using

cargo build --target thumbv7em-none-eabihf --features stm32f4xx-hal --example  text_i2c
cargo build --target thumbv7em-none-eabihf --features stm32h7xx-hal --example  text_i2c

When I try to make changes for sharing the bus (see https://crates.io/crates/embedded-hal-bus and https://github.com/rust-embedded/embedded-hal/blob/master/docs/migrating-from-0.2-to-1.0.md#error-type-bounds ) I cannot get the correct formulation or the proper trait. Commented out in the code are many of the lines I think I need, but I have not had any success with a very large number of attempts. Suggestions would be appreciated.

@bugadani
Copy link
Contributor

Could you please try with embedded-hal-bus = "0.1.0" instead of trying to use the dependency from github?

@pdgilbert
Copy link
Author

Changing Cargo.toml so I have

embedded-hal-bus = "0.1.0"

and text_i2c.rs to what I think I should have:

...
use hal::{
    //i2c::I2c,
    prelude::*,
    pac::{Peripherals, I2C1},
    pac,
};

use embedded_hal_bus::i2c::I2c;
...

Then when I compile I get

...

 Downloaded embedded-hal-bus v0.1.0
  Downloaded 1 crate (11.9 KB) in 0.72s
   Compiling embedded-hal-bus v0.1.0
   Compiling ssd1306 v0.8.4 (/home/paul/githubClones/ssd1306)

error[E0432]: unresolved import `embedded_hal_bus::i2c::I2c`
  --> examples/text_i2c.rs:53:5
   |
53 | use embedded_hal_bus::i2c::I2c;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `I2c` in `i2c`
   |
help: consider importing one of these items instead
   |
53 | use crate::hal::i2c::I2c;
   |     ~~~~~~~~~~~~~~~~~~~~
53 | use embedded_hal::i2c::I2c;
   |     ~~~~~~~~~~~~~~~~~~~~~~
53 | use embedded_hal_async::i2c::I2c;
   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 | use stm32f1xx_hal::i2c::I2c;
   |     ~~~~~~~~~~~~~~~~~~~~~~~
     and 2 other candidates

For more information about this error, try `rustc --explain E0432`.
error: could not compile `ssd1306` (example "text_i2c") due to 1 previous error

I find it strange that there is "no I2c in i2c". It really looks to me like it should be there. I don't see typos or anything simple, but this does not seem right.

Also, when I look at cargo tree, it looks like display-interface-i2c depends on embedded-hal-async but not on embedded-hal-bus.

$ cargo tree
ssd1306 v0.8.4 (/home/paul/githubClones/ssd1306)
├── display-interface v0.5.0 (https://github.com/bugadani/display-interface.git?branch=eh1#e65eaf6d)
├── display-interface-i2c v0.5.0 (https://github.com/bugadani/display-interface.git?branch=eh1#e65eaf6d)
│ ├── display-interface v0.5.0 (https://github.com/bugadani/display-interface.git?branch=eh1#e65eaf6d)
│ ├── embedded-hal v1.0.0
│ └── embedded-hal-async v1.0.0
│ └── embedded-hal v1.0.0
├── display-interface-spi v0.5.0 (https://github.com/bugadani/display-interface.git?branch=eh1#e65eaf6d)
│ ├── byte-slice-cast v1.2.2
│ ├── display-interface v0.5.0 (https://github.com/bugadani/display-interface.git?branch=eh1#e65eaf6d)
│ ├── embedded-hal v1.0.0
│ └── embedded-hal-async v1.0.0 ()
├── embedded-graphics-core v0.4.0
│ ├── az v1.2.1
│ └── byteorder v1.5.0
├── embedded-hal v1.0.0
├── embedded-hal-async v1.0.0 (
)
└── embedded-hal-bus v0.1.0
├── critical-section v1.1.2
└── embedded-hal v1.0.0
[dev-dependencies]
...

@bugadani
Copy link
Contributor

embedded-hal-bus isn't a simple plug-and-play crate, you don't get an I2c struct that "just works". You need to decide on how you share your bus between your devices, and for that you have three options.

Why do you expect display-interface-i2c to depend on embedded-hal-bus? embedded-hal-bus doesn't define any new traits that would require any special handling in display-interface-i2c.

@pdgilbert
Copy link
Author

Thanks for the hint @bugadani . I guess it is more complicated than I thought. I'll eventually figure it out. Not exactly a simple replacement for shared_bus, but seems like more control over the mechanism.

My thinking on display-interface-i2c depending on embedded-hal-bus was because I mis-read the tree and thought it depended on embedded-hal-spi. I think the spi and i2c similarities are such that one dependency would suggest the other too..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants