rust-embedded / linux-embedded-hal

Implementation of the `embedded-hal` traits for Linux devices
Apache License 2.0
241 stars 41 forks source link

Pin set_direction errors right after export #93

Closed RaulTrombin closed 1 year ago

RaulTrombin commented 1 year ago

Hi, I'm using the Pin method for CS1 and CS2, also for 3 leds. Here is how I'm using it:

        let cs_2 = Pin::new(16);
        cs_2.export().expect("Error: Error during CS2 export");
        cs_2.set_direction(Direction::High)
            .expect("Error: Setting CS2 pin as output");

So, when I do a first run, it fails:

System is Linux on armv7l hardware
OS Release is 5.10.33-v7l+
OS Version is #1415 SMP Fri Apr 30 15:50:57 BST 2021
Iniciating navigator module.
thread '<unnamed>' panicked at 'Error: Setting CS2 pin as output: Io(Os { code: 13, kind: PermissionDenied, message: "Permission denied" })', /home/raultrombin/.cargo/git/checkouts/navigator-rs-2872844b08e6ceff/cfe571b/src/lib.rs:131:14
stack backtrace:
   0: 0xb6f56e80 - std::backtrace_rs::backtrace::libunwind::trace::hd3840244c887d756
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1: 0xb6f56e80 - std::backtrace_rs::backtrace::trace_unsynchronized::hfa9aa3f288e7ea4d
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2: 0xb6f56e80 - std::sys_common::backtrace::_print_fmt::ha5dd1213f42cd24c
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/sys_common/backtrace.rs:65:5
   3: 0xb6f56e80 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h10e27ff4dc06f70d
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/sys_common/backtrace.rs:44:22
   4: 0xb6f72874 - core::fmt::rt::Argument::fmt::h6ca71d35b3cbe820
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/core/src/fmt/rt.rs:138:9
   5: 0xb6f72874 - core::fmt::write::h0dd162dfc1d20034
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/core/src/fmt/mod.rs:1094:21
   6: 0xb6f54ea8 - std::io::Write::write_fmt::h5e7c8c388c0530bc
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/io/mod.rs:1713:15
   7: 0xb6f56cb0 - std::sys_common::backtrace::_print::h85d5586bf00d40ec
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/sys_common/backtrace.rs:47:5
   8: 0xb6f56cb0 - std::sys_common::backtrace::print::h4e6afe6a16138b69
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/sys_common/backtrace.rs:34:9
   9: 0xb6f57f7c - std::panicking::default_hook::{{closure}}::h8cfdb93069a88529
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/panicking.rs:269:22
  10: 0xb6f57cc8 - std::panicking::default_hook::h686642dd8d4b0259
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/panicking.rs:288:9
  11: 0xb6f58678 - std::panicking::rust_panic_with_hook::h984f6dcc57afc0f1
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/panicking.rs:705:13
  12: 0xb6f5839c - std::panicking::begin_panic_handler::{{closure}}::hff00024b15d9e6b2
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/panicking.rs:597:13
  13: 0xb6f57314 - std::sys_common::backtrace::__rust_end_short_backtrace::hed49dc7f027d4b45
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/sys_common/backtrace.rs:151:18
  14: 0xb6f58154 - rust_begin_unwind
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/std/src/panicking.rs:593:5
  15: 0xb6f35b38 - core::panicking::panic_fmt::h79c5dd6da1f47f23
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/core/src/panicking.rs:67:14
  16: 0xb6f35eb4 - core::result::unwrap_failed::hc7b5d8b3e1351f6b
                       at /rustc/f0411ffcebcd7f75ac02ed45feb53ffd07b75398/library/core/src/result.rs:1651:5
  17: 0xb6f37510 - navigator_rs::Navigator::new::hcc0def6f7439095e
  18: 0xb6f3622c - navigator::NavigationManager::get_instance::he00dd8700ca85460
  19: 0xb6f36350 - init
  20:    0x10d78 - main
                       at /home/blueos/deploy/examples/cpp/main.cpp:26:7
  21: 0xb6c6d740 - __libc_start_main
                       at ./csu/libc-start.c:308:16
fatal runtime error: failed to initiate panic, error 9
Aborted

But during the next run it works, basically i have to run it 5 times before to have it working (the 5 first erros for each pin), on each boot of the OS. Running it as sudo works at the fresh first time.

RaulTrombin commented 1 year ago

I discovered that there should be a minimum delay of 20 milliseconds between exporting and setting directions. In the case of port 16, it requires a 30-millisecond delay, although the reason for this is unclear.

            pin.export().expect("Error: Error during led pins export");
            Delay {}.delay_ms(30 as u16);
            pin.set_direction(Direction::High)
                .expect("Error: Setting led pins as output");

In conclusion, if you run the program with sudo, the delay is not necessary. However, if you run it as a regular user, this delay is required.I guess it's related to the kernel.

RaulTrombin commented 1 year ago

Any tips on how to investigate this further? Could it be something related to method export?

posborne commented 1 year ago

@RaulTrombin What SOC are you targeting?

posborne commented 1 year ago

Actually, thinking about this a bit more I strongly suspect that this is a udev-related race condition on export. The kernel exports the device but it is async for udev to change the permissions. If your code gets to it first, then the perms won't be updated yet.

The cdev API wouldn't have this same problem.

RaulTrombin commented 1 year ago

@posborne it's the arm7 for raspberry pi 4, cdev is another crate/feature?

posborne commented 1 year ago

@RaulTrombin The GPIO sysfs interface is deprecated. The linux-embedded-hal crate provides both as part of features. To interact with the kernel via the cdev interface you'd use https://docs.rs/linux-embedded-hal/latest/linux_embedded_hal/struct.CdevPin.html (and then the embedded-hal interface once you have a pin).