Pin set_direction errors right after export
RaulTrombin opened this issue · 6 comments
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.
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.
Any tips on how to investigate this further? Could it be something related to method export?
@RaulTrombin What SOC are you targeting?
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.
@posborne it's the arm7 for raspberry pi 4, cdev is another crate/feature?
@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).