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

Update Board info for Pi 5 #2145

Merged
merged 9 commits into from
Oct 19, 2023
Merged

Update Board info for Pi 5 #2145

merged 9 commits into from
Oct 19, 2023

Conversation

pjgpetecodes
Copy link
Contributor

@pjgpetecodes pjgpetecodes commented Oct 8, 2023

The Board info for the new Raspberry Pi 5 is missing.

Microsoft Reviewers: Open in CodeFlow

@ghost ghost added the area-System.Device.Gpio Contains types for using general-purpose I/O (GPIO) pins label Oct 8, 2023
Comment on lines 144 to 145
RaspberryBoardInfo.Model.RaspberryPi5 or
RaspberryBoardInfo.Model.RaspberryPi400 => new RaspberryPi3LinuxDriver(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GPIO Hardware of the RPi5 seems to be quite different from previous versions. Is the RaspberryPi3LinuxDriver really working correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point... I'll see if I can build it all locally and try it on my Pi5 and see what's what. :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read the pre-release datasheet for the new custom IC called RP1 which is new to the RPi5.
It governs all the I/O, serial ports, I2C, SPI, PWM, video and USB communications. The HW architecture is very different from the previous boards even if they apparently maintained the external pin compatibility (They also use MUXes for the I/O, meaning that you can remap the ping assignments).

The main point about that IC is to offload the communications from the main processor to support low-power communication while the rest of the board is in sleep mode. It also supports 1.8V levels but they have to be carefully used because, once set any voltage higher than 1.8V can damage the board.

Said that, the libgpiod could be enough to decouple the new functionalities but since there are more features, it will probably deserve a new separate RasperryPi5LinuxDriver to support them.

I don't have a new RPi5, but any test you could do is more than welcome :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a recommended workflow for development / debugging for GPIO? Are we able to debug directly on the Pi? @pgrawehr @raffaeler ...

Copy link
Contributor

@raffaeler raffaeler Oct 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a recommended workflow for development / debugging for GPIO? Are we able to debug directly on the Pi?

The point here is that there is no direct access for the C# code to the GPIO, therefore debugging the GPIO access does not help much. The dotnet/iot library provides two "drivers": sysfs (GPIOs mapped on files) and libgpiod. They are just the C# code accessing the file system or the libgpiod api.

  • sysfs is the simpler (and slower) way. If you can successfully access the GPIOs using the default tools, it should work from dotnet/iot as well. Even if this works, it is not the best solution as file mapped GPIOs have a number of issues.
  • libgpiod provides access to the GPIOs via APIs. I understood that there is no current version for libgpiod for the RPi5. In this case there is nothing you can do from dotnet. A soon as the Raspberry Foundation should provide it, we will have to see if the APIs are exactly the same or not.

Alternate solutions are:

  • fork libgpiod and provide support for the RPi5, you should download and implement the RP1 specifications inside the libgpiod source code. This step is definitely not trivial.
  • implement the RP1 specs directly in C# bypassing libgpiod. It is doable but, again, not trivial.
    AFAIK we never did this for any other board.

P.S. As I mentioned in the previous message the RP1 specs have a number of new features that may not fit in the current libgpiod API. This is why I believe we need something different on the C# wrapper side as well.

Copy link
Contributor

@pgrawehr pgrawehr Oct 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pjgpetecodes There are two options to work with the library:

Variant 1

  • Check out the repo on the PC, build
  • Create / update an example
  • Publish it for arm64 and copy to the pi
  • Run on the Pi, use SSH for remote debugging, if needed

Variant 2

  • Checkout on the PI
  • Build on the Pi
  • Execute the examples / Integration tests

I'm normally going with 1, unless I'm running the GPIO testbench. Then I check out on the Pi and run dotnet test System.Device.Gpio.sln. (For the GPIO tests to work, you need to have pins 5 and 6 connected with a resistor)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing I'll have to clone, switch to my working branch, and build this on the pi, then manually add the system.device.gpio dlls to my project to begin with...?

You can just cross-compiling everything on Windows and then copy to the RPi5. Your test code could be any basic binding. I suggest you to directly reference the dotnet/iot libraries so that you recompile the libraries as well.

This is the typical way to cross-compile using self-contained to avoid any dependency and being able to sync the sources as suggested by Patrick.

  • Release vs Debug: pick Debug if you want to avoid optimizations and sync the sources
  • linx-arm vs linux-arm64. This depends on the OS on the RPi
dotnet deploy -c Release -r linux-arm --self-contained=true

Please note that the pdbs will point to sources that you just compiled.

In any case, if you just want to make a test, you don't need to debug. You can just deploy the release version as self-contained and see if if works (you can write on the console some message to have detailed info).

HTH

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arghhh... My comments above (#2145 (comment)) were stuck in pending... Apologies @raffaeler and @pgrawehr ... Thanks for the help mind you!

As you can see it seems to work at a high level at least...

Need to figure out the best way to move forward now eh!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, that's good news, at least we have one driver that works for the Pi5. Can you (just for reference) do the same test with using the RaspberryPi3Driver and the SysFsDriver?

PinNumberingScheme.Board is only supported with the RaspberryPi3Driver, because it needs to know the mapping from the logical pins to the physical pins. Because most boards and drivers don't support that either, we've mostly given up support for that anyway and stick to the logical numbering.

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So...

With the original code;

  • RaspberryPi3Driver driver gives Not a supported Raspberry Pi type: (Fairly obviously)`
  • SysFSDriver just works!

With Raspberry Pi 5 added in the boardInfo.BoardModel switch in the CreateInternalRaspberryPi3LinuxDriver function, creating the RaspberryPi3Driver and passing it into the GpioController gives An unhandled exception of type 'System.IO.IOException' occurred in System.Device.Gpio.dll: 'Error 13 Initializing the Gpio driver'

Interestingly, doing a sudo dotnet run, gives Error 22 instead of Error 13 (But still System.IO.IOException)... Not sure of the difference.

Also, doing an ls /dev/gpiomem (as I see that mentioned in the RaspberryPiLinuxDriver.cs) gives No such file or directory, same with sudo ls /dev/gpiomem.

sudo adduser <myusername> gpio gives adduser: The user '<myusername>' is already a member of 'gpio'

ls /dev/mem gives:

crw-r----- 1 root kmem 1, 1 Oct 10 21:11

This is all no doubt because the new RP1 IO chip does GPIO entirely differently.

For reference, standing up something like a PWM Servo means that we can't pass in which GPIO Driver we use, so this needs to be done behind the scenes I guess.

I mean, ideally we'd write a driver specifically for this, but I'm not sure what's involved in that of course.

@@ -141,6 +141,7 @@ RaspberryBoardInfo.Model.RaspberryPi3BPlus or
RaspberryBoardInfo.Model.RaspberryPiZeroW or
RaspberryBoardInfo.Model.RaspberryPiZero2W or
RaspberryBoardInfo.Model.RaspberryPi4 or
RaspberryBoardInfo.Model.RaspberryPi5 or
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Triage] Please remove this line to avoid using that driver for Raspberry Pi 5 because it's not fully working and as a next step right after this PR consider creating a separate PR/issue for Raspberry 5 driver.

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks... Done... I've also added the Pi5 Board reference to the GpioController class along with a switch choosing the LibGpiodDriver when on windows.

However, I guess this will only be used if running on Windows 10 or the now (pretty much) defunct Windows 10 IoT?

Do let me know if you think this should be removed though?

I'll definitely go with a new PR for for any work on a Pi5 driver.

Add Pi 5 OProduct to GpioDriver.
@@ -506,6 +507,11 @@ private static GpioDriver GetBestDriverForBoardOnWindows()
return new RaspberryPi3Driver();
}

if (baseBoardProduct == RaspberryPi5Product || baseBoardProduct.StartsWith($"{RaspberryPi5Product} "))
{
return new LibGpiodDriver();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be in the Linux method? AFAIK there's no supported windows version for rpi at this time and libgpiod is not for windows.

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I absolutely agree... Only, that function doesn't detect the board type nor does this class for Unix, where that code is within the RaspberryPi3Driver class sadly...

So, I figure, if I'm going to need to bring that code in to this class, or modify the RaspberryPi3Driver class, then I should submit a new PR for that as @krwq suggests perhaps?

Absolutely happy to take some direction though!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, let's keep this simple. As you've already noticed above, Windows isn't really supported any more (the defunct Windows 10 Iot is only supported on the Raspberry Pi 3, and for Windows 11, there are no officially supported versions for any Pi at all at this time).

So for now, move this code to GetBestDriverForLinux() so at least we get a valid driver there. If I understand correctly, you need to do new LibGpiodDriver(4) though. After this, I would say this PR is ready to get merged.

After that, investigation is needed onto the next steps. We probably need a fully new RaspberryPi5Driver then, that handles the GPIO device for the new RP1 chip. Don't forget to take a look at the RaspberryPiBoard class, which contains the logic to program the mux for the different GPIO alternate functions. This logic will likely also change.

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok done...

(Ignoring the brain farts of commits - Amazing how much trouble an errant semi-colon can cause - We can squash)... It works...

20231013_124046

Of course, if you use a Pin Numbering scheme of Board instead of Logical it throws a Platform Not Supported error (I like the board numbering scheme personally).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried PWM and a Servo out of interest and it doesn't seem to work interestingly... I wonder is this a limitation of the LibGpioDriver?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Python and gpiozero I get jittery servo movement from BCM18... But there's movement...

Could you re-try with C# after running the Python code?

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing sadly... gpiozero, while jittery, works... I'm sure it's bit bashed PWM in gpiozero by default given that its jitterry and gives this warning;

/usr/lib/python3/dist-packages/gpiozero/output_devices.py:1509: PWMSoftwareFallback: To reduce servo jitter, use the pigpio pin factory.See https://gpiozero.readthedocs.io/en/stable/api_output.html#servo for more info warnings.warn(PWMSoftwareFallback(

No movement at all for .NET... Which will be trying to use Hardware PWM.

With that in mind... When I try software PWM from the bindings it works... But not ideal...

using SoftwarePwmChannel pwmChannel1 = new SoftwarePwmChannel(18, 50, 0.5, true);
using ServoMotor servoMotor1 = new ServoMotor(
                pwmChannel1,
                180,
                900,
                2100);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is probably some new initialization stuff needed to make it work on the RPi5 but it's hard to say.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have a dig around and a play.... See what I can turn up...

Copy link
Contributor Author

@pjgpetecodes pjgpetecodes Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW... I tried adding the following to the config.txt file and rebooting;

dtoverlay=pwm-2chan,pin=18,func=2,pin2=13,func2=4

But, no dice.

Worth trying eh.

I've also asked the question around Pi 5 docs in the Raspberry pi Forums, see if there's some more info out there other than the RP1 Datasheet.

@pjgpetecodes
Copy link
Contributor Author

Looks like this is stuck for some reason... Not sure why...

@raffaeler
Copy link
Contributor

Looks like this is stuck for some reason... Not sure why...

No worries, we just have to review the changes this week during the triage.

@pgrawehr
Copy link
Contributor

/azp run dotnet.iot

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@pjgpetecodes
Copy link
Contributor Author

Looks like this is stuck for some reason... Not sure why...

No worries, we just have to review the changes this week during the triage.

Ahhh... Gotcha... Makes sense... Thanks.

I thought I'd done something wrong!

Interestingly it looks like something failed with the build though?

@pgrawehr
Copy link
Contributor

@pjgpetecodes No, it's all fine with the build now. Because you're a first-time contributor, the build doesn't start automatically, though. Therefore I had to force it to run.

@raffaeler
Copy link
Contributor

Interestingly it looks like something failed with the build though?

Yes, a couple of builds failed because there are random (known) issues happening in the pipelines that makes some tests fail. The issues on the pipeline will be hopefully fixed soon.
Anyway, I forced re-running the failed platforms and now they are all green.

@pjgpetecodes
Copy link
Contributor Author

Wahoo... Awesome... Thanks!

In the meanwhile... I'm doing some learning on how the current driver works and how to create a new one for the Pi 5!

@krwq krwq merged commit f7cbec0 into dotnet:main Oct 19, 2023
9 checks passed
@pgrawehr pgrawehr added this to the v3.1.0 milestone Nov 9, 2023
@raffaeler raffaeler mentioned this pull request Nov 22, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Dec 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Device.Gpio Contains types for using general-purpose I/O (GPIO) pins
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants