copterust / vl53l0x

vl53l0x
Other
9 stars 8 forks source link

BusError(Nack) for stm32l475 #4

Open tasosxak opened 5 years ago

tasosxak commented 5 years ago

Hi guys, I tried to use this driver with RTFM for stm32l475 (the Discovery kit for IoT node, stm32l4) and i get BusError(Nack):

let scl = gpiob.pb10.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb11.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);

    let i2c = I2c::i2c2(
           dp.I2C2,
           (scl,sda),
           400.khz(),
           rcc.cfgr.freeze(&mut flash.acr),
          &mut rcc.apb1r1
           );

    let mut dis  = VL53L0x::new(i2c);

    let diss : vl53l0x::VL53L0x<hal::i2c::I2c<hal::stm32::I2C2, 
    (hal::gpio::gpiob::PB10<hal::gpio::Alternate<hal::gpio::AF4, 
    hal::gpio::Output<hal::gpio::OpenDrain>>>, 
    hal::gpio::gpiob::PB11<hal::gpio::Alternate<hal::gpio::AF4,
    hal::gpio::Output<hal::gpio::OpenDrain>>>)>>;

    match dis {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(o) => diss = o,
    }

openocd session:

...
xPSR: 0x61000000 pc: 0x20000050 msp: 0x20018000, semihosting
Warn : block write succeeded
Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (1362). Workaround: increase "set remotetimeout" in GDB
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
adapter speed: 480 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08017288 msp: 0x20018000, semihosting
BusError(Nack)

Any idea what is wrong?

bofh commented 5 years ago

Nobody answered on a bus. I've read the documentation and it seems that they configured i2c address differently (from 7.15 I2C addresses of modules used on MB1297). Try to change it here: https://github.com/copterust/vl53l0x/blob/master/src/lib.rs#L21

hargoniX commented 5 years ago

But the manual says that the read address is 0x52 and the write one is 0x53 which comes down to 0b101001x (x for read or write bit) which is exactly the address you are using at the moment inside your code isnt it?

bofh commented 5 years ago

True, can you use any other device on that i2c?

tasosxak commented 5 years ago

Yes magnetometer , but no hts221 (nack error)

bofh commented 5 years ago

Another idea -- they have VL53L0X_XSHUT connected, maybe it is pulled to off?

bofh commented 5 years ago

Xshutdown pin, Active LOW -- so try to output high on the corresponding pin.

bofh commented 5 years ago

According to this: PC6 -- GPIO_Output -- VL53L0X_XSHUT. So configure it as an output and set to high.

bofh commented 5 years ago

Also add the delay for 1.2ms after pin rise (it's the boot time of vl.)

tasosxak commented 5 years ago
let mut pin = gpioc.pc6.into_push_pull_output(&mut gpioc.moder, &mut gpioc.otyper);
    pin.set_high();

    for i in 1..50000 {}

    let scl = gpiob.pb10.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb11.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);

    let i2c = I2c::i2c2(
           dp.I2C2,
           (scl,sda),
           400.khz(),
           rcc.cfgr.freeze(&mut flash.acr),
          &mut rcc.apb1r1
           );

    //let mut mg = Lis3mdl::new(i2c).unwrap();
    let mut dis  = VL53L0x::new(i2c);

    let diss : vl53l0x::VL53L0x<hal::i2c::I2c<hal::stm32::I2C2, 
    (hal::gpio::gpiob::PB10<hal::gpio::Alternate<hal::gpio::AF4, 
    hal::gpio::Output<hal::gpio::OpenDrain>>>, 
    hal::gpio::gpiob::PB11<hal::gpio::Alternate<hal::gpio::AF4,
    hal::gpio::Output<hal::gpio::OpenDrain>>>)>>;
    match dis {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(o) => diss = o,
    }

Because rtfm takes ownership of SySTick , i add a for loop for the delay. But i get the same message "BussError(Nack)"

bofh commented 5 years ago

I wonder if it compiles or that loop just got optimized out?

tasosxak commented 5 years ago

the message however does appear after some seconds

little-arhat commented 5 years ago

@tasosxak you can also use Delay implementation based on cortex-m::asm::delay: http://github.com/copterust/asm-delay.

bofh commented 5 years ago

@tasosxak Let’s check if it is a driver problem or something else. Can you try something like:

const ADDRESS: u8 = 0x29;
let mut data: [u8; 1] = [0];
i2c.write_read(ADDRESS, &[0xC0], &mut data)?;
tasosxak commented 5 years ago

@tasosxak you can also use Delay implementation based on cortex-m::asm::delay: http://github.com/copterust/asm-delay.

