gpiozero / gpiozero

A simple interface to GPIO devices with Raspberry Pi
https://gpiozero.readthedocs.io/
Other
1.9k stars 303 forks source link

lgpio pin factory is broken on RPi5 since kernel 6.6.45 #1166

Open HiassofT opened 3 weeks ago

HiassofT commented 3 weeks ago

Operating system: e.g. RPiOS Bookworm Python version: 3.11.2 Pi model: Pi 5 GPIO Zero version: 2.0.1 Pin factory used: lgpio

A recent change in the RPi kernel switched the gpiochip number on RPi5 to 0 (see https://github.com/raspberrypi/linux/pull/6144) but gpiozero still uses a hardcoded chip number of 4 on RPi5 (see https://github.com/gpiozero/gpiozero/blob/master/gpiozero/pins/lgpio.py#L66) and thus fails to find the GPIO pin

root@raspberrypi:~# python3
Python 3.11.2 (main, May  2 2024, 11:59:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import gpiozero
>>> b = gpiozero.Button(4)
/usr/lib/python3/dist-packages/gpiozero/devices.py:295: PinFactoryFallback: Falling back from lgpio: 'can not open gpiochip'
  warnings.warn(
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 408, in pin
    pin = self.pins[info]
          ~~~~~~~~~^^^^^^
KeyError: PinInfo(number=7, name='GPIO4', names=frozenset({'J8:7', 'BCM4', 'GPIO4', 4, 'WPI7', '4', 'BOARD7'}), pull='', row=4, col=1, interfaces=frozenset({'', 'gpio', 'dpi', 'spi', 'uart', 'i2c'}))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 103, in __call__
    self = super().__call__(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 412, in __init__
    super().__init__(
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 417, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 162, in __init__
    super().__init__(
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 243, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 79, in __init__
    super().__init__(pin, pin_factory=pin_factory)
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 549, in __init__
    pin = self.pin_factory.pin(pin)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 410, in pin
    pin = self.pin_class(self, info)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 101, in __init__
    GPIO.setup(self._number, GPIO.IN, self.GPIO_PULL_UPS[self._pull])
RuntimeError: Cannot determine SOC peripheral base address
Pierrot66657 commented 3 weeks ago

Bonjour, du coup comment je peux faire pour contrôler mon GPIO sur Raspberry Pi5 via Python, script bash ou via le terminal?

Merci

SVDouble commented 3 weeks ago

I used this monkey patch to work around the issue:

import gpiozero.pins.lgpio
import lgpio

def __patched_init(self, chip=None):
    gpiozero.pins.lgpio.LGPIOFactory.__bases__[0].__init__(self)
    chip = 0
    self._handle = lgpio.gpiochip_open(chip)
    self._chip = chip
    self.pin_class = gpiozero.pins.lgpio.LGPIOPin

gpiozero.pins.lgpio.LGPIOFactory.__init__ = __patched_init

This forces GPIO Zero to use chip 0 on RPi5 and resolves the problem.

HiassofT commented 3 weeks ago

Yes, something like this or just patching https://github.com/gpiozero/gpiozero/blob/master/gpiozero/pins/lgpio.py#L66 will work as a quick workaround on newer kernels but break stuff on older kernels so this isn't a solution.

Something like this https://github.com/waveform80/rpi-lgpio/commit/bb7ff0e2072eb15ad81c713201a2616e69c464a8 rpi-lgpio change needs to be done for gpiozero's lgpio usage, too

Pierrot66657 commented 2 weeks ago

Merci pour vos retours mais depuis la 6.6.47, tout est redevenu fonctionnel!

Milliways2 commented 5 days ago

gpiozero using the default lgpio fails on a Pi5 using Kernel 6.6.47+rpt-rpi-2712.

GPIO has moved to gpiochip0 but gpiozero uses gpiochip4.

Although the LGPIOFactory accepts chip as a parameter it ignores the value passed in and replaces it with 0.

gpiozero later checks the Revision Code and for BCM2712 replaces with gpiochip4.

To continue support for older kernel on Pi5 it would be better to test for the presence of /dev/gpiochip4.

pi-lemaire commented 4 days ago

Hi there, Indeed the last update on the Raspbery Pi 5 changed the GPIO chip ID, breaking my small flashing lights test script. The simple fix was to change the environment variable: export RPI_LGPIO_CHIP=0

1CM69 commented 4 days ago

Hi there, Indeed the last update on the Raspbery Pi 5 changed the GPIO chip ID, breaking my small flashing lights test script. The simple fix was to change the environment variable: export RPI_LGPIO_CHIP=0

I'm having this issue too, where exactly are you adding this fix too (more details needed for me the dummy) thanks

pi-lemaire commented 4 days ago

in the shell, before you call your python script you may also add it at the beginning of your python script, before importing the lgpio library:

import os os.environ['RPI_LGPIO_CHIP']='0'

at least this worked for me

L4wnmower commented 4 days ago

export RPI_LGPIO_CHIP=0

Issue does not seem fixable through this. Currently PWM-control is broken. Kernel 6.6.47+rpt-rpi-2712 bumped yesternight. Sadly

L4wnmower commented 4 days ago

Something like this waveform80/rpi-lgpio@bb7ff0e rpi-lgpio change needs to be done for gpiozero's lgpio usage, too

Do we know if this commit was ever merged in gpiozero or not? Waveform80 commented on July 18th he was checking to include this

pelwell commented 2 days ago

This ought to work as a minimally invasive patch:

diff --git a/gpiozero/pins/lgpio.py b/gpiozero/pins/lgpio.py
index 9fa8739..81e0298 100644
--- a/gpiozero/pins/lgpio.py
+++ b/gpiozero/pins/lgpio.py
@@ -63,7 +63,7 @@ class LGPIOFactory(LocalPiFactory):
     """
     def __init__(self, chip=None):
         super().__init__()
-        chip = 4 if (self._get_revision() & 0xff0) >> 4 == 0x17 else 0
+        chip = 4 if (self._get_revision() & 0xff0) >> 4 == 0x17 and os.path.exists('/dev/gpiochip4') else 0
         self._handle = lgpio.gpiochip_open(chip)
         self._chip = chip
         self.pin_class = LGPIOPin
XECDesign commented 2 days ago

This ought to work as a minimally invasive patch:

diff --git a/gpiozero/pins/lgpio.py b/gpiozero/pins/lgpio.py
index 9fa8739..81e0298 100644
--- a/gpiozero/pins/lgpio.py
+++ b/gpiozero/pins/lgpio.py
@@ -63,7 +63,7 @@ class LGPIOFactory(LocalPiFactory):
     """
     def __init__(self, chip=None):
         super().__init__()
-        chip = 4 if (self._get_revision() & 0xff0) >> 4 == 0x17 else 0
+        chip = 4 if (self._get_revision() & 0xff0) >> 4 == 0x17 and os.path.exists('/dev/gpiochip4') else 0
         self._handle = lgpio.gpiochip_open(chip)
         self._chip = chip
         self.pin_class = LGPIOPin

Should I pull that in to our package of it?

pelwell commented 2 days ago

Assuming it works, yes.

pelwell commented 2 days ago

Or there's this...:

$ sudo ln -s gpiochip0 /dev/gpiochip4
MarcLandis commented 2 days ago

Or there's this...:

$ sudo ln -s gpiochip0 /dev/gpiochip4

This works until a proper fix is published.

waveform80 commented 2 days ago

Sorry for my tardiness on this -- I've been intending to copy my fix from rpi-lgpio into gpiozero for this but I've been swamped with work things. Unfortunately I'm still swamped tonight (typing this in the middle of a meeting :) but I'll stick this on top of my list for tomorrow morning.

pelwell commented 2 days ago

There's an unofficial patch and a more general workaround about to go into our gpiozero package, so the pressure is off.

L4wnmower commented 2 days ago

Sorry for my tardiness on this -- I've been intending to copy my fix from rpi-lgpio into gpiozero for this but I've been swamped with work things. Unfortunately I'm still swamped tonight (typing this in the middle of a meeting :) but I'll stick this on top of my list for tomorrow morning.

Dave, thank you for the effort. Many thanks also to Phil for his help and to Matthias for catching the issue early on

usr-fritz commented 1 day ago

I found this article, which is also helpful, to fix the problem:

https://kofler.info/gpio-aerger-auf-dem-raspberry-pi-5/

lurch commented 1 day ago

There's an unofficial patch and a more general workaround about to go into our gpiozero package, so the pressure is off.

This "hacky patch" and "symlink workaround" (@XECDesign 's words :wink: ) are now both available on Raspberry Pi OS with an apt full-upgrade.