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

gpioioctl:Implement ioctl access to Linux GPIO chips/lines. #59

Merged
merged 32 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f2576ad
Implement ioctl access to Linux GPIO chips/lines.
gsexton Aug 28, 2024
3606c9b
Restructure tests. Remoe exposted fields from Chip and replace with g…
gsexton Sep 2, 2024
fde9c61
Remove obsoleted tests
gsexton Sep 2, 2024
5a2bd2e
Restore deleted files from sysfs
gsexton Sep 4, 2024
7e310bb
Changes for review comments
gsexton Sep 8, 2024
a4bd079
Pickup missed file
gsexton Sep 8, 2024
ac0bfa3
Fix prerequisite
gsexton Sep 8, 2024
7105f30
Cleanup JSON Marshaling for String()
gsexton Sep 9, 2024
9f4e183
Fix tests
gsexton Sep 9, 2024
6ff2ec3
Fix versions in test
gsexton Sep 9, 2024
1010695
try again
gsexton Sep 9, 2024
ad454c1
Remove String() funcs made for debugging since they're not really nee…
gsexton Sep 9, 2024
91c118d
Add gpioioctl initialization to host since it's required, and netlink…
gsexton Sep 9, 2024
0a36c23
gofmt
gsexton Sep 9, 2024
f80454e
generalize comment
gsexton Sep 9, 2024
ec651b5
Fix lint errors on various close statements.
gsexton Sep 9, 2024
9e052c9
Fix lint errors on various close statements.
gsexton Sep 9, 2024
7d39120
Fix test failure
gsexton Sep 9, 2024
342cb00
Fix commit
gsexton Sep 9, 2024
8cf3652
Fix sysfs test
gsexton Sep 9, 2024
dd8d970
Add conditional compilation
gsexton Sep 12, 2024
d6353a3
gofmt
gsexton Sep 12, 2024
1b97518
Revert go.mod
gsexton Sep 12, 2024
21d9499
Fix lint error on shadowed variable.
gsexton Sep 12, 2024
0f05e40
Lint fixes
gsexton Sep 12, 2024
2eaa0bc
Add timeout to onewire init to ensure pipeline compatibility.
gsexton Sep 12, 2024
47b0b70
add fd to socket. sort of necessary because the case of s to interfac…
gsexton Sep 12, 2024
0ffd4b2
Add conditional compilation to deal with OS differences
gsexton Sep 12, 2024
6990635
add license
gsexton Sep 12, 2024
1edbb95
Fix typo
gsexton Sep 12, 2024
aaec1cc
Revert init changes
gsexton Sep 12, 2024
9204ccc
More revert
gsexton Sep 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions gpioioctl/Testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Testing
gsexton marked this conversation as resolved.
Show resolved Hide resolved

The tests implemented perform *functional* tests of the library. This means that
the tests performed interact with a GPIO chipset, and perform actual read/write
operations. Using this test set, it's possible to quickly and accurately check
if the library is working as expected on a specific hardware/kernel combination.

## Requirements

Although the library is not Raspberry Pi specific, the GPIO pin names used for
tests are.

As written, the tests must be executed on a Raspberry Pi SBC running Linux. Tested
models are:

* Raspberry Pi 3B
* Raspberry Pi Zero W
* Raspberry Pi 4
* Raspberry Pi 5

You must also have the golang SDK installed.

## Setting Up

In order to execute the functional tests, you must jumper the sets of pins shown
below together.

For example, the single line tests require GPIO5 and GPIO13 to be connected to
each other, so a jumper is required between pins 29 and 33. For the multi-line
tests to work, you must connect the following GPIO pins together with jumpers.

| GPIO Output | Output Pin # | GPIO Input | Input Pin # |
| ----------- | ------------ | ---------- | ----------- |
| GPIO2 | 3 | GPIO10 | 19 |
| GPIO3 | 5 | GPIO11 | 23 |
| GPIO4 | 7 | GPIO12 | 32 |
| GPIO5 | 29 | GPIO13 | 33 |
| GPIO6 | 31 | GPIO14 | 8 |
| GPIO7 | 26 | GPIO15 | 10 |
| GPIO8 | 24 | GPIO16 | 36 |
| GPIO9 | 21 | GPIO17 | 11 |

## Cross-Compiling
If you don't have a working go installation on the target machine, you can cross
compile from one machine and then copy the test binary to the target machine.

To cross compile for Raspberry Pi, execute the command:

```bash
$periph.io/x/host/gpioctl> GOOS=linux GOARCH=arm64 go test -c
$periph.io/x/host/gpioctl> scp gpioioctl.test [email protected]:~
$periph.io/x/host/gpioctl> ssh [email protected]
$user> ./gpioioctl.test -test.v
```
for Pi Zero W, use:

```bash
$periph.io/x/host/gpioctl> GOOS=linux GOARCH=arm GOARM=6 go test -c
$periph.io/x/host/gpioctl> scp gpioioctl.test [email protected]:~
$periph.io/x/host/gpioctl> ssh [email protected]
$user> ./gpioioctl.test -test.v

```

## Executing the Tests

After connecting the jumper wires as shown above, and you have golang installed
and the go/bin directory in the path, change to this directory and execute the
command:

```bash
$> go test -v -cover
```
103 changes: 103 additions & 0 deletions gpioioctl/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package gpioioctl_test
// Copyright 2024 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.


import (
"fmt"
"log"
"time"

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

func ExampleChips() {
_, _ = host.Init()
_, _ = driverreg.Init()

fmt.Println("GPIO Test Program")
chip := gpioioctl.Chips[0]
defer chip.Close()
fmt.Println(chip.String())
// Test by flashing an LED.
led := gpioreg.ByName("GPIO5")
fmt.Println("Flashing LED ", led.Name())
for i := range 20 {
_ = led.Out((i % 2) == 0)
time.Sleep(500 * time.Millisecond)
}
_ = led.Out(true)

testRotary(chip, "GPIO20", "GPIO21", "GPIO19")
gsexton marked this conversation as resolved.
Show resolved Hide resolved
}

// Test the LineSet functionality by using it to read a Rotary Encoder w/ Button.
func testRotary(chip *gpioioctl.GPIOChip, stateLine, dataLine, buttonLine string) {
config := gpioioctl.LineSetConfig{DefaultDirection: gpioioctl.LineInput, DefaultEdge: gpio.RisingEdge, DefaultPull: gpio.PullUp}
config.Lines = []string{stateLine, dataLine, buttonLine}
// The Data Pin of the Rotary Encoder should NOT have an edge.
_ = config.AddOverrides(gpioioctl.LineInput, gpio.NoEdge, gpio.PullUp, dataLine)
ls, err := chip.LineSetFromConfig(&config)
if err != nil {
log.Fatal(err)
}
defer ls.Close()
statePinNumber := uint32(ls.ByOffset(0).Number())
buttonPinNumber := uint32(ls.ByOffset(2).Number())

var tLast = time.Now().Add(-1 * time.Second)
var halting bool
go func() {
time.Sleep(60 * time.Second)
halting = true
fmt.Println("Sending halt!")
_ = ls.Halt()
}()
fmt.Println("Test Rotary Switch - Turn dial to test rotary encoder, press button to test it.")
for {
lineNumber, _, err := ls.WaitForEdge(0)
if err == nil {
tNow := time.Now()
if (tNow.UnixMilli() - tLast.UnixMilli()) < 100 {
continue
}
tLast = tNow
if lineNumber == statePinNumber {
var bits uint64
tDeadline := tNow.UnixNano() + 20_000_000
var consecutive uint64
for time.Now().UnixNano() < tDeadline {
// Spin on reading the pins until we get some number
// of consecutive readings that are the same.
bits, _ = ls.Read(0x03)
if bits&0x01 == 0x00 {
// We're bouncing.
consecutive = 0
} else {
consecutive += 1
if consecutive > 25 {
if bits == 0x01 {
fmt.Printf("Clockwise bits=%d\n", bits)
} else if bits == 0x03 {
fmt.Printf("CounterClockwise bits=%d\n", bits)
}
break
}
}
}
} else if lineNumber == buttonPinNumber {
fmt.Println("Button Pressed!")
}
} else {
fmt.Println("Timeout detected")
if halting {
break
}
}
}
}
Loading
Loading