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

Running example/rpi.rs on raspberry pi zero multiple times causes program to hang indefinitely. #29

Open
MechanicalPython opened this issue Jun 13, 2020 · 11 comments

Comments

@MechanicalPython
Copy link

Cloning mpu9250 onto a pi zero and running cargo run --example rpi follows the same steps consistently:

First time gives: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Os { code: 13, kind: PermissionDenied, message: "Permission denied" })', examples/rpi.rs:35:5

Sometimes runs correctly 1-3 times.

From then on the program hangs indefinitely on this line: let mut mpu9250 = Mpu9250::marg_default(spi, ncs, &mut Delay).unwrap();

Once the program starts hanging, it never corrects itself. The longest I've let it hang is a few minutes. Reboots don't always work but a power off restart gives the panic, correctly running and then hanging cycle.

Wiring is SPI and follows the guide given at the top of rpi.rs.

I also had to change mpu9250.all().unwrap() to mpu9250.all::<[f32; 3]>().unwrap() on line 49 and 53 due to compile error:

error[E0283]: type annotations needed
  --> examples/rpi.rs:49:31
   |
49 |     println!("{:#?}", mpu9250.all().unwrap());
   |                               ^^^
   |                               |
   |                               cannot infer type for type parameter `T` declared on the method `all`
   |                               help: consider specifying the type argument in the method call: `all::<T>`
   |
   = note: cannot resolve `_: std::convert::From<[f32; 3]>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0283`.
error: could not compile `mpu9250`.
@tchamelot
Copy link
Collaborator

For the first point, do you run the code as root or as a standard user? I think that you need root privilege to open /dev/spidev0.0.

The second point is an update on the code base that was not mirrored on the examples, I will change that. Thank you for the feedback.

@MechanicalPython
Copy link
Author

I run as the default pi user which I believe has spi permissions. Running groups gives pi adm dialout cdrom sudo audio video plugdev games users input netdev gpio i2c spi

@tchamelot
Copy link
Collaborator

tchamelot commented Jun 13, 2020

Yeah my bad, it has nothing to do with spi chardev. It is on a line dealing with gpio, but you also seem to have gpio rights. Looking quickly into the code i noticed that the ncs pin is exported but never released (unexported) and that the Pinstruct do not implement the Droptrait. Can you try adding ncs.unexport().unwrap() at the last line?

@MechanicalPython
Copy link
Author

I added ncs.unexport().unwrap() to line 53 and got the following compile error:

error[E0382]: borrow of moved value: `ncs`
  --> examples/rpi.rs:53:5
   |
32 |     let ncs = Pin::new(25);
   |         --- move occurs because `ncs` has type `hal::Pin`, which does not implement the `Copy` trait
...
37 |     let mut mpu9250 = Mpu9250::marg_default(spi, ncs, &mut Delay).unwrap();
   |                                                  --- value moved here
...
53 |     ncs.unexport().unwrap();
   |     ^^^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: could not compile `mpu9250`.

@MechanicalPython
Copy link
Author

MechanicalPython commented Jun 13, 2020

I added

53: let ncs = Pin::new(25);

54: ncs.unexport().unwrap();

And now the program cycles between

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Os { code: 13, kind: PermissionDenied, message: "Permission denied" })', examples/rpi.rs:35:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

and successfully running.

Line 35 (permission error location) is:

ncs.set_direction(Direction::Out).unwrap();

@tchamelot
Copy link
Collaborator

Ok, I think it solves some part of the issue because you don't have anymore the case when you need to power down the system. For the permission denied issue, can you try to run as root several time to reproduce it and take a look at rust-embedded/rust-sysfs-gpio#5.

@regexident
Copy link

For what it's worth I'm seeing the same behavior (random hanging) when using Mpu9250::marg_default from a bare-bones STM32F4 board.

@tchamelot
Copy link
Collaborator

For what it's worth I'm seeing the same behavior (random hanging) when using Mpu9250::marg_default from a bare-bones STM32F4 board.

I don't think I can help you without any more detail. I don't have a stm32f64 so I can't reproduce it. I know that there are bugs on examples. They have not been updated with new features yet. I suggest you to open a new issue to see if anyone can help you.

@MechanicalPython
Copy link
Author

For what it's worth I tracked down the hanging error to line 210 in src/device.rs (

while Device::read(self, Register::I2C_MST_STATUS)? & (1 << 6) == 0 {}
)

When working normally, the Device::read(self, Register::I2C_MST_STATUS)? gives the number 64 and when it hangs it gives 0, causing the while loop to run forever.

@mbuesch
Copy link
Contributor

mbuesch commented Jan 5, 2022

