Closed tasosxak closed 4 years ago
The minicom output makes it Look like the error happens after it writes the "z", correct?
So the error is likely that the Builder is failing to build, and so the unwrap panics. Looks like the Error type implements Debug. Can you see if the error is NACK or OVERRUN?
Finally, is this on a custom board, or something like the Nucleo?
its a discovery kit of stm32l475VGT6 by stm. [https://www.st.com/content/ccc/resource/technical/document/reference_manual/02/35/09/0c/4f/f7/40/03/DM00083560.pdf/files/DM00083560.pdf/jcr:content/translations/en.DM00083560.pdf]
How I can find out the error type?
Instead of "unwrap"ing the result of build, you can print the error:
let mut hts_result = hts221::Builder::new(i2c)
.with_avg_t(hts221::AvgT::Avg256)
.with_avg_h(hts221::AvgH::Avg512)
.build();
if hts_result.is_err() {
hprintln!("{:?}", hts_result.err().unwrap());
}
let mut hts = hts_result.unwrap();
I was developing using a similar board, and I did not have to set the I2C pins to open drain outputs first. Does it behave differently if you do this instead:
let scl = gpiob.pb10.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
let sda = gpiob.pb11.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate stm32l4xx_hal;
extern crate hts221;
extern crate cortex_m;
#[macro_use(entry, exception)]
extern crate cortex_m_rt as rt;
#[macro_use(block)]
extern crate nb;
extern crate panic_semihosting;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
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 stm32l4xx_hal::prelude::*;
use crate::stm32l4xx_hal::serial::Serial;
const PERIOD: u32 = 5_000_000;
#[entry]
fn main() -> ! {
//hprintln!("Hello, world!").unwrap();
let peripherals = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
let mut flash = peripherals.FLASH.constrain();
let mut rcc = peripherals.RCC.constrain();
let mut gpiob = peripherals.GPIOB.split(&mut rcc.ahb2);
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let serial = Serial::usart1( peripherals.USART1, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb2);
let (mut tx, mut rx) = serial.split();
let sent = b'A';
block!(tx.write(sent)).ok();
//let p = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
block!(tx.write(b'h')).ok();
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);
block!(tx.write(b'k')).ok();
let i2c = I2c::i2c2(
peripherals.I2C2,
(scl,sda),
1.mhz(),
rcc.cfgr.freeze(&mut flash.acr),
&mut rcc.apb1r1
);
block!(tx.write(b'z')).ok();
let mut hts_result = hts221::Builder::new(i2c)
.with_avg_t(hts221::AvgT::Avg256)
.with_avg_h(hts221::AvgH::Avg512)
.build();
if hts_result.is_err() {
hprintln!("{:?}", hts_result.err().unwrap());
}
//let mut hts = hts_result.unwrap();
let x = 4;//hts.temperature_x8().unwrap() / 8;
block!(tx.write(b'Y')).ok();
block!(tx.write(x as u8)).ok();
//hprintln!("temperature: {}",hts.temperature_x8().unwrap() / 8);
loop {}
}
minicom:
Welcome to minicom 2.7.1
OPTIONS: I18n
Compiled on Aug 13 2017, 15:25:34.
Port /dev/ttyACM0, 03:53:44
Press CTRL-A Z for help on special keys
Ahkz
If I remove into_open_drain_output calls i get compiler error:
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate stm32l4xx_hal;
extern crate hts221;
extern crate cortex_m;
#[macro_use(entry, exception)]
extern crate cortex_m_rt as rt;
#[macro_use(block)]
extern crate nb;
extern crate panic_semihosting;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
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 stm32l4xx_hal::prelude::*;
use crate::stm32l4xx_hal::serial::Serial;
const PERIOD: u32 = 5_000_000;
#[entry]
fn main() -> ! {
//hprintln!("Hello, world!").unwrap();
let peripherals = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
let mut flash = peripherals.FLASH.constrain();
let mut rcc = peripherals.RCC.constrain();
let mut gpiob = peripherals.GPIOB.split(&mut rcc.ahb2);
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let serial = Serial::usart1( peripherals.USART1, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb2);
let (mut tx, mut rx) = serial.split();
let sent = b'A';
block!(tx.write(sent)).ok();
//let p = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
block!(tx.write(b'h')).ok();
let scl = gpiob.pb10.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
let sda = gpiob.pb11.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
block!(tx.write(b'k')).ok();
let i2c = I2c::i2c2(
peripherals.I2C2,
(scl,sda),
1.mhz(),
rcc.cfgr.freeze(&mut flash.acr),
&mut rcc.apb1r1
);
block!(tx.write(b'z')).ok();
let mut hts_result = hts221::Builder::new(i2c)
.with_avg_t(hts221::AvgT::Avg256)
.with_avg_h(hts221::AvgH::Avg512)
.build();
if hts_result.is_err() {
hprintln!("{:?}", hts_result.err().unwrap());
}
//let mut hts = hts_result.unwrap();
let x = 4;//hts.temperature_x8().unwrap() / 8;
block!(tx.write(b'Y')).ok();
block!(tx.write(x as u8)).ok();
//hprintln!("temperature: {}",hts.temperature_x8().unwrap() / 8);
loop {}
}
error[E0277]: the trait bound `stm32l4xx_hal::gpio::gpiob::PB10<stm32l4xx_hal::gpio::Alternate<stm32l4xx_hal::gpio::AF4, stm32l4xx_hal::gpio::Input<stm32l4xx_hal::gpio::Floating>>>: stm32l4xx_hal::i2c::SclPin<stm32l4xx_hal::stm32::I2C2>` is not satisfied
--> examples/hello.rs:57:19
|
57 | let i2c = I2c::i2c2(
| ^^^^^^^^^ the trait `stm32l4xx_hal::i2c::SclPin<stm32l4xx_hal::stm32::I2C2>` is not implemented for `stm32l4xx_hal::gpio::gpiob::PB10<stm32l4xx_hal::gpio::Alternate<stm32l4xx_hal::gpio::AF4, stm32l4xx_hal::gpio::Input<stm32l4xx_hal::gpio::Floating>>>`
|
= help: the following implementations were found:
<stm32l4xx_hal::gpio::gpiob::PB10<stm32l4xx_hal::gpio::Alternate<stm32l4xx_hal::gpio::AF4, stm32l4xx_hal::gpio::Output<stm32l4xx_hal::gpio::OpenDrain>>> as stm32l4xx_hal::i2c::SclPin<stm32l4xx_hal::stm32::I2C2>>
= note: required by `<stm32l4xx_hal::i2c::I2c<stm32l4xx_hal::stm32::I2C2, (SCL, SDA)>>::i2c2`
error[E0277]: the trait bound `stm32l4xx_hal::gpio::gpiob::PB11<stm32l4xx_hal::gpio::Alternate<stm32l4xx_hal::gpio::AF4, stm32l4xx_hal::gpio::Input<stm32l4xx_hal::gpio::Floating>>>: stm32l4xx_hal::i2c::SdaPin<stm32l4xx_hal::stm32::I2C2>` is not satisfied
--> examples/hello.rs:57:19
|
57 | let i2c = I2c::i2c2(
| ^^^^^^^^^ the trait `stm32l4xx_hal::i2c::SdaPin<stm32l4xx_hal::stm32::I2C2>` is not implemented for `stm32l4xx_hal::gpio::gpiob::PB11<stm32l4xx_hal::gpio::Alternate<stm32l4xx_hal::gpio::AF4, stm32l4xx_hal::gpio::Input<stm32l4xx_hal::gpio::Floating>>>`
|
= help: the following implementations were found:
<stm32l4xx_hal::gpio::gpiob::PB11<stm32l4xx_hal::gpio::Alternate<stm32l4xx_hal::gpio::AF4, stm32l4xx_hal::gpio::Output<stm32l4xx_hal::gpio::OpenDrain>>> as stm32l4xx_hal::i2c::SdaPin<stm32l4xx_hal::stm32::I2C2>>
= note: required by `<stm32l4xx_hal::i2c::I2c<stm32l4xx_hal::stm32::I2C2, (SCL, SDA)>>::i2c2`
Looks like the hprintln didn't do anything useful. Try replacing hprintln!("{:?}", hts_result.err().unwrap());
with
match hts_result.err().unwrap() {
stm32f4xx_hal::i2c::Error::NACK => block!(tx.write(b'n')),
stm32f4xx_hal::i2c::Error::OVERRUN => block!(tx.write(b'o')),
}
That will at least provide a bit more information, but I'm not really sure what to do in either case. You may need to step through the hts221 build function to see which call is failing. That may provide more insight.
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate stm32l4xx_hal;
extern crate hts221;
extern crate cortex_m;
#[macro_use(entry, exception)]
extern crate cortex_m_rt as rt;
#[macro_use(block)]
extern crate nb;
extern crate panic_semihosting;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
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 stm32l4xx_hal::prelude::*;
use crate::stm32l4xx_hal::serial::Serial;
const PERIOD: u32 = 5_000_000;
#[entry]
fn main() -> ! {
//hprintln!("Hello, world!").unwrap();
let peripherals = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
let mut flash = peripherals.FLASH.constrain();
let mut rcc = peripherals.RCC.constrain();
let mut gpiob = peripherals.GPIOB.split(&mut rcc.ahb2);
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let serial = Serial::usart1( peripherals.USART1, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb2);
let (mut tx, mut rx) = serial.split();
let sent = b'A';
block!(tx.write(sent)).ok();
//let p = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
block!(tx.write(b'h')).ok();
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);
block!(tx.write(b'k')).ok();
let i2c = I2c::i2c2(
peripherals.I2C2,
(scl,sda),
1.mhz(),
rcc.cfgr.freeze(&mut flash.acr),
&mut rcc.apb1r1
);
block!(tx.write(b'z')).ok();
let mut hts_result = hts221::Builder::new(i2c)
.with_avg_t(hts221::AvgT::Avg256)
.with_avg_h(hts221::AvgH::Avg512)
.build();
match hts_result.err().unwrap() {
stm32l4xx_hal::i2c::Error::NACK => block!(tx.write(b'n')).ok(),
stm32l4xx_hal::i2c::Error::OVERRUN => block!(tx.write(b'o')).ok(),
}
//let mut hts = hts_result.unwrap();
let x = 4;//hts.temperature_x8().unwrap() / 8;
block!(tx.write(b'Y')).ok();
block!(tx.write(x as u8)).ok();
//hprintln!("temperature: {}",hts.temperature_x8().unwrap() / 8);
loop {}
}
Error:
error[E0599]: no variant named `NACK` found for type `stm32l4xx_hal::i2c::Error` in the current scope
--> examples/hello.rs:71:28
|
71 | stm32l4xx_hal::i2c::Error::NACK => block!(tx.write(b'n')).ok(),
| ---------------------------^^^^
| |
| variant not found in `stm32l4xx_hal::i2c::Error`
error[E0599]: no variant named `OVERRUN` found for type `stm32l4xx_hal::i2c::Error` in the current scope
--> examples/hello.rs:72:28
|
72 | stm32l4xx_hal::i2c::Error::OVERRUN => block!(tx.write(b'o')).ok(),
| ---------------------------^^^^^^^
| |
| variant not found in `stm32l4xx_hal::i2c::Error`
error[E0308]: mismatched types
--> examples/hello.rs:70:8
|
70 | / match hts_result.err().unwrap() {
71 | | stm32l4xx_hal::i2c::Error::NACK => block!(tx.write(b'n')).ok(),
72 | | stm32l4xx_hal::i2c::Error::OVERRUN => block!(tx.write(b'o')).ok(),
73 | | }
| |_^ expected (), found enum `core::option::Option`
|
= note: expected type `()`
found type `core::option::Option<()>`
error: aborting due to 3 previous errors
Some errors occurred: E0308, E0599.
For more information about an error, try `rustc --explain E0308`.
error: Could not compile `app`.
To learn more, run the command again with --verbose.
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate stm32l4xx_hal;
extern crate hts221;
extern crate cortex_m;
#[macro_use(entry, exception)]
extern crate cortex_m_rt as rt;
extern crate stm32l4xx_hal as hal;
extern crate cortex_m_semihosting as sh;
extern crate nb;
extern crate panic_semihosting;
use cortex_m_semihosting::{debug, hprintln};
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 stm32l4xx_hal::prelude::*;
use crate::stm32l4xx_hal::serial::Serial;
use crate::stm32l4xx_hal::prelude::*;
use crate::stm32l4xx_hal::delay::Delay;
use crate::rt::ExceptionFrame;
use crate::rt::entry;
use core::fmt::Write;
use crate::sh::hio;
const PERIOD: u32 = 5_000_000;
#[entry]
fn main() -> ! {
let mut hstdout = hio::hstdout().unwrap();
let peripherals = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
let mut flash = peripherals.FLASH.constrain();
let mut rcc = peripherals.RCC.constrain();
let mut gpiob = peripherals.GPIOB.split(&mut rcc.ahb2);
let clocks = rcc.cfgr.freeze(&mut flash.acr);
//let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
// let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
// let serial = Serial::usart1( peripherals.USART1, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb2);
//let (mut tx, mut rx) = serial.split();
//let sent = b'A';
//block!(tx.write(sent)).ok();
//let p = stm32l4xx_hal::stm32l4::stm32l4x5::Peripherals::take().unwrap();
//block!(tx.write(b'h')).ok();
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);
//block!(tx.write(b'k')).ok();
let i2c = I2c::i2c2(
peripherals.I2C2,
(scl,sda),
1.mhz(),
rcc.cfgr.freeze(&mut flash.acr),
&mut rcc.apb1r1
);
//block!(tx.write(b'z')).ok();
let mut hts_result = hts221::Builder::new(i2c)
.with_avg_t(hts221::AvgT::Avg256)
.with_avg_h(hts221::AvgH::Avg512)
.build();
if hts_result.is_err() {
writeln!(hstdout,"{:?}", hts_result.err().unwrap()).unwrap();
}
//let mut hts = hts_result.unwrap();
let x = 4;//hts.temperature_x8().unwrap() / 8;
//block!(tx.write(b'Y')).ok();
// block!(tx.write(x as u8)).ok();
//hprintln!("temperature: {}",hts.temperature_x8().unwrap() / 8);
loop {}
}
openocd session:
xPSR: 0x01000000 pc: 0x08008a66 msp: 0x20018000, semihosting
Nack
I went out and got the same board, and can confirm this issue. I suspect there's something specific to this board that is not enabling either the I2C2 bus or this specific sensor by default, but I haven't had any luck narrowing it down.
I doubt the underlying issue is with the driver, but I'll keep the issue open until I can get it fixed, since I'd like to use the sensor on this board.
I tried out the X-Cube-Watson demo software from STMicro, and it can talk to the HTS221 just fine. Now to replicate all of the initialization in Rust...
Hi @danielgallagher0 have you managed to find what’s wrong?
No, I haven't had time in the evenings to work on this for the last couple of months. I should be able to get back to it mid-August or September.
Hi, any news on this?
Probably the reason is 10 bit addressing: https://github.com/copterust/vl53l0x/issues/5
Finally got back to this, and found it. The issue that @bofh linked is correct, though it's 8-bit addressing, not 10-bit. stm32f30x-hal (which is the first HAL I developed against) uses 7-bit addresses for its I2C devices, and appends the 1-bit R/W value in the least significant place to make the full 8-bit address. stm32l4xx-hal expects the address to be 8-bit.
I confirmed by updating the I2C_ID for the HTS221 to 0xBE (i.e., 0x5F << 1), and it works. Will update the crate appropriately and close when released.
I get runtime error, after this command
block!(tx.write(b'k')).ok();
openocd :
gdb session:
minicom: