raspi-config nonint do_i2c 1 hängt "für immer"

Während der Entwicklung PiCockpit ausprobierenund versucht, dem Benutzer zu erlauben, I2C über das Webinterface auszuschalten, bin ich auf Abstürze und Probleme gestoßen.

Ich verwende raspi-config im nicht-interaktiven Modus (ich habe bereits darüber geschrieben) um I2C vom PiCockpit-Client aus zu steuern.

Während der Fehlersuche stellte ich fest, dass der Befehl (raspi-config) einfrieren würde, wenn etwas auf den I2C-Bus zugreift.

Bei der Untersuchung mit ps aux stellte ich fest, dass ein anderer Befehl gestartet, aber nicht ausgeführt worden war:

dtparam i2c_arm=off

Dies ist eine kompilierte Binärdatei, kein Skript. Aber es hat einen ausführlichen Modus.

dies manuell im Verbose-Modus auszuführen, während etwas anderes auf den I2C-Bus zugreift:

17:32:55 root@Avalon:/home/pi # dtparam -v i2c_arm=off

DTOVERLAY[debug]: Verwendung der Plattform 'bcm2711'

DTOVERLAY[debug]: Überlagerungskarte geladen

run_cmd: which dtoverlay-pre >/dev/null 2>&1 && dtoverlay-pre

run_cmd: dtc -I fs -O dtb -o '/tmp/.dtoverlays/base.dtb' /proc/device-tree 1>/dev/null 2>&1

DTOVERLAY[debug]: Laden der Datei '/tmp/.dtoverlays/base.dtb'

DTOVERLAY[debug]: Übersteuerung i2c_arm gefunden

DTOVERLAY[debug]: i2c_arm überschreiben: String Ziel 'Status'

DTOVERLAY[debug]: 166 Bytes nach '/tmp/.dtoverlays/69_dtparam.dtbo' geschrieben

DTOVERLAY[debug]: schrieb 179 Bytes nach '/sys/kernel/config/device-tree/overlays/69_dtparam/dtbo'

run_cmd: which dtoverlay-post >/dev/null 2>&1 && dtoverlay-post

hängen würde vor den letzten Befehl (gelb hervorgehoben).

Sobald die andere Anwendung den I2C-Bus freigegeben hatte, beendete dtparam seine Arbeit und zeigte die letzte Zeile an.

Wie kann man herausfinden, welche Anwendungen auf den i2c-Bus zugreifen?

Ganz einfach, mit lsof:

sudo lsof /dev/i2c-1

lsof: WARNUNG: kann nicht stat() fuse.gvfsd-fuse Dateisystem /run/user/1000/gvfs
       Die ausgegebenen Informationen können unvollständig sein.
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 24772 root 13u CHR 89,1 0t0 285423 /dev/i2c-1

Bild

in meinem Fall kann die Datei je nach Aktivität der beiden Anwendungen (CO2 und BME688) auch zweimal geöffnet sein:

Bild

Da es anscheinend keinen Workaround für das Hängen von dtparam (und damit von raspi-config) gibt, wenn auf I2C zugegriffen wird, empfehle ich, zuerst den Status der Dateideskriptoren zu überprüfen und dem Benutzer eine Fehlermeldung anzuzeigen, wenn dies der Fall ist (dass er die Anwendungen zuerst deaktivieren muss, damit dies funktioniert).

NB: Für den SMBus von Python können Sie einfach bus.close() (wenn Sie Ihren SMBus-Instanzbus genannt haben)