dotnet / iot

This repo includes .NET Core implementations for various IoT boards, chips, displays and PCBs.
MIT License
2.12k stars 574 forks source link

PinNumberingScheme.Board is broken #2326

Open FredMurphy opened 2 weeks ago

FredMurphy commented 2 weeks ago

Describe the bug

Using PinNumberingScheme.Board seems broken. I had a problem when writing a BoagleBoard driver, and looked at the RaspberryPi driver to see how it was handled there. It seems that trying to use PinNumberingScheme.Board on the Raspberry Pi - and probably any board - doesn't work.

Steps to reproduce

This code fails with System.ArgumentException: The specified pin number is invalid. (Parameter 'pinNumber'):

GpioController controller = new(PinNumberingScheme.Board, new RaspberryPi3Driver());

GpioPin pin1 = controller.OpenPin(38, PinMode.Output);

PinValue pinValue = pin1.Read();
Console.WriteLine($"value: {pinValue}");

This code - using Logical numbering to refer to the same pin works fine:

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

GpioPin pin1 = controller.OpenPin(20, PinMode.Output);

PinValue pinValue = pin1.Read();
Console.WriteLine($"value: {pinValue}");

Both snippets of code refer to the same pin - logical pin 20 which is pin 38 of the Pi 3 header

Expected behavior The pin value should be read

Actual behavior

Unhandled exception. System.ArgumentException: The specified pin number is invalid. (Parameter 'pinNumber')
   at System.Device.Gpio.Drivers.RaspberryPi3LinuxDriver.ValidatePinNumber(Int32 pinNumber) in C:\Users\Fred\source\repos\iot\src\System.Device.Gpio\System\Device\Gpio\Drivers\RaspberryPi3LinuxDriver.cs:line 65
   at System.Device.Gpio.Drivers.RaspberryPi3LinuxDriver.Read(Int32 pinNumber) in C:\Users\Fred\source\repos\iot\src\System.Device.Gpio\System\Device\Gpio\Drivers\RaspberryPi3LinuxDriver.cs:line 171
   at System.Device.Gpio.Drivers.RaspberryPi3Driver.Read(Int32 pinNumber) in C:\Users\Fred\source\repos\iot\src\System.Device.Gpio\System\Device\Gpio\Drivers\RaspberryPi3Driver.cs:line 199
   at System.Device.Gpio.GpioPin.Read() in C:\Users\Fred\source\repos\iot\src\System.Device.Gpio\System\Device\Gpio\GpioPin.cs:line 58
   at Program.<Main>$(String[] args) in C:\Users\Fred\source\repos\gpiotestpi\Program.cs:line 28

Some Investigation I've tracked down what I believe to be the issue.

When the pin is created, the board value 38 is correctly mapped to the logical value of 20 in RaspberryPi3LinuxDriver.ConvertPinNumberToLogicalNumberingScheme(). However, from this point on, the pin number of the GpioPin remains 38. When the Read() operation occurs, the driver treats the pin number as if it was a logical pin 38 and this is not valid. (If the Board pin number was below 28, then the Read() operation would potentially read the wrong pin instead of throwing an exception.) The GpioPin has no concept of whether it was created as a Board or Logical pin.

A potential solution would be for a GpioPin to contain both the pin number used to refer to it and also the pin number used by the driver. There's some overlap with concepts in the Virtual Contoller and Pin code in https://github.com/dotnet/iot/pull/2180, but it's not quite the same.

Versions used This is running using the latest code from the main branch compiled locally. Tested on a Pi3 running latest 64-bit OS.

pgrawehr commented 3 days ago

Honestly, I think we should drop support for different PinNumberingScheme's alltogether. It works only for very few boards (namely the RPI3 and 4), and even then only sometimes (as this ticket shows) and has little practical use. Everybody else is working with the logical numbers.