let mut pin = gpioc.pc6.into_push_pull_output(&mut gpioc.moder, &mut gpioc.otyper);
    pin.set_high();

    let d = AsmDelay::new(64_000_000); // 64Mhz
    d.delay_ms(2);

    let scl = gpiob.pb10.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb11.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);

    let i2c = I2c::i2c2(
           dp.I2C2,
           (scl,sda),
           400.khz(),
           rcc.cfgr.freeze(&mut flash.acr),
          &mut rcc.apb1r1
           );

    //let mut mg = Lis3mdl::new(i2c).unwrap();
    let mut dis  = VL53L0x::new(i2c);

    let diss : vl53l0x::VL53L0x<hal::i2c::I2c<hal::stm32::I2C2, 
    (hal::gpio::gpiob::PB10<hal::gpio::Alternate<hal::gpio::AF4, 
    hal::gpio::Output<hal::gpio::OpenDrain>>>, 
    hal::gpio::gpiob::PB11<hal::gpio::Alternate<hal::gpio::AF4,
    hal::gpio::Output<hal::gpio::OpenDrain>>>)>>;
    match dis {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(o) => diss = o,
    }

Compiler error:

error[E0277]: the trait bound `bitrate::Hertz<u32>: core::convert::From<u32>` is not satisfied
  --> src/main.rs:92:13
   |
