adafruit / Adafruit_Blinka

Add CircuitPython hardware API and libraries to MicroPython & CPython devices
https://learn.adafruit.com/circuitpython-on-raspberrypi-linux
MIT License
453 stars 340 forks source link

RPI 5 - python library piod: 'Chip' has no attribute 'OPEN_BY_NUMBER' #740

Closed jasperjonker closed 9 months ago

jasperjonker commented 10 months ago

Board Name

Raspberry Pi 5

Steps

When following the following steps on the raspberry pi 5:

pyenv virtualenv system test
pyenv shell test
pip install --upgrade Adafruit-Blinka

and then run blinka.py:

import board
import digitalio
import busio

print("Hello blinka!")

# Try to great a Digital input
pin = digitalio.DigitalInOut(board.D4)
print("Digital IO ok!")

# Try to create an I2C device
i2c = busio.I2C(board.SCL, board.SDA)
print("I2C ok!")

# Try to create an SPI device
spi = busio.SPI(board.SCLK, board.MOSI, board.MISO)
print("SPI ok!")

print("done!")

I get the following error:

ImportError: libgpiod Python bindings not found, please install and try again! See https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/master/libgpiod.sh

Installing gpiod: pip install --upgrade gpiod

❯ python blinka.py
Traceback (most recent call last):
  File "/home/utb/Downloads/blinka.py", line 1, in <module>
    import board
  File "/home/utb/.pyenv/versions/test2/lib/python3.11/site-packages/board.py", line 47, in <module>
    from adafruit_blinka.board.raspberrypi.raspi_5b import *
  File "/home/utb/.pyenv/versions/test2/lib/python3.11/site-packages/adafruit_blinka/board/raspberrypi/raspi_5b.py", line 6, in <module>
    from adafruit_blinka.microcontroller.bcm2712 import pin
  File "/home/utb/.pyenv/versions/test2/lib/python3.11/site-packages/adafruit_blinka/microcontroller/bcm2712/pin.py", line 8, in <module>
    D0 = Pin((4, 0))
         ^^^^^^^^^^^
  File "/home/utb/.pyenv/versions/test2/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py", line 36, in __init__
    self._chip = gpiod.Chip(str(pin_id[0]), gpiod.Chip.OPEN_BY_NUMBER)
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Chip' has no attribute 'OPEN_BY_NUMBER'

Description

1) The link provided to the installer script for libgpiod is not existing anymore. It should be https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/main/libgpiod.py 2) I tried building the python bindings/wheels from source of gpiod, which raises the same error as above. Note: I have libgpiod-dev, libgpiod2, gpiod, python3-libgpiod installed. 3) The script relies on sudo pip install ... which is not supported in Debian 12 systems. The latest Raspberry Pi OS is on Debian 12 and throws an error:

Blinka error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.

    For more information visit http://rptl.io/venv

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

One could change the pip_command to pip3 install --upgrade --break-system-packages, but this might not be such a good idea.

Additional information

No response

makermelissa commented 10 months ago

You will want to run sudo apt install python3-libgpiod rather than pip install gpiod. You can follow the guide here: https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi

The automated installer should install this for you and the manual install instructions also have you install the correct version.

makermelissa commented 10 months ago

Ok, I can take a look.

makermelissa commented 10 months ago

Tested and it works great by following instructions. You will need to uninstall the python library gpiod for it to use libgpiod. Just use pip uninstall gpiod.

Leaving this open for the moment as there are a couple of possible improvements:

  1. Either have the script attemp to remove the python package gpiod
  2. or make it so it can be run by either (it was working as of a few weeks ago) library.

I'd prefer the second option, but I think it will run slower than the libgpiod option, so it may not be preferable. I may do some testing similar to https://adafruit-playground.com/u/MakerMelissa/pages/comparing-libgpiod-and-gpiozero-speeds-on-the-raspberry-pi-5 and make a decision off of that.

bleugreen commented 10 months ago

Following the guide linked above (on a RPi 5) leads me to