@MechanicalPython Can you try the change from Pull Request #36?
I think that should fix the hang.

@t348575
Copy link

t348575 commented Dec 18, 2022

For what it's worth I'm seeing the same behavior (random hanging) when using Mpu9250::marg_default from a bare-bones STM32F4 board.

I'm also trying to interface with a 9255 on an stm32f401ccu, and it waits on the same line. I'm on the master branch of this repo, and my code is basically just an example hello world with rtic and the mpu 9255. The IMU works fine.

Any possible reasons / suggestions?

while Device::read(self, Register::I2C_MST_STATUS)? & (1 << 6) == 0 {}

My code:

#![no_main]
#![no_std]

use core::panic::PanicInfo;

use cortex_m_rt::{ExceptionFrame, exception};
use rtt_target::rprintln;

#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true)]
mod app {
    use mpu9250::{Mpu9250, SpiDevice, Marg};
    use stm32f4xx_hal::{prelude::*, pac::{NVIC, SPI1}, spi::Spi, interrupt, gpio::{Pin, Alternate, Output, Edge, Speed}};
    use rtt_target::{rprintln, rtt_init_print};

    #[shared]
    struct Shared {}

    #[local]
    struct Local {
        mpu_interrupt: Pin<'A', 0>,
        mpu: Mpu9250<SpiDevice<Spi<SPI1, (Pin<'A', 5, Alternate<5>>, Pin<'A', 6, Alternate<5>>, Pin<'A', 7, Alternate<5>>), false>, Pin<'A', 4, Output>>, Marg>
    }

    #[init]
    fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
        rtt_init_print!();
        rprintln!("Device up!");

        let mut dp = ctx.device;
        let cp = ctx.core;

        let rcc = dp.RCC.constrain();
        let gpioa = dp.GPIOA.split();
        let gpiob = dp.GPIOB.split();
        let gpioc = dp.GPIOC.split();
        let mut led = gpioc.pc13.into_push_pull_output();
        led.set_high();

        let mut syscfg = dp.SYSCFG.constrain();

        let clocks = rcc.cfgr   
                        .sysclk(48.MHz()).freeze();

        let sck_scl = gpioa.pa5.into_alternate();
        let miso_ad0 = gpioa.pa6.into_alternate();
        let mosi_sda = gpioa.pa7.into_alternate();

        let spi = dp.SPI1.spi(
            (sck_scl, miso_ad0, mosi_sda),
            mpu9250::MODE,
            1.MHz(),
            &clocks,
        );
        let ncs = gpioa.pa4.into_push_pull_output().speed(Speed::High);

        let mut interrupt_pin = gpioa.pa0.into_pull_down_input();
        interrupt_pin.make_interrupt_source(&mut syscfg);
        interrupt_pin.enable_interrupt(&mut dp.EXTI);
        interrupt_pin.trigger_on_edge(&mut dp.EXTI, Edge::Falling);

        let mut delay = {
            use asm_delay::bitrate::*;
            asm_delay::AsmDelay::new(clocks.sysclk().to_Hz().hz())
        };

        rprintln!("Pins, spi, ncs ok");
        let mut mpu = Mpu9250::marg_default(spi, ncs, &mut delay).expect("Could not create mpu9250");
        led.set_low();

        rprintln!("Mpu ok");

        mpu.enable_interrupts(mpu9250::InterruptEnable::RAW_RDY_EN).expect("Could not enable mpu interrupt");

        NVIC::unpend(interrupt::EXTI0);
        unsafe { NVIC::unmask(interrupt::EXTI0) }
        
        rprintln!("Mpu interrupts ready");

        (
            Shared {},
            Local {
                mpu_interrupt: interrupt_pin,
                mpu
            },
            init::Monotonics()
        )
    }

    #[idle]
    fn idle(_: idle::Context) -> ! {
        loop {
            cortex_m::asm::nop();
        }
    }

    #[task(binds = EXTI0, local = [mpu, mpu_interrupt])]
    fn handle_mpu(ctx: handle_mpu::Context) {
        match ctx.local.mpu.all::<[f32; 3]>() {
            Ok(a) => {
                rprintln!("[a:({:?},{:?},{:?}),g:({:?},{:?},{:?}),t:{:?}]",
                    a.accel[0],
                    a.accel[1],
                    a.accel[2],
                    a.gyro[0],
                    a.gyro[1],
                    a.gyro[2],
                    a.temp
                );
            }
            Err(e) => {
                rprintln!("e: {:?}", e);
            }
        }

        ctx.local.mpu_interrupt.clear_interrupt_pending_bit();
    }
}

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

#[inline(never)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    rprintln!("{}", info);
    loop {}
}

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

5 participants