92 |     let d = AsmDelay::new(64_000_000u32); // 64Mhz
   |             ^^^^^^^^^^^^^ the trait `core::convert::From<u32>` is not implemented for `bitrate::Hertz<u32>`
   |
   = note: required because of the requirements on the impl of `core::convert::Into<bitrate::Hertz<u32>>` for `u32`
   = note: required by `asm_delay::AsmDelay::new
tasosxak commented 5 years ago

@tasosxak Let’s check if it is a driver problem or something else. Can you try something like:

const ADDRESS: u8 = 0x29;
let mut data: [u8; 1] = [0];
i2c.write_read(ADDRESS, &[0xC0], &mut data)?;
 let mut pin = gpioc.pc6.into_push_pull_output(&mut gpioc.moder, &mut gpioc.otyper);
    pin.set_high();

    for i in 1..5000 {}
   // let d = AsmDelay::new(64_000_000u32); // 64Mhz
   // d.delay_ms(2);

    let scl = gpiob.pb10.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb11.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);

    let mut i2c = I2c::i2c2(
           dp.I2C2,
           (scl,sda),
           400.khz(),
           rcc.cfgr.freeze(&mut flash.acr),
          &mut rcc.apb1r1
           );

    const ADDRESS: u8 = 0x29; 
    let mut data: [u8; 1] = [0]; 
    let mut x = i2c.write_read(ADDRESS, &[0xC0], &mut data);
    match x {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(_) => hprintln!("its ok").unwrap(),
    }

    //let mut mg = Lis3mdl::new(i2c).unwrap();
    let mut dis  = VL53L0x::new(i2c);

    let diss : vl53l0x::VL53L0x<hal::i2c::I2c<hal::stm32::I2C2, 
    (hal::gpio::gpiob::PB10<hal::gpio::Alternate<hal::gpio::AF4, 
    hal::gpio::Output<hal::gpio::OpenDrain>>>, 
    hal::gpio::gpiob::PB11<hal::gpio::Alternate<hal::gpio::AF4,
    hal::gpio::Output<hal::gpio::OpenDrain>>>)>>;
    match dis {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(o) => diss = o,
    }

openocd output:

Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (1402). Workaround: increase "set remotetimeout" in GDB
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
adapter speed: 480 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08017a58 msp: 0x20018000, semihosting
Nack
BusError(Nack)
little-arhat commented 5 years ago

Docs of asmdelay should be updated, I guess.

AsmDelay uses bitrate crate, so you should do use bitrate::* and then AsmDelay::new(65.mhz()).

Alternatevely, you could use just cortex-m::asm::delay, but that one accepts cycle count.

bofh commented 5 years ago

@tasosxak so it looks like a problem on a bus. I'm still 98% sure that an empty for loop will be removed by the compiler so please try reading who_am_i register after the delay implemented via AsmDelay, or cortex_m::asm::delay.

tasosxak commented 5 years ago
extern crate panic_semihosting;
extern crate stm32l4xx_hal as hal;
extern crate hts221;
extern crate lis3mdl;
extern crate vl53l0x;
extern crate embedded_hal;

use cortex_m_semihosting::hprintln;
use rtfm::{app, Instant};
use hts221::Builder;
//use stm32l4xx_hal::rcc::RccExt;
//use stm32l4xx_hal::gpio::GpioExt;
//use stm32l4::stm32l4x5::interrupt;
use stm32l4xx_hal::i2c::SdaPin;
use stm32l4xx_hal::i2c::SclPin;
use stm32l4xx_hal::i2c::Error;
use stm32l4xx_hal::i2c::I2c;
use stm32l4xx_hal::stm32::I2C2;
//use stm32l4xx_hal::flash::FlashExt;
//use stm32l4xx_hal::time::U32Ext;
//use hal::delay::Delay;
//use hal::prelude::*;
use lis3mdl::Lis3mdl;
use vl53l0x::VL53L0x;
//use embedded_hal::prelude::*;
//use asm_delay::AsmDelay;
use bitrate::*;
error[E0034]: multiple applicable items in scope
  --> src/main.rs:94:30
   |
94 |     let d = AsmDelay::new(65.mhz()); // 64Mhz
   |                              ^^^ multiple `mhz` found

I really i dont know why i get this error

tasosxak commented 5 years ago

I tried "cortex_m::asm::delay;" so now :

let mut pin = gpioc.pc6.into_push_pull_output(&mut gpioc.moder, &mut gpioc.otyper);
    pin.set_high();

    //for i in 1..5000 {}
    //let d = AsmDelay::new(65.mhz()); // 64Mhz
    //d.delay_ms(2);
    delay(80000) ;

    let scl = gpiob.pb10.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb11.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper).into_af4(&mut gpiob.moder, &mut gpiob.afrh);

    let mut i2c = I2c::i2c2(
           dp.I2C2,
           (scl,sda),
           400.khz(),
           rcc.cfgr.freeze(&mut flash.acr),
          &mut rcc.apb1r1
           );

    const ADDRESS: u8 = 0x29; 
    let mut data: [u8; 1] = [0]; 
    let mut x = i2c.write_read(ADDRESS, &[0xC0], &mut data);
    match x {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(_) => hprintln!("its ok").unwrap(),
    }

    //let mut mg = Lis3mdl::new(i2c).unwrap();
    let mut dis  = VL53L0x::new(i2c);

    let diss : vl53l0x::VL53L0x<hal::i2c::I2c<hal::stm32::I2C2, 
    (hal::gpio::gpiob::PB10<hal::gpio::Alternate<hal::gpio::AF4, 
    hal::gpio::Output<hal::gpio::OpenDrain>>>, 
    hal::gpio::gpiob::PB11<hal::gpio::Alternate<hal::gpio::AF4,
    hal::gpio::Output<hal::gpio::OpenDrain>>>)>>;
    match dis {
      Err(e) => hprintln!("{:?}",e).unwrap(),
      Ok(o) => diss = o,
    }

openocd:

Warn : Padding 4 bytes to keep 8-byte write size
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x20000050 msp: 0x20018000, semihosting
Warn : block write succeeded
Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (1373). Workaround: increase "set remotetimeout" in GDB
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
adapter speed: 480 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08017790 msp: 0x20018000, semihosting
Nack
BusError(Nack)
bofh commented 5 years ago

Are C examples for vl53 work on your board?

tasosxak commented 5 years ago

I didn't try with C. As I said magnetometer which uses i2c works fine.

bofh commented 5 years ago

To sum up:

So it is either:

Running official C VL53 example for this board would either confirm, or disprove hardware problem.

bofh commented 5 years ago

BTW: I’ve found the schematics of your board, they do have a pull-up resistor on a xshut pin of vl, so you could remove that code, it seems that it does nothing at all.

tasosxak commented 5 years ago

I didn't call who_am_i function if is important i can try. Also hts221 sensor doesnt work ,here i get "Nack" error.

bofh commented 5 years ago

Who am I is the register inside vl and you are reading it directly without a driver with a line let mut x = i2c.write_read(ADDRESS, &[0xC0], &mut data); and it does not work.

tasosxak commented 5 years ago

So if who_am_i register doesnt work it should not work magnetometer right?

bofh commented 5 years ago

Something is wrong before the driver. You need to debug it a bit. To understand what exactly try C example (if there is one that comes with this board.) Or maybe ask the embedded_hal team.

tasosxak commented 5 years ago

I checked it on another stm32l475 board and I get the same error.

bofh commented 5 years ago

Is it your board? https://www.st.com/en/evaluation-tools/b-l475e-iot01a.html

tasosxak commented 5 years ago

Yes

tasosxak commented 5 years ago

Also the link of issue for hts221 sensor: https://github.com/danielgallagher0/hts221/issues/4

lucazulian commented 4 years ago

I've the same problem for STM32L432 board