Traceback (most recent call last):
  File "/home/dev/blinkatest.py", line 1, in <module>
    import board
  File "/home/dev/.venv/crec/lib/python3.11/site-packages/board.py", line 47, in <module>
    from adafruit_blinka.board.raspberrypi.raspi_5b import *
  File "/home/dev/.venv/crec/lib/python3.11/site-packages/adafruit_blinka/board/raspberrypi/raspi_5b.py", line 6, in <module>
    from adafruit_blinka.microcontroller.bcm2712 import pin
  File "/home/dev/.venv/crec/lib/python3.11/site-packages/adafruit_blinka/microcontroller/bcm2712/pin.py", line 5, in <module>
    from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
  File "/home/dev/.venv/crec/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py", line 8, in <module>
    raise ImportError(
ImportError: libgpiod Python bindings not found, please install and try again! See https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/master/libgpiod.sh

I have verified that python3-libgpiod is installed, and have tried both the script and the manual install but I'm getting the same error for both. Removing libgpiod and installing the Python module leads to the OPEN_BY_NUMBER error, which feels closer than the results of the install script.

EDIT: Tried starting from scratch on a clean os, after running the script I got:

Settings take effect on next boot.

REBOOT NOW? [Y/n] 
Reboot started...
sh: 1: reboot: not found

Which is odd

makermelissa commented 10 months ago

Which OS/Version of the OS are you running? Also, what are the results of the command sudo apt list | grep python3-libgpiod?

graemeok commented 9 months ago

After sudo -E env PATH=$PATH raspi_blinka.py, I can run the blinkatest, but I still can't draw to the piTFT. Has anyone been able to get adafruit-circuitpython-rgb-display working on Pi5? I get an error in libgpiod_pin.py, line 98 : self._line_request => [Errno 16] Device or resource busy with a 2.8"piTFT. apt list above gives : python3-libgpiod/stable,now 1.6.3-1+b3 arm64 [installed]

rreichenbach commented 9 months ago

I also get the "Device or resource busy" error trying to initialize a TFT display, but since it can be reproduced with just the following python lines, I'm thinking it's a problem with the digitalio lib on pi5/bookworm regardless if it's being used with a TFT. Note that the problem doesn't occur for all pins (eg. D5) but does for CE0 and CE1 which are needed for initializing a display. I do have SPI enabled (via config.txt, verified via raspi-config) but don't rule out other possible system configuration which may be needed for SPI on pi5.

>>> import board, digitalio
>>> digitalio.DigitalInOut(board.D5)
<digitalio.DigitalInOut object at 0x7fff5250e310>
>>> digitalio.DigitalInOut(board.CE0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.11/dist-packages/digitalio.py", line 183, in __init__
    self.direction = Direction.INPUT
    ^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/digitalio.py", line 213, in direction
    self._pin.init(mode=Pin.IN)
  File "/usr/local/lib/python3.11/dist-packages/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py", line 98, in init
    self._line.request(
OSError: [Errno 16] Device or resource busy
makermelissa commented 9 months ago

Make sure the OS doesn't have drivers using gpio or spi bus.

graemeok commented 9 months ago

I just tried "pip install adafruit-circuitpython-rgb-display" with piOS lite - bookworm on pi5 as others had suggested this might work. It didn't, same error as rreichenbach above.

The circuit python environment reports the following: pi4 board.CE0 = 8 board.D25 = 25

pi5 board.CE0 = (4, 8) board.D25 = (4, 25)

I guess this is sort of consistent with the 'i2cdetect -y 1' reports pi4 spi0 CS1 spi0 CS0 are on gpiochip0

pi5 spi0 CS1 spi0 CS0 are on gpiochip4

I don't have the knowledge required to dig into circuit python, so the following suggestion is one made in ignorance, so please excuse. maybe the issue is with circuit python assuming for the pi5 that the CS1 & CS0 are on gpiochip0

rreichenbach commented 9 months ago

To rule out any possible quirks of my install, I've done two fresh Bookworm 64-bit installs on a pi5, one lite, one full. Both incur the same "Device or resource busy" error when initializing the CE0 and CE1 pins.

The only thing I did after first boot is installed Blinka via these instructions: https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi

Then ran python and try to initialize CE0 or CE1.

(env) pistomp@pistomp:~ $ python3

Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> import board, digitalio
>>> digitalio.DigitalInOut(board.CE0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pistomp/env/lib/python3.11/site-packages/digitalio.py", line 183, in __init__
    self.direction = Direction.INPUT
    ^^^^^^^^^^^^^^
  File "/home/pistomp/env/lib/python3.11/site-packages/digitalio.py", line 213, in direction
    self._pin.init(mode=Pin.IN)
  File "/home/pistomp/env/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py", line 98, in init
    self._line.request(
OSError: [Errno 16] Device or resource busy

The DigitalInOut constructor fails for CE0 (same as D8) and CE1 (D7), but works for all the other pins (0 thru 6, and 9 thru 27))

It seems odd to me that DigitalInOut always creates a pin as an Input. There's no flag for the constructor to create an output. You instead create it (as an input) then change it using the direction() or switch_to_output() method. Still that doesn't seem to be the cause of the error because I can use pinctrl to make any other pin an output and yet the DigitalInOut() constructor works fine on those. There is just something special about the CE0/D8 and CE1/D7 on pi5 boards.

rreichenbach commented 9 months ago

Ok, the gpioinfo command appears to be showing the issue. Used pins. See below.

Anyone know how to determine which process or driver might be causing those to be "used"?

This is a fresh install with no customization and only Blinka installed. Disabling the only dtoverlay in config.txt didn't help. I suppose I'll just start shutting down services and re-testing, hoping something will release those pins.

gpiochip4 - 54 lines:
    line   0:      "ID_SD"       unused   input  active-high 
    line   1:      "ID_SC"       unused   input  active-high 
    line   2:       "PIN3"       unused   input  active-high 
    line   3:       "PIN5"       unused   input  active-high 
    line   4:       "PIN7"       unused   input  active-high 
    line   5:      "PIN29"       unused   input  active-high 
    line   6:      "PIN31"       unused   input  active-high 
    line   7:      "PIN26"   "spi0 CS1"  output   active-low [used]
    line   8:      "PIN24"   "spi0 CS0"  output   active-low [used]
    line   9:      "PIN21"       unused   input  active-high 
    line  10:      "PIN19"       unused   input  active-high 
    line  11:      "PIN23"       unused   input  active-high 
    line  12:      "PIN32"       unused   input  active-high 
    line  13:      "PIN33"       unused   input  active-high 
    line  14:       "PIN8"       unused   input  active-high 
    line  15:      "PIN10"       unused   input  active-high 
    line  16:      "PIN36"       unused   input  active-high 
    line  17:      "PIN11"       unused   input  active-high 
    line  18:      "PIN12"       unused   input  active-high 
    line  19:      "PIN35"       unused   input  active-high 
    line  20:      "PIN38"       unused   input  active-high 
    line  21:      "PIN40"       unused   input  active-high 
    line  22:      "PIN15"       unused   input  active-high 
    line  23:      "PIN16"       unused   input  active-high 
    line  24:      "PIN18"       unused   input  active-high 
    line  25:      "PIN22"       unused   input  active-high 
    line  26:      "PIN37"       unused   input  active-high 
    line  27:      "PIN13"       unused   input  active-high 
    line  28: "PCIE_RP1_WAKE" unused input active-high 
    line  29:   "FAN_TACH"       unused   input  active-high 
    line  30:   "HOST_SDA"       unused   input  active-high 
graemeok commented 9 months ago

I've connected the piTFT to both a PI4 & a PI5.

I compared gpioinfo on PI4 as well as PI5. on both, the following is reported PIN26 SPI_CE1_N spi0 CS1 output active_low [used] PIN24 SPI_CE0_N spi1 CS0 output active_low [used]

on PI4 this setting is on gpiochip0

on PI5 this setting is on gpiochip4

if you disable SPI in Raspberry Pi Configuration, then PIN26, 24 become unused.

i'm going to dig a little deeper into libgpiod_pin.py

graemeok commented 9 months ago

wouldn't it have made more sense for the raspberry foundation to have the PI5 maintaine all the PI4 gpiochip0 mappings to PI5 gpiochip0 mappings and any new internal mappings onto gpiochip1,2,3,4?

makermelissa commented 9 months ago

I was able to reproduce the issue. Good catch on the gpioinfo. It shouldn't be giving a device busy with SPI enabled, but maybe it's a permissions thing or a libgpiod thing.

graemeok commented 9 months ago

apologies if this has already been pointed out, but just a sanity check here. which version of gpiod should I be using? apt install gpiod => ver 1.6.3 pip install gpiod => ver 2.1.3

rreichenbach commented 9 months ago

Thanks for looking into this @makermelissa

@graemeok, I can't answer your "should I be using" question, but it does seem suspicious that the version you'd get via pip is quite a bit newer.

@makermelissa did suggest above to pip uninstall gpiod. From my own experience, when I have gpiod installed, I get the OPEN_BY_NUMBER error reported originally for this issue because 'import board' fails. When I uninstall gpiod, things get further and I get the "Device or resource busy" error.

makermelissa commented 9 months ago

@graemeok I'd suggest sudo apt install python3-libgpiod and not having gpiod installed for now. That helps with gpio, but still am running into the SPI issues.

makermelissa commented 9 months ago

@graemeok I'd suggest sudo apt install python3-libgpiod and not having gpiod installed for now. That helps with gpio, but still am running into the SPI issues.

I take that back. use sudo apt install gpiod.

makermelissa commented 9 months ago

I don't have the knowledge required to dig into circuit python, so the following suggestion is one made in ignorance, so please excuse. maybe the issue is with circuit python assuming for the pi5 that the CS1 & CS0 are on gpiochip0

No, the biggest difference between Blinka on the Pi 4 vs Pi 5 is for the Pi 5 we went with libgpiod instead of RPi.GPIO because RPi.GPIO was not updated to work on the Pi 5's hardware. libgpiod works on the other pins, but seems to have an issue with the CE0/CE1 pins which are toggled via python.

So one interesting thing I noticed is that Blinka works fine on a Pi 4, although gpioinfo still shows the CE0/CE1 pins as busy, so the issue is almost certainly related to libgpiod in one way or another. It could still be a permissions thing and adding to udev rules or something similar may get around that.

makermelissa commented 9 months ago

Ok, making progress... I ran the following commands:

sudo groupadd gpiod
sudo usermod -G gpiod pi

Then added the following to /etc/udev/rules.d/60-gpiod.rules

# udev rules for gpio port access through libgpiod
SUBSYSTEM=="gpio", KERNEL=="gpiochip0", GROUP="gpiod", MODE="0660"

Now I'm getting:

Traceback (most recent call last):
  File "/home/pi/ili9341_pitft_simpletest.py", line 11, in <module>
    import board
  File "/home/pi/env/lib/python3.11/site-packages/board.py", line 50, in <module>
    from adafruit_blinka.board.raspberrypi.raspi_5b import *
  File "/home/pi/env/lib/python3.11/site-packages/adafruit_blinka/board/raspberrypi/raspi_5b.py", line 6, in <module>
    from adafruit_blinka.microcontroller.bcm2712 import pin
  File "/home/pi/env/lib/python3.11/site-packages/adafruit_blinka/microcontroller/bcm2712/pin.py", line 8, in <module>
    D0 = Pin((4, 0))
         ^^^^^^^^^^^
  File "/home/pi/env/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py", line 36, in __init__
    self._chip = gpiod.Chip(str(pin_id[0]), gpiod.Chip.OPEN_BY_NUMBER)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied
makermelissa commented 9 months ago

Ok, I guess that was really a step backward rather than progress. Running as sudo still results in OSError: [Errno 16] Device or resource busy.

makermelissa commented 9 months ago

So slipping back into the original issue, it looks like the libgpiod_pin.py was written for libgpiod 1.6.x. I'm thinking of creating versions and then just checking and loading the appropriate file as to not lose backward compatibility.

makermelissa commented 9 months ago

I submitted a PR to fix the original issue, which will close this issue. Unfortunately it does not fix the OSError: [Errno 16] Device or resource busy error. Continued discussion of that error will be in #755, which is already open specifically for that.

yishaiSilver commented 4 months ago

Though suggested by my error message, the following install script wasn't working in my docker container. Using apt install python3-libgpiod fixed my issues. Thank you

https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/main/libgpiod.py