uraimo / SwiftyGPIO

A Swift library for hardware projects on Linux/ARM boards with support for GPIOs/SPI/I2C/PWM/UART/1Wire.
MIT License
1.35k stars 135 forks source link

Getting `edge` causes a crash on a Raspberry Pi 4 Model B Rev 1.5 #139

Open just-doit opened 5 months ago

just-doit commented 5 months ago

Board Type

Raspberry Pi 4 Model B Rev 1.5

Operating System

Linux 6.6.20+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.20-1+rpt1 (2024-03-07) aarch64 GNU/Linux

Swift Version

Swift version 5.10 (swift-5.10-RELEASE) Target: aarch64-unknown-linux-gnu Prebuild

Description

A pin is configured as an input and should call up a function when it changes (both high->low and low-high). When getting the value of the edge property an exception is raised. In my opinion, this is caused by the getter making the following call:

            return GPIOEdge(rawValue: getStringValue("gpio "+String(id)+"/edge")!)!

This ends up at readFromFile with the following path: /sys/class/gpio/gpio0/edge. However, this does not exist on my device, so that nil is returned. This is unwrapped with ! -> boom.

This is what /sys/class/gpiolooks like:

total 0
drwxrwxr-x  2 root gpio    0 Apr 30 14:39 .
drwxr-xr-x 65 root root    0 Jan  1  1970 ..
--w--w----  1 root gpio 4096 Apr 30 14:39 export
lrwxrwxrwx  1 root gpio    0 Apr 30 14:39 gpiochip512 -> ../../devices/platform/soc/fe200000.gpio/gpio/gpiochip512
lrwxrwxrwx  1 root gpio    0 Apr 30 14:39 gpiochip570 -> ../../devices/platform/soc/soc:firmware/soc:firmware:gpio/gpio/gpiochip570
--w--w----  1 root gpio 4096 Apr 30 14:39 unexport
uraimo commented 5 months ago

Hi, can you try running your application with sudo and if that doesn't work try executing:

echo the_id_you_are_using >/sys/class/gpio/export
ls /sys/class/gpio

From what I see the gpio file the library needs for the edge feature has not been created at all, the gpiochip ones should point to the controller or similar devices, no the individual gpios.

just-doit commented 5 months ago

HI, thanks for the quick response.

Running with sudo makes no difference. I build this small sample app:

import Foundation
import SwiftyGPIO

let gpios = SwiftyGPIO.GPIOs(for:.RaspberryPi4)

if let pin = gpios[.P17]
{
    print("\(pin.edge)")
}

The crash is:

SwiftyGPIO/SwiftyGPIO.swift:73: Fatal error: Unexpectedly found nil while unwrapping an Optional value

💣 Program crashed: System trap at 0x0000007f80e0f3ac

Thread 0 "SwiftyGPIOTest" crashed:

0 0x0000007f80e0f3ac closure #1 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 236 in libswiftCore.so
1 0x0000007f80e0f198 closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 199 in libswiftCore.so
2 0x0000007f80e0f088 closure #1 in _assertionFailure(_:_:file:line:flags:) + 327 in libswiftCore.so
3 0x0000007f80e0ec58 _assertionFailure(_:_:file:line:flags:) + 175 in libswiftCore.so
4 GPIO.edge.getter + 491 in SwiftyGPIOTest at /home/dirk/SwiftyGPIOTest/.build/checkouts/SwiftyGPIO/Sources/SwiftyGPIO.swift:73:80

    71│         get {
    72│             if !exported {enableIO(id)}
    73│             return GPIOEdge(rawValue: getStringValue("gpio"+String(id)+"/edge")!)!
      │                                                                                ▲
    74│         }
    75│     }

echo 17 >/sys/class/gpio/export gives echo: write error: Invalid argument sudo echo 17 >/sys/class/gpio/export gives same error.

ls -al /sys/class/gpio returns:

total 0
drwxrwxr-x  2 root gpio    0 May  1 17:38 .
drwxr-xr-x 65 root root    0 Jan  1  1970 ..
--w--w----  1 root gpio 4096 May  2 09:05 export
lrwxrwxrwx  1 root gpio    0 May  1 17:38 gpiochip512 -> ../../devices/platform/soc/fe200000.gpio/gpio/gpiochip512
lrwxrwxrwx  1 root gpio    0 May  1 17:38 gpiochip570 -> ../../devices/platform/soc/soc:firmware/soc:firmware:gpio/gpio/gpiochip570
--w--w----  1 root gpio 4096 May  1 17:38 unexport
uraimo commented 5 months ago

Ok, the raspberry people broke it in the kernel last month, can you try again with release 1.4.4 and using for:.RaspberryPi4_2024 instead?

It would be great if you could also report back if gpios are actually working when you set some value, I'm still not sure if they changed something else or not, but can't test it right now.

just-doit commented 5 months ago

This is a bit better, but I can't get an output pin to change it's value.

My test app is now this:

import Foundation
import SwiftyGPIO

let gpios = SwiftyGPIO.GPIOs(for:.RaspberryPi4_2024)

if let pin = gpios[.P17]
{
    print("\(pin.edge)")
    pin.edge = .BOTH
    print("\(pin.edge)")
}

if let pin = gpios[.P4]
{
    pin.value = 1
    print("\(pin.value)")
    pin.direction = .OUT
    pin.value = 0
    print("\(pin.value)")
    Thread.sleep(forTimeInterval: 10.0)
    pin.value = 1
    print("\(pin.value)")
}

It outputs

NONE
BOTH
0
0
0

gpioinfo returns this for the both pins I've used:

    line   4:      "GPIO4"       unused   input  active-high
    line  17:     "GPIO17"      "sysfs"   input  active-high [used]

The output pin stays high, when measured.