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

Edge detection does not work on Raspbian Bookworm #62

Open
fischerman opened this issue Sep 23, 2024 · 16 comments
Open

Edge detection does not work on Raspbian Bookworm #62

fischerman opened this issue Sep 23, 2024 · 16 comments

Comments

@fischerman
Copy link

Describe the bug

The pin cannot be associated with a sysfs pin.

$ go run cmd/edge/edge.go 
2024/09/23 10:22:18 bcm283x-gpio (GPIO17): pin 17 is not exported by sysfs
exit status 1

To Reproduce
Steps to reproduce the behavior:

  1. Run program
package main

import (
	"log"

	"periph.io/x/conn/v3/gpio"
	"periph.io/x/conn/v3/gpio/gpioreg"
	"periph.io/x/host/v3"
)

func main() {
	if _, err := host.Init(); err != nil {
		log.Fatal(err)
	}

	// Lookup a pin by its number:
	p := gpioreg.ByName("GPIO17")
	if p == nil {
		log.Fatal("Failed to find GPIO17")
	}

	// Set it as input, with an internal pull down resistor:
	if err := p.In(gpio.PullDown, gpio.BothEdges); err != nil {
		log.Fatal(err)
	}

	p.WaitForEdge(-1)
}
  1. See error

Expected behavior

No error on In.

Platform:

  • OS: Raspbian GNU/Linux 12 (bookworm)
  • Board: Raspberry Pi 2 Model B v1.1

Additional context

I'm not aware of any prerequisites that must be met. I tried running the program as root as well, but I get the same error.

@fischerman
Copy link
Author

I think the problem is that starting with Bookworm sysfs GPIO has been removed. It might affect other distributions as well. At least all Raspberries are affected.

@fischerman fischerman changed the title Edge detection does not work on Raspberry Pi 2 Edge detection does not work on Raspbian Bookworm Sep 23, 2024
@maruel
Copy link
Member

maruel commented Sep 23, 2024

Can you test if b69b28c fixes the problem? If so, I'll do a release.

@fischerman
Copy link
Author

On the Pi 2 I'm getting a lot of errors now:

go run cmd/edge/edge.go 
2024/09/24 10:28:43 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 33,
    "Name": "NC",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "NC" twice; already registered as "{\n    \"Line\": 30,\n    \"Name\": \"NC\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/09/24 10:28:43 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 34,
    "Name": "NC",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "NC" twice; already registered as "{\n    \"Line\": 30,\n    \"Name\": \"NC\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/09/24 10:28:43 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 36,
    "Name": "NC",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "NC" twice; already registered as "{\n    \"Line\": 30,\n    \"Name\": \"NC\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/09/24 10:28:43 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 37,
    "Name": "NC",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "NC" twice; already registered as "{\n    \"Line\": 30,\n    \"Name\": \"NC\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/09/24 10:28:43 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 39,
    "Name": "NC",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "NC" twice; already registered as "{\n    \"Line\": 30,\n    \"Name\": \"NC\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/09/24 10:28:43 bcm283x-gpio (GPIO17): subsystem gpiomem not initialized and sysfs not accessible
exit status 1

Not sure if it is related but header-list no longer returns functions:

$ go run headers-list/main.go 
AUDIO: 2 pins
  Pos  Name    Func
  1    GPIO45  
  2    GPIO40  

HDMI: 1 pins
  Pos  Name    Func
  1    GPIO46  

P1: 40 pins
  Func    Name  Pos  Pos  Name    Func
          3.3V    1  2    5V          
         GPIO2    3  4    5V          
         GPIO3    5  6    GROUND      
         GPIO4    7  8    GPIO14      
        GROUND    9  10   GPIO15      
        GPIO17   11  12   GPIO18      
        GPIO27   13  14   GROUND      
        GPIO22   15  16   GPIO23      
          3.3V   17  18   GPIO24      
        GPIO10   19  20   GROUND      
         GPIO9   21  22   GPIO25      
        GPIO11   23  24   GPIO8       
        GROUND   25  26   GPIO7       
         GPIO0   27  28   GPIO1       
         GPIO5   29  30   GROUND      
         GPIO6   31  32   GPIO12      
        GPIO13   33  34   GROUND      
        GPIO19   35  36   GPIO16      
        GPIO26   37  38   GPIO20      
        GROUND   39  40   GPIO21

@gsexton
Copy link
Contributor

gsexton commented Sep 27, 2024

@fischerman
Can you try running this example:

host/gpioioctl/example_test.go

@Evert-Arends
Copy link

I want to see this fixed so I ran a gpio out on my RPI 5, using the branch you provided @maruel

pi@worker-pi-1:~/GraftXL/cmd/run3 $ go get periph.io/x/host/v3@b69b28c4e40f9f233222c9d7ea610ef0fcc8a54b
go: downloading periph.io/x/host/v3 v3.8.3-0.20240918234808-b69b28c4e40f

which quickly died:

2024/10/08 20:13:09 chip gpiochip4  gpioreg.Register(line)  {
    "Line": 47,
    "Name": "2712_WAKE",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "2712_WAKE" twice; already registered as "{\n    \"Line\": 8,\n    \"Name\": \"2712_WAKE\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
Failed to set pin as output: bcm283x-gpio (GPIO17): subsystem gpiomem not initialized and sysfs not accessible

Using this example code for my motor that works on the RPI4:

package main

import (
    "fmt"
    "time"
    "periph.io/x/conn/v3/gpio"
    "periph.io/x/host/v3"
    "periph.io/x/host/v3/rpi"
)

func main() {
    if _, err := host.Init(); err != nil {
        fmt.Println("Failed to initialize periph:", err)
        return
    }

    stepPin := rpi.P1_11 // Use GPIO17

    // Set the pin as an output
    if err := stepPin.Out(gpio.Low); err != nil {
        fmt.Println("Failed to set pin as output:", err)
        return
    }

    pulseCount := 800


    pulseDuration := 1000 * time.Microsecond

    // Generate pulses
    fmt.Printf("Sending %d pulses...\n", pulseCount)
    for i := 0; i < pulseCount; i++ {
        if err := stepPin.Out(gpio.High); err != nil {
            fmt.Println("Failed to set pin high:", err)
            return
        }

        time.Sleep(pulseDuration / 2)

        if err := stepPin.Out(gpio.Low); err != nil {
            fmt.Println("Failed to set pin low:", err)
            return
        }

        time.Sleep(pulseDuration / 2)
    }

    fmt.Println("Finished sending pulses.")
}

I hope this helps in someway!

@gsexton
Copy link
Contributor

gsexton commented Oct 8, 2024

@Evert-Arends

There are 4 GPIO chips on the Pi 5, and they all export a pin named "2712_WAKE". This causes the error you're seeing.

Take the return out of the host.Init() statement and see what it does.

@Evert-Arends
Copy link

Did that, removed the return.

2024/10/09 19:10:11 chip gpiochip4  gpioreg.Register(line)  {
    "Line": 47,
    "Name": "2712_WAKE",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "2712_WAKE" twice; already registered as "{\n    \"Line\": 8,\n    \"Name\": \"2712_WAKE\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
Failed to set pin as output: bcm283x-gpio (GPIO23): subsystem gpiomem not initialized and sysfs not accessible

func main() {
        if _, err := host.Init(); err != nil {
                fmt.Println("Failed to initialize periph:", err)
                //        return
        }

        stepPin := rpi.P1_16 // 23

        // Set the pin as an output
        if err := stepPin.Out(gpio.Low); err != nil {
                fmt.Println("Failed to set pin as output:", err)
                return
        }

        pulseCount := 800

        pulseDuration := 1000 * time.Microsecond

        // Generate pulses
        fmt.Printf("Sending %d pulses...\n", pulseCount)
        for i := 0; i < pulseCount; i++ {
                if err := stepPin.Out(gpio.High); err != nil {
                        fmt.Println("Failed to set pin high:", err)
                        return
                }

                time.Sleep(pulseDuration / 2)

                if err := stepPin.Out(gpio.Low); err != nil {
                        fmt.Println("Failed to set pin low:", err)
                        return
                }

                time.Sleep(pulseDuration / 2)
        }

        fmt.Println("Finished sending pulses.")
}

@gsexton
Copy link
Contributor

gsexton commented Oct 10, 2024

@fischerman and @Evert-Arends

Here is a basic program using the gpioioctl code that demonstrates edge detection. It assumes you have a jumper connecting GPIO2 and GPIO 10. This was run on a Raspberry Pi 5:

gsexton@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 12 (bookworm)
Release:        12
Codename:       bookworm
gsexton@raspberrypi:~ $ uname -a
Linux raspberrypi 6.6.45-v8-16k+ #1791 SMP PREEMPT Tue Aug 13 12:52:29 BST 2024 aarch64 GNU/Linux

To build this, you'll need the commit that has gpioioctl in it:

gsexton@raspberrypi:~ $ go get periph.io/x/host/v3@b69b28c4e40f9f233222c9d7ea610ef0fcc8a54b

main.go

package main

import (
	"fmt"
	"time"

	"periph.io/x/conn/v3/gpio"
	"periph.io/x/host/v3"
	"periph.io/x/host/v3/gpioioctl"
)

func main() {
	if _, err := host.Init(); err != nil {
		fmt.Println("Failed to initialize periph:", err)
		//        return
	}

	gpiochip:=gpioioctl.Chips[0]
	outPin:=gpiochip.ByName("GPIO2")
	inPin:=gpiochip.ByName("GPIO10")
	inPin.In(gpio.PullDown,gpio.RisingEdge)
	fmt.Println("inPin=",inPin)
	fmt.Println("outPin=",outPin)
	
	l:=gpio.Low
	go func() {
		for  {
			l=!l
			fmt.Println("setting outPin to ",l)
			outPin.Out(l)
			
			time.Sleep(1000 * time.Millisecond)
		}
	}()

	for  {
		if inPin.WaitForEdge(0){
			fmt.Println("Received edge")
		} else {
			fmt.Println("WaitForEdge() unblocked without receiving edge.")
		}
	}
}

Sample Output:

gsexton@raspberrypi:~ $ ./simpledge 
2024/10/09 18:57:50 chip gpiochip12  gpioreg.Register(line)  {
    "Line": 8,
    "Name": "2712_WAKE",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "2712_WAKE" twice; already registered as "{\n    \"Line\": 47,\n    \"Name\": \"2712_WAKE\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
inPin= {
    "Line": 10,
    "Name": "GPIO10",
    "Consumer": "simpledge@2246",
    "Direction": "Input",
    "Pull": "PullDown",
    "Edges": "RisingEdge"
}
outPin= {
    "Line": 2,
    "Name": "GPIO2",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}
setting outPin to  High
Received edge
setting outPin to  Low
setting outPin to  High
Received edge
setting outPin to  Low
setting outPin to  High
Received edge
setting outPin to  Low
setting outPin to  High
Received edge
^C

@fischerman
Copy link
Author

@gsexton Your example works on my RPi2. I compared it to my program and what seems to break it is:

gpioreg.ByName("GPIO17")

gpioioctl.Chips[0] on the other hand works fine.

@gsexton
Copy link
Contributor

gsexton commented Oct 14, 2024

@fischerman I've looked into this.

The problem is the bcm283x driver is running after the gpioioctl register code. That driver explicitly unregisters the gpioioctl registered GPIO pins values and supplies non-working sysfs based pins, causing things to break (line 1395 of host/bcm283x/gpio.go).

@maruel do you have any ideas on the correct fix?

@maruel
Copy link
Member

maruel commented Oct 15, 2024

bcm283x needs to condition on which driver is loaded and act accordingly.

@damdo
Copy link

damdo commented Oct 23, 2024

Is this then solved by #63 ?
Should this be closed? Thanks!

@gsexton
Copy link
Contributor

gsexton commented Nov 3, 2024

@damdo Could you test this on your configuration using the current head?

@fischerman and @Evert-Arends Could you test this and see if your issue is resolved?

@fischerman
Copy link
Author

I've tested the following program with commit 7540d26b4dc114207d0e5f7603b0f176bf5805dd.

package main

import (
	"fmt"
	"log"
	"time"

	"periph.io/x/conn/v3/gpio"
	"periph.io/x/conn/v3/gpio/gpioreg"
	"periph.io/x/host/v3"
)

func main() {
	if _, err := host.Init(); err != nil {
		fmt.Println("Failed to initialize periph:", err)
		//        return
	}

	outPin := gpioreg.ByName("GPIO2")
	if outPin == nil {
		log.Fatal("Failed to find GPIO2")
	}
	inPin := gpioreg.ByName("GPIO10")
	if inPin == nil {
		log.Fatal("Failed to find GPIO10")
	}
	inPin.In(gpio.PullDown, gpio.RisingEdge)
	fmt.Println("inPin=", inPin)
	fmt.Println("outPin=", outPin)

	l := gpio.Low
	go func() {
		for {
			l = !l
			fmt.Println("setting outPin to ", l)
			outPin.Out(l)

			time.Sleep(1000 * time.Millisecond)
		}
	}()

	for {
		if inPin.WaitForEdge(0) {
			fmt.Println("Received edge")
		} else {
			fmt.Println("WaitForEdge() unblocked without receiving edge.")
		}
	}
}

It works. However, I still see a lot of warnings:

2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 0,
    "Name": "ID_SDA",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "ID_SDA" twice; already registered as "{\n    \"Line\": 0,\n    \"Name\": \"ID_SDA\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 1,
    "Name": "ID_SCL",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "ID_SCL" twice; already registered as "{\n    \"Line\": 1,\n    \"Name\": \"ID_SCL\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 2,
    "Name": "GPIO2",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO2" twice; already registered as "{\n    \"Line\": 2,\n    \"Name\": \"GPIO2\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 3,
    "Name": "GPIO3",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO3" twice; already registered as "{\n    \"Line\": 3,\n    \"Name\": \"GPIO3\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 4,
    "Name": "GPIO4",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO4" twice; already registered as "{\n    \"Line\": 4,\n    \"Name\": \"GPIO4\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 5,
    "Name": "GPIO5",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO5" twice; already registered as "{\n    \"Line\": 5,\n    \"Name\": \"GPIO5\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 6,
    "Name": "GPIO6",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO6" twice; already registered as "{\n    \"Line\": 6,\n    \"Name\": \"GPIO6\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 7,
    "Name": "GPIO7",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO7" twice; already registered as "{\n    \"Line\": 7,\n    \"Name\": \"GPIO7\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 8,
    "Name": "GPIO8",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO8" twice; already registered as "{\n    \"Line\": 8,\n    \"Name\": \"GPIO8\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 9,
    "Name": "GPIO9",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO9" twice; already registered as "{\n    \"Line\": 9,\n    \"Name\": \"GPIO9\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 10,
    "Name": "GPIO10",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO10" twice; already registered as "{\n    \"Line\": 10,\n    \"Name\": \"GPIO10\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 11,
    "Name": "GPIO11",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO11" twice; already registered as "{\n    \"Line\": 11,\n    \"Name\": \"GPIO11\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 12,
    "Name": "GPIO12",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO12" twice; already registered as "{\n    \"Line\": 12,\n    \"Name\": \"GPIO12\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 13,
    "Name": "GPIO13",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO13" twice; already registered as "{\n    \"Line\": 13,\n    \"Name\": \"GPIO13\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 14,
    "Name": "GPIO14",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO14" twice; already registered as "{\n    \"Line\": 14,\n    \"Name\": \"GPIO14\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 15,
    "Name": "GPIO15",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO15" twice; already registered as "{\n    \"Line\": 15,\n    \"Name\": \"GPIO15\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 16,
    "Name": "GPIO16",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO16" twice; already registered as "{\n    \"Line\": 16,\n    \"Name\": \"GPIO16\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 17,
    "Name": "GPIO17",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO17" twice; already registered as "{\n    \"Line\": 17,\n    \"Name\": \"GPIO17\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 18,
    "Name": "GPIO18",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO18" twice; already registered as "{\n    \"Line\": 18,\n    \"Name\": \"GPIO18\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 19,
    "Name": "GPIO19",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO19" twice; already registered as "{\n    \"Line\": 19,\n    \"Name\": \"GPIO19\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 20,
    "Name": "GPIO20",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO20" twice; already registered as "{\n    \"Line\": 20,\n    \"Name\": \"GPIO20\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 21,
    "Name": "GPIO21",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO21" twice; already registered as "{\n    \"Line\": 21,\n    \"Name\": \"GPIO21\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 22,
    "Name": "GPIO22",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO22" twice; already registered as "{\n    \"Line\": 22,\n    \"Name\": \"GPIO22\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 23,
    "Name": "GPIO23",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO23" twice; already registered as "{\n    \"Line\": 23,\n    \"Name\": \"GPIO23\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 24,
    "Name": "GPIO24",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO24" twice; already registered as "{\n    \"Line\": 24,\n    \"Name\": \"GPIO24\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 25,
    "Name": "GPIO25",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO25" twice; already registered as "{\n    \"Line\": 25,\n    \"Name\": \"GPIO25\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 26,
    "Name": "GPIO26",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO26" twice; already registered as "{\n    \"Line\": 26,\n    \"Name\": \"GPIO26\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 27,
    "Name": "GPIO27",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "GPIO27" twice; already registered as "{\n    \"Line\": 27,\n    \"Name\": \"GPIO27\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 28,
    "Name": "HDMI_HPD_N",
    "Consumer": "hpd",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "HDMI_HPD_N" twice; already registered as "{\n    \"Line\": 28,\n    \"Name\": \"HDMI_HPD_N\",\n    \"Consumer\": \"hpd\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 29,
    "Name": "STATUS_LED_N",
    "Consumer": "ACT",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "STATUS_LED_N" twice; already registered as "{\n    \"Line\": 29,\n    \"Name\": \"STATUS_LED_N\",\n    \"Consumer\": \"ACT\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 30,
    "Name": "CTS0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "CTS0" twice; already registered as "{\n    \"Line\": 30,\n    \"Name\": \"CTS0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 31,
    "Name": "RTS0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "RTS0" twice; already registered as "{\n    \"Line\": 31,\n    \"Name\": \"RTS0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 32,
    "Name": "TXD0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "TXD0" twice; already registered as "{\n    \"Line\": 32,\n    \"Name\": \"TXD0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 33,
    "Name": "RXD0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "RXD0" twice; already registered as "{\n    \"Line\": 33,\n    \"Name\": \"RXD0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 34,
    "Name": "SD1_CLK",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD1_CLK" twice; already registered as "{\n    \"Line\": 34,\n    \"Name\": \"SD1_CLK\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 35,
    "Name": "SD1_CMD",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD1_CMD" twice; already registered as "{\n    \"Line\": 35,\n    \"Name\": \"SD1_CMD\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 36,
    "Name": "SD1_DATA0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD1_DATA0" twice; already registered as "{\n    \"Line\": 36,\n    \"Name\": \"SD1_DATA0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 37,
    "Name": "SD1_DATA1",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD1_DATA1" twice; already registered as "{\n    \"Line\": 37,\n    \"Name\": \"SD1_DATA1\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 38,
    "Name": "SD1_DATA2",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD1_DATA2" twice; already registered as "{\n    \"Line\": 38,\n    \"Name\": \"SD1_DATA2\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 39,
    "Name": "SD1_DATA3",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD1_DATA3" twice; already registered as "{\n    \"Line\": 39,\n    \"Name\": \"SD1_DATA3\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 40,
    "Name": "CAM_GPIO1",
    "Consumer": "cam1_regulator",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "CAM_GPIO1" twice; already registered as "{\n    \"Line\": 40,\n    \"Name\": \"CAM_GPIO1\",\n    \"Consumer\": \"cam1_regulator\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 41,
    "Name": "WL_ON",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "WL_ON" twice; already registered as "{\n    \"Line\": 41,\n    \"Name\": \"WL_ON\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 42,
    "Name": "BT_ON",
    "Consumer": "shutdown",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "BT_ON" twice; already registered as "{\n    \"Line\": 42,\n    \"Name\": \"BT_ON\",\n    \"Consumer\": \"shutdown\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 43,
    "Name": "WIFI_CLK",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "WIFI_CLK" twice; already registered as "{\n    \"Line\": 43,\n    \"Name\": \"WIFI_CLK\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 44,
    "Name": "SDA0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SDA0" twice; already registered as "{\n    \"Line\": 44,\n    \"Name\": \"SDA0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 45,
    "Name": "SCL0",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SCL0" twice; already registered as "{\n    \"Line\": 45,\n    \"Name\": \"SCL0\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
inPin= GPIO10
outPin= GPIO2
setting outPin to  High
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 46,
    "Name": "SMPS_SCL",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SMPS_SCL" twice; already registered as "{\n    \"Line\": 46,\n    \"Name\": \"SMPS_SCL\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 47,
    "Name": "SMPS_SDA",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SMPS_SDA" twice; already registered as "{\n    \"Line\": 47,\n    \"Name\": \"SMPS_SDA\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 48,
    "Name": "SD_CLK_R",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD_CLK_R" twice; already registered as "{\n    \"Line\": 48,\n    \"Name\": \"SD_CLK_R\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 49,
    "Name": "SD_CMD_R",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD_CMD_R" twice; already registered as "{\n    \"Line\": 49,\n    \"Name\": \"SD_CMD_R\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 50,
    "Name": "SD_DATA0_R",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD_DATA0_R" twice; already registered as "{\n    \"Line\": 50,\n    \"Name\": \"SD_DATA0_R\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 51,
    "Name": "SD_DATA1_R",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD_DATA1_R" twice; already registered as "{\n    \"Line\": 51,\n    \"Name\": \"SD_DATA1_R\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 52,
    "Name": "SD_DATA2_R",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD_DATA2_R" twice; already registered as "{\n    \"Line\": 52,\n    \"Name\": \"SD_DATA2_R\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}"
2024/11/04 20:12:24 chip gpiochip0  gpioreg.Register(line)  {
    "Line": 53,
    "Name": "SD_DATA3_R",
    "Consumer": "",
    "Direction": "NotSet",
    "Pull": "PullNoChange",
    "Edges": "NoEdge"
}  returned  gpioreg: can't register pin "SD_DATA3_R" twice; already registered as "{\n    \"Line\": 53,\n    \"Name\": \"SD_DATA3_R\",\n    \"Consumer\": \"\",\n    \"Direction\": \"NotSet\",\n    \"Pull\": \"PullNoChange\",\n    \"Edges\": \"NoEdge\"\n}

@maruel
Copy link
Member

maruel commented Nov 11, 2024

@fischerman These errors are not supported to be there, that's weird.

@gsexton
Copy link
Contributor

gsexton commented Nov 14, 2024

@maruel

I guess we need to discuss how to handle this. There's a lot going on.

Today I noticed that in a pi5 I have running, there's a symlink for /dev/gpiochip4 -> /dev/gpiochip0. That's probably causing most of the duplication. There's some discussion of that here:

http://git.munts.com/muntsos/doc/AppNote11-link-gpiochip.pdf

The pi5 exports 5 total GPIO chips. Some of the lines have duplicate names. I see two chips (not counting the symlink) that have 2712_WAKE lines. So, we can't depend upon the exported line/pin names to be unique.

Looking at the output of the chips dumped (now you know why I went wild on my String() implementation :) ). I can see that perhaps the parser should deterministically make a chip with label "pinctrl" the first one to be processed. Some of the chip labels appear to be pointers. For example: "Label": "gpio-brcmstb@107d508500" btw.

So, our options are:

  1. Don't print the errors. Programs break in mysterious ways because it's not going to be deterministic. The first release of bookworm for Pi5 was returning the chips in a different order than they are now. The effect will be that duplicates won't be accessible.

  2. If the chip name looks like a pointer, assume it's not exposed and don't do anything with it.

  3. Keep doing all of the chips, but don't add colliding line names to the registry; just drop them. Probably not a bad choice.

  4. Change the driver code so that it checks for the key. The bcm283x code is already doing this. We have two choices, if the key is duplicated, insert some sort of prefix (chip label) into the key and stick it in anyhow. This impacts the utility of the registry because you're not really going to be deterministic again. We can mitigate that somewhat by processing a chip labeled "pinctrl" first. There's also nothing that says the "pointer labels" will be the same across kernel updates. Sort of a vote for suggestion 2 above...

Alternatively, we can stick everything that is not labeled pinctrl into the registry with as label+line.

--

It's really sort of a mess.

My recommendation is Option 2, and add code to handle duplicate chips caused by symlinks. Examine the /dev/ entry and skip if if it's a symlink. This is unfortunately a Pi specific answer.

For a non-pi specific answer, my recommendation is: 1) Do a chip named "pinctrl-" first if found, and the rest in lexical order of device name. Skip symlinks. If a name is a collision, prefix it with the chip label.

I've attached a copy of the chip output from a pi5 running the lastest kernel if you'd like to look at it.

chips.json

Let me know what you would like and I'll create another PR to implement it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

5 participants