Skip to content

I2c with Alternate<OpenDrain> #519

@pdgilbert

Description

@pdgilbert

(Using git master) I have code for setting i2c1 which works with pb6,pb7 in several device crates using embedded-hal 1.0.0. When I try to use pb8,pb9 which need Alternate<OpenDrain> I get the errors below, with code further below. I am not sure if this is a bug or if I have the wrong incantation for Alternate OpenDrain. Something seems a bit odd about the 0 in

note: required for `Pin<'B', 8, Alternate<OpenDrain>>` to implement `RInto<stm32f1xx_hal::afio::i2c1::Scl, 0>`

since I think it needs gpiob.crh.

Click to expand pb8, pb9 alternate_open_drain error messages
$ cargo build --no-default-features --target thumbv7m-none-eabi --features stm32f103,stm32f1xx  --example setup-i2c
   Compiling testing-example v0.0.1 (../test_itc_f1xx)
error[E0277]: the trait bound `stm32f1xx_hal::afio::i2c1::Scl: RFrom<stm32f1xx_hal::gpio::Pin<'B', 8, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 0>` is not satisfied
   --> examples/setup-i2c.rs:116:50
    |
116 |     let i2c1 = BlockingI2c::<I2C1>::new(dp.I2C1, (scl, sda),
    |                ------------------------          ^^^^^^^^^^ unsatisfied trait bound
    |                |
    |                required by a bound introduced by this call
    |
    = help: the trait `RFrom<stm32f1xx_hal::gpio::Pin<'B', 8, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 0>` is not implemented for `stm32f1xx_hal::afio::i2c1::Scl`
    = help: the following other types implement trait `RFrom<T, R>`:
              `stm32f1xx_hal::afio::i2c1::Scl` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 6, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 0>`
              `stm32f1xx_hal::afio::i2c1::Scl` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 6>, 0>`
              `stm32f1xx_hal::afio::i2c1::Scl` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 8, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 1>`
              `stm32f1xx_hal::afio::i2c1::Scl` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 8>, 1>`
    = note: required for `Pin<'B', 8, Alternate<OpenDrain>>` to implement `RInto<stm32f1xx_hal::afio::i2c1::Scl, 0>`
note: required by a bound in `BlockingI2c::<I2C>::new`
   --> /.cargo/git/checkouts/stm32f1xx-hal-bb9d214e810c7b47/f62c083/src/i2c/blocking.rs:25:21
    |
23  |     pub fn new(
    |            --- required by a bound in this associated function
24  |         i2c: I2C,
25  |         pins: (impl RInto<I2C::Scl, 0>, impl RInto<I2C::Sda, 0>),
    |                     ^^^^^^^^^^^^^^^^^^ required by this bound in `BlockingI2c::<I2C>::new`
    = note: the full name for the type has been written to '../test_itc_f1xx/target/thumbv7m-none-eabi/debug/examples/setup_i2c-7f777f03336668fc.long-type-6265293051827038659.txt'
    = note: consider using `--verbose` to print the full type name to the console

error[E0277]: the trait bound `stm32f1xx_hal::afio::i2c1::Sda: RFrom<stm32f1xx_hal::gpio::Pin<'B', 9, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 0>` is not satisfied
   --> examples/setup-i2c.rs:116:50
    |
116 |     let i2c1 = BlockingI2c::<I2C1>::new(dp.I2C1, (scl, sda),
    |                ------------------------          ^^^^^^^^^^ unsatisfied trait bound
    |                |
    |                required by a bound introduced by this call
    |
    = help: the trait `RFrom<stm32f1xx_hal::gpio::Pin<'B', 9, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 0>` is not implemented for `stm32f1xx_hal::afio::i2c1::Sda`
    = help: the following other types implement trait `RFrom<T, R>`:
              `stm32f1xx_hal::afio::i2c1::Sda` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 7, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 0>`
              `stm32f1xx_hal::afio::i2c1::Sda` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 7>, 0>`
              `stm32f1xx_hal::afio::i2c1::Sda` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 9, stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::OpenDrain>>, 1>`
              `stm32f1xx_hal::afio::i2c1::Sda` implements `RFrom<stm32f1xx_hal::gpio::Pin<'B', 9>, 1>`
    = note: required for `Pin<'B', 9, Alternate<OpenDrain>>` to implement `RInto<stm32f1xx_hal::afio::i2c1::Sda, 0>`
note: required by a bound in `BlockingI2c::<I2C>::new`
   --> /.cargo/git/checkouts/stm32f1xx-hal-bb9d214e810c7b47/f62c083/src/i2c/blocking.rs:25:46
    |
23  |     pub fn new(
    |            --- required by a bound in this associated function
24  |         i2c: I2C,
25  |         pins: (impl RInto<I2C::Scl, 0>, impl RInto<I2C::Sda, 0>),
    |                                              ^^^^^^^^^^^^^^^^^^ required by this bound in `BlockingI2c::<I2C>::new`
    = note: the full name for the type has been written to '../test_itc_f1xx/target/thumbv7m-none-eabi/debug/examples/setup_i2c-7f777f03336668fc.long-type-2758305641861797322.txt'
    = note: consider using `--verbose` to print the full type name to the console

For more information about this error, try `rustc --explain E0277`.
error: could not compile `testing-example` (example "setup-i2c") due to 2 previous errors

Click to expand code
//! Setup i2c and delays.
//! 
//!  Usage example 1:
//!        in Cargo.toml:  embedded-aht20   = "0.1.3"   
//!   
//!        use embedded_aht20::{Aht20, DEFAULT_I2C_ADDRESS}; 
//!        ...
//!        let (i2c1, mut delay, mut delay2) = setup();
//!        let mut aht  = Aht20::new(i2c1, DEFAULT_I2C_ADDRESS, &mut delay).expect("sensor initialization failed.");
//!        loop {
//!           let th = aht.measure().unwrap();   // Read humidity and temperature.
//!           delay2.delay(5000.millis()); 
//!        }
//! 
//!  Usage example 2:
//!        in Cargo.toml:  aht20-driver     = { version = "2.0.0", default-features = false }
//!   
//!        use aht20_driver::{AHT20, SENSOR_ADDRESS}; 
//!        ...
//!        let (i2c1, mut delay, mut delay2) = setup(); 
//!        let mut aht20_uninit = AHT20::new(i2c1, SENSOR_ADDRESS);
//!        let mut aht = aht20_uninit.init(&mut delay).unwrap();
//!        loop {
//!           let th = aht.measure(&mut delay).unwrap();  
//!           hprintln!("{:.2}C  {:.2}% RH", th.temperature, th.humidity);
//!           delay2.delay(5000.millis()); 
//!        }
//! 
//!  Usage example 3:
//!        in Cargo.toml:  aht20  = { git = "https://github.com/blueluna/aht20" }
//!   
//!        use aht20::{Aht20};  
//!        ...
//!        let (i2c1, mut delay, mut delay2) = setup();
//!        let mut aht = Aht20::new(i2c1, &mut delay);
//!        loop {
//!           let (h, t) = aht.read().unwrap();
//!           hprintln!("{:.3}C  {}% RH", t.celsius(), h.rh());
//!           delay2.delay(5000.millis()); 
//!        }
//! 
//!  Usage example 4:
//!        in Cargo.toml:    embedded-sht3x =  "0.1.0"
//!   
//!        use  embedded_sht3x::{Repeatability::High, Sht3x, DEFAULT_I2C_ADDRESS}; 
//!        ...
//!        let (i2c1, mut delay, mut delay2) = setup();
//!        let mut sen  = Sht3x::new(i2c1, DEFAULT_I2C_ADDRESS, &mut delay);
//!        loop {
//!           let th = sen.single_measurement().unwrap();   // Read humidity and temperature.
//!           hprintln!("{:.2}C  {:.2}% RH", th.temperature, th.humidity);
//!           delay2.delay(5000.millis()); 
//!        }
//! 
//! 
//!  Usage example 5:
//!        in Cargo.toml:  shtcx = { git = "https://github.com/dbrgn/shtcx-rs" }
//!   
//!        use  shtcx::{LowPower, PowerMode};
//!        ...
//!        let (i2c1, mut delay, mut delay2) = setup();
//!        let mut sen  = shtcx::shtc3(i2c1);
//!        sen.wakeup(&mut delay).expect("Wakeup failed"); 
//!        loop {
//!           let th = sen.measure(PowerMode::NormalMode, &mut delay)
//!                                .expect("Normal mode measurement failed");
//!           hprintln!("{:.2}C  {:.2}% RH", th.temperature.as_degrees_celsius(), th.humidity.as_percent());
//!           delay2.delay(5000.millis()); 
//!        }
//! 

#![deny(unsafe_code)]
#![no_std]
#![no_main]

#[cfg(debug_assertions)]
use panic_semihosting as _;

#[cfg(not(debug_assertions))]
use panic_halt as _;

use cortex_m_rt::entry;

use cortex_m_semihosting::hprintln;

#[cfg(feature = "stm32f1xx")]
use stm32f1xx_hal::{
    pac::{CorePeripherals, Peripherals, I2C1 },
    i2c::{DutyCycle, Mode, BlockingI2c}, 
    timer::{SysTimerExt, TimerExt, SysDelay},
    gpio::GpioExt,
    prelude::*, 
};

use embedded_hal::delay::DelayNs;


fn setup() -> (BlockingI2c<I2C1>, impl DelayNs, SysDelay){

    let cp = CorePeripherals::take().unwrap();
    let dp = Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain();
    let rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    // or
    //let clocks = rcc.cfgr.use_hse(8.MHz()).freeze(&mut flash.acr);

    let gpiob = dp.GPIOB.split();
    //let scl = gpiob.pb6; 
    //let sda = gpiob.pb7; 
    // cannot get next to work
    let scl = gpiob.pb8.into_alternate_open_drain(&mut gpiob.crh); 
    let sda = gpiob.pb9.into_alternate_open_drain(&mut gpiob.crh); 

    let i2c1 = BlockingI2c::<I2C1>::new(dp.I2C1, (scl, sda),
                   Mode::Fast {frequency: 400.kHz(), duty_cycle: DutyCycle::Ratio16to9,},
                   &clocks, 1000, 10, 1000, 1000,);

    
    // TIM1 TIM2 TIM3 and TIM4 implement trait Instance needed for these
    //let mut delay = stm32f1xx_hal::timer::FTimerUs::new(dp.TIM2, &clocks).delay();
    // or
    let delay = dp.TIM2.delay_us(&clocks);    

    let delay2 = cp.SYST.delay(&clocks); 
 
    (i2c1, delay, delay2)
}

#[entry]
fn main() -> ! {
    
    let (_i2c1, mut delay, mut delay2) = setup();

    hprintln!("Start the sensor...");
    //    example 1
    // let mut aht  = Aht20::new(i2c1, DEFAULT_I2C_ADDRESS, &mut delay).expect("sensor initialization failed.");

    delay.delay_ms(500);   // this is a DelayNs

    loop {
        hprintln!("aht.measure()");

        // example 1
        //let th = aht.measure().unwrap();   // Read humidity and temperature.
        //hprintln!("{:.3}C  {}% RH", th.temperature.celcius(), th.relative_humidity);

        delay2.delay(5000.millis());   // this is a SysDelay
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions