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

GPIO input gives segmentation fault on BeagleBone Black in v3.1.0 #2313

Open
FredMurphy opened this issue May 13, 2024 · 15 comments
Open

GPIO input gives segmentation fault on BeagleBone Black in v3.1.0 #2313

FredMurphy opened this issue May 13, 2024 · 15 comments
Assignees
Labels
bug Something isn't working Priority:0 Work that we can't release without
Milestone

Comments

@FredMurphy
Copy link

Describe the bug

Opening a pin for input on a BeagleBone Black gives a Segmentation Fault in v3.1.0. The same code works in v3.0.0

Steps to reproduce

using System.Device.Gpio;

GpioController controller = new();
GpioPin buttonPin = controller.OpenPin(67, PinMode.Input);

code compiled with the following and then copied over via SCP:

dotnet publish --runtime linux-arm --self-contained

Expected behavior
An input pin should be opened and value can later be read.

Actual behavior
Segmentation fault as the pin is opened. Output pins work fine.

Versions used
dotnet version 8.0.204 (also tried 6.0.421)
BeagleBone Debian 11.7 minimal (although seems to happen on other versions too)
System.Device.Gpio version 3.1.0

Reverting System.Device.Gpio to 3.0.0. fixes the issue.

@FredMurphy FredMurphy added the bug Something isn't working label May 13, 2024
@FredMurphy FredMurphy changed the title GPIO input gives segmentation fault on BeagleBone Black since v3.1.0 GPIO input gives segmentation fault on BeagleBone Black in v3.1.0 May 13, 2024
@pgrawehr
Copy link
Contributor

Can you add the result of GpioController.QueryComponentInformation to the question? I don't remember any relevant changes there.

@FredMurphy
Copy link
Author

FredMurphy commented May 15, 2024

3.0.0 (working)

{
  "Name": "System.Device.Gpio.GpioController",
  "Description": "Generic GPIO Controller",
  "Properties": {
    "OpenPins": ""
  },
  "SubComponents": [
    {
      "Name": "System.Device.Gpio.Drivers.SysFsDriver",
      "Description": "Gpio Driver",
      "Properties": {},
      "SubComponents": []
    }
  ]
}

3.1.0 (not working)

{
  "Name": "System.Device.Gpio.GpioController",
  "Description": "Generic GPIO Controller",
  "Properties": {
    "OpenPins": ""
  },
  "SubComponents": [
    {
      "Name": "System.Device.Gpio.Drivers.LibGpiodDriver",
      "Description": "LibGpiodDriver",
      "Properties": {
        "LibGpiodVersion": "1.6.2"
      },
      "SubComponents": []
    }
  ]
}

No surprises that this fixes the problem when running 3.1.0, but obviously the default for the BBB is not ideal.

GpioController controller = new(PinNumberingScheme.Logical, new SysFsDriver());

@pgrawehr
Copy link
Contributor

At least there's a workaround ;-)

I guess we have to analyze why

a) 3.0.0 prefers sysfs over libgpiod and
b) libgpiod doesn't work

Can you verify whether libgpiod would work with 3.0?

@FredMurphy
Copy link
Author

FredMurphy commented May 16, 2024

I hadn't thought to check that.
3.0.0 also gives a segmentation fault when asked to use LibGpiodDriver,

@pgrawehr
Copy link
Contributor

pgrawehr commented May 16, 2024

[Triage] This somehow sounds like a problem in libgpiod itself. There's a command line tool called gpiod which you could use to check whether the bug is in the libgpiod library itself or in our code. Here's a link:
https://lloydrochester.com/post/hardware/libgpiod-input-rpi/

First try to run gpiodetect to make sure you are using a valid controller and line.

@krwq krwq added the Priority:0 Work that we can't release without label May 16, 2024
@FredMurphy
Copy link
Author

gpiod seems to work fine on its own. My above example logical pin of 67 maps to gpiod chip2 pin3. The following works and gives a 0 or 1 depending on whether I connect the pin to GND or 3V3.

gpioget gpiochip2 3

@raffaeler
Copy link
Contributor

gpiod seems to work fine on its own. My above example logical pin of 67 maps to gpiod chip2 pin3. The following works and gives a 0 or 1 depending on whether I connect the pin to GND or 3V3.

gpioget gpiochip2 3

The gpiochip number is most probably the culprit. In fact, by default the libgpiod driver in this repository defaults to zero.

Could you please try creating the libgpio driver passing 2 to the constructor?
https://github.com/dotnet/iot/blob/main/src/System.Device.Gpio/System/Device/Gpio/Drivers/Libgpiod/LibGpiodDriver.cs#L24

Then you pass this instance to the GpioController (the default PinNumberingScheme is PinNumberingScheme.Logical)
https://github.com/dotnet/iot/blob/main/src/System.Device.Gpio/System/Device/Gpio/GpioController.cs

If this still does not work, there may be a mismatch from the logical/physical pin number due to the PinNumberingScheme. You can try changing it. There may still be the need to create a mapping specific to this BeagleBon board.

Thanks

@FredMurphy
Copy link
Author

FredMurphy commented May 20, 2024

This works - using gpiod and referring to the pin as gpiochip2 pin 3, rather than the pin 67 that worked when 3.0.0 defaulted to SysFsDriver:

GpioController controller = new(PinNumberingScheme.Logical, new LibGpiodDriver(2));
GpioPin buttonPin = controller.OpenPin(3, PinMode.Input);

As we ascertained earlier, this also works:

GpioController controller = new(PinNumberingScheme.Logical, new SysFsDriver());
GpioPin buttonPin = controller.OpenPin(67, PinMode.Input);

I suppose we can put this down to a change in the default driver from SysFsDriver to LibGpiodDriver and the fact that the pin numbering then has to be changed to match. Not great that previously working code breaks at runtime with nothing but a NuGet package update though.

@raffaeler
Copy link
Contributor

raffaeler commented May 20, 2024

This works - using gpiod and referring to the pin as gpiochip2 pin 3, rather than the pin 67 that worked when 3.0.0 defaulted to SysFsDriver:

Great to hear that.

The mismatch between physical and logical pins depends on the absence of a specific driver like this one:
https://github.com/dotnet/iot/blob/main/src/devices/Gpio/Drivers/OrangePiZero2Driver.cs#L16

It may also be important to find a way to detect the board and pick the correct driver as it happens here:
https://github.com/dotnet/iot/blob/main/src/System.Device.Gpio/System/Device/Gpio/GpioController.cs#L470

@pgrawehr Am I forgetting anything else?

@FredMurphy Would you be interested in contributing to supporting the BeagleBone Black with a pull-request?

Thanks

@FredMurphy
Copy link
Author

@FredMurphy Would you be interested in contributing to supporting the BeagleBone Black with a pull-request?
I'd be happy to. It might take me a little while to get my head round how things are structured and fit it in with work commitments, etc. though.

@raffaeler
Copy link
Contributor

That would be great!
None of us in the Triage team has the board, but feel free to ask any doubts.
You can start looking at the existing drivers to figure out the general structure.

Thanks

@joperezr
Copy link
Member

[Triage]: We are trying to figure out what is the root cause of the segfault. Is it because when we PInvoke we do it with a chip that is wrong? Or is it because we are not catching an error returned by that PInvoke and trying to use the handle with the invalid handle? @raffaeler or @pgrawehr will try this out in the following week. If the issue is the former, we'll have to investigate and see how to fix but we won't block the release for this. If the issue is the latter, then we will fix the catching the error before our next release.

@joperezr joperezr added this to the v3.2.0 milestone May 23, 2024
@FredMurphy
Copy link
Author

FredMurphy commented May 23, 2024

I'm happy to do some testing if nobody has a BeagleBone Black, I'm guessing that the changed default driver meant I was unwittingly trying to use the LibGpiodDriver with chip 0 and pin 67

@joperezr
Copy link
Member

That would be super helpful, yes. You should be able to create the Driver yourself var driver = new LibGpiodDriver(2) to specify the chip 2, and then pass that in to the GpioController. If that works, then we'll confirm what the root cause is. From there, it would be good what is throwing the segfault, and check if we could catch some error in order to "fail in a better way" meaning with a better message.

@raffaeler
Copy link
Contributor

From the previous messages I understand that @FredMurphy already successfully tested that.

The only reason now to create a specific driver is to bake the pin mappings in it, which afaik requires talking to different gpio chips depending on the gpio being accessed.

@FredMurphy Could you please confirm or correct my statements?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Priority:0 Work that we can't release without
Projects
None yet
Development

No branches or pull requests

5 participants