Iot: Clarify board support

Created on 7 Sep 2020  路  6Comments  路  Source: dotnet/iot

Describe the bug

At the moment, it isnt clear from the README what versions of Raspberry PI are supported. The driver files indicate Pi3 and above but it isn't clear.
It looks like on PI2, it should be able to use libgpiod or sysfs but that isn't clear.
If that's indeed the case, then maybe clarify the build process (for ex. right now, I'm compiling on my desktop for linux-arm. If I have to rely on libgpiod-dev, then does that mean that cross compiling is ruled out and I have to build on the RPi?

For context: I'm trying to connect to a NRF24L01 on a Rpi2 B+. As of now, my code compiles and seems to be failing silently (no errors, but no pin ops are working)

Expected behavior

  1. README or Docs clearly list out supported boards.
  2. Should native libraries be required, then clarify if cross compiling is still an option.
  3. A sample project would be terrific.

Describe what did you expect to happen

Actual behavior

Unable to find if a Rpi2 is actually supported or not. Linux drivers folder only says Rpi3 and above in code comments.

Detection behavior in GpioController.cs seems to only checks for BCM2385 in /proc/cpuinfo which from this page https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md says that all PIs will report BCM2385

image

Versions used

Add following information:

  • dotnet --info on the machine being used to build
.NET Core SDK (reflecting any global.json):
 Version:   3.1.401
 Commit:    39d17847db

Runtime Environment:
 OS Name:     neon
 OS Version:  20.04
 OS Platform: Linux
 RID:         linux-x64
 Base Path:   /usr/share/dotnet/sdk/3.1.401/
  • dotnet --info on the machine where app is being run (not applicable for self-contained apps)
    using self-contained apps

  • Version of System.Device.Gpio package
    nuget System.Device.Gpio 1.1.0-prerelease.20276.1 prerelease

bug untriaged

Most helpful comment

I think what should come out of this issue is some kind of doc explaining on what's supported and that's not a simple answer of "we support it" or "not supported".

But to give some answer here. There are couple of levels of what's supported and what's not:
Iot.Device.Bindings to the most part (with exception of few bindings) is not depending on any OS or board. As long as you pass in I2cDevice/SpiDevice/GpioController/PwmChannel the device should just work. I.e. if you use Ft4222 almost whole Iot.Device.Bindings will work on any Linux/Windows/OSX (minus PWM channel which you can get by connecting a specific I2C device which exposes PwmChannels so technically you can get anything to work with that one dongle)

There are two pieces of System.Device.Gpio which are unfortunately put in one place (see: https://github.com/dotnet/iot/issues/1182):

  • core part: abstraction which is not depending on anything (abstract classes defining on what's core and what Iot.Device.Bindings depends on)
  • implementations which are closely related to board/OS/...

Now let's expand on the implementations in System.Device.Gpio or GPIO specifically (I2C/SPI are relatively painless):

By default you will get auto-detection logic which will pick the best driver implementation for your board - the problem is this logic hard to get right so we've had many issues with that and still have some and the most reliable way is to actually use driver directly (but then you might be limited to building for a specific board)

  • you can get basic support from SysFs implementation on any Linux but it will slow and some features might not work
  • LibGpiod - as long as it's installed on your Linux it's much faster than SysFs implementation but if it's not available it will not get used - that's probably the most generic solution for Linux with both speed and compat in mind
  • Windows 10 IoT Core implementation - works on some boards (i.e. Raspberry Pi 3, Hummingboard) and reasonably fast
  • direct/memory implementation - implementation which relies on memory layout for very specific board - if you use this driver on the wrong board the very wrong things can happen. It requires reading parts of the spec for this specific board but you can get the best perf with this - we have implementation for Pi3, Pi4 and couple other

All 6 comments

Related: #1145 The board detection is currently broken.

Would it be possible for you to test whether the Pi3 driver works on the Pi2 if you explicitly load it?

I tried with explicit loading - doesn't seem to make a difference

let Connect packetSize (radio:RadioConfig) (cancellationToken:CancellationToken) =
        task {
            try
            let gpioDriver = new RaspberryPi3Driver()
            let controller = new GpioController(PinNumberingScheme.Logical, gpioDriver);
            let settings = SpiConnectionSettings(radio.SpiBusId, 0)
            settings.ClockFrequency <- Nrf24l01.SpiClockFrequency
            settings.Mode <- Nrf24l01.SpiMode
            let device = SpiDevice.Create(settings);
            let nrf = new Nrf24l01(device, radio.ChipEnable, radio.Irq, packetSize, 46uy, OutputPower.N00dBm, DataRate.Rate250Kbps,
                                        PinNumberingScheme.Logical, controller)
            radio.RxPipeBytes |> Option.map (fun v ->
                                                nrf.Pipe0.Address <- v
                                                printfn "Set rx address %A" v
                                            ) |> ignore
            nrf.Channel <- 46uy
            nrf.DataReceived.Add (recieveHandler radio nrf)
            Thread.Sleep(2000)
            printRadioDetails nrf
            // more code - not relevant.

No exception thrown but when I read values off the chip, I get only defaults/unset values. Python code with the same connections works - so I know that this isn't a jiggly wire.

That's weird, looks more like a problem with the SpiDevice. This typically happens when the CS line is not properly set (there are some conceptual problems with the use of it and whether it is explicitly controlled or implicitly by the spi driver). Assuming the radio is the only attached device, can you try hardwiring the CS line to ground (or 3.3V, not sure what this device needs) with something like an 1k resistor?

Hmm - I switched to a RPi 4 with the same pin connections the radio responds to commands - so doesn't that rule out any pin problems?

Oh - and I should have stated this before - but somehow missed it - even on the RPi2, my python version based on pyNRF ( https://github.com/nRF24/RF24) has been working for many months... so that definitely rules out hw issues.

The problem I mention above is not directly a HW issue, but one about how the SPI driver is being used. But since switching to a PI4 works fine, this looks really more like a problem of the implementation. I don't know why the SPI access should be different between an PI2 and a PI4. Maybe this requires a different driver usage or something.

I think what should come out of this issue is some kind of doc explaining on what's supported and that's not a simple answer of "we support it" or "not supported".

But to give some answer here. There are couple of levels of what's supported and what's not:
Iot.Device.Bindings to the most part (with exception of few bindings) is not depending on any OS or board. As long as you pass in I2cDevice/SpiDevice/GpioController/PwmChannel the device should just work. I.e. if you use Ft4222 almost whole Iot.Device.Bindings will work on any Linux/Windows/OSX (minus PWM channel which you can get by connecting a specific I2C device which exposes PwmChannels so technically you can get anything to work with that one dongle)

There are two pieces of System.Device.Gpio which are unfortunately put in one place (see: https://github.com/dotnet/iot/issues/1182):

  • core part: abstraction which is not depending on anything (abstract classes defining on what's core and what Iot.Device.Bindings depends on)
  • implementations which are closely related to board/OS/...

Now let's expand on the implementations in System.Device.Gpio or GPIO specifically (I2C/SPI are relatively painless):

By default you will get auto-detection logic which will pick the best driver implementation for your board - the problem is this logic hard to get right so we've had many issues with that and still have some and the most reliable way is to actually use driver directly (but then you might be limited to building for a specific board)

  • you can get basic support from SysFs implementation on any Linux but it will slow and some features might not work
  • LibGpiod - as long as it's installed on your Linux it's much faster than SysFs implementation but if it's not available it will not get used - that's probably the most generic solution for Linux with both speed and compat in mind
  • Windows 10 IoT Core implementation - works on some boards (i.e. Raspberry Pi 3, Hummingboard) and reasonably fast
  • direct/memory implementation - implementation which relies on memory layout for very specific board - if you use this driver on the wrong board the very wrong things can happen. It requires reading parts of the spec for this specific board but you can get the best perf with this - we have implementation for Pi3, Pi4 and couple other
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mskuratowski picture mskuratowski  路  3Comments

krwq picture krwq  路  5Comments

alex182 picture alex182  路  6Comments

Ellerbach picture Ellerbach  路  4Comments

krwq picture krwq  路  3Comments