Go·Hardware·Lean

periph - Peripherals I/O in Go

mascot

Documentation is at https://periph.io

Join us for a chat on gophers.slack.com/messages/periph, get an invite here.

New home

The source code is now hosted in multiple repositories at github.com/periph. See https://periph.io/news/2020/a_new_start/ for more details.

Authors

periph was initiated with ❤️ ️ and passion by Marc-Antoine Ruel. The full list of contributors is in AUTHORS and CONTRIBUTORS.

Disclaimer

This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google.

This project is not affiliated with the Go project.

Owner
Google
Google ❤️ Open Source
Google
Comments
  • sysfs-spi: invalid SPI KeepCS handling [was: can't set antenna for mfrc522 device]

    sysfs-spi: invalid SPI KeepCS handling [was: can't set antenna for mfrc522 device]

    Hello jdevelop and maruel, great to see this merge. pull/220 I am busy trying out the experimental mfrc522 code but it fails to set the antenna.

    The pins follow the layout described here by jdevelop. interrupt falling edge by jens18 rfid-layout

    So after initially running into this:

    mfrc522: mfrc522: timeout waitinf for IRQ edge: 30s.

    I used the following command which worked for the irq pin timeout but it would then run into this issue:

    pi@raspberrypi:~/go/src/github.com/google/periph/experimental $ go run cmd/mfrc522/main.go -rs-pin 13 -irq-pin 11

    mfrc522: mfrc522: can not set the bitmask for antenna. exit status 1

    Could anybody help me troubleshoot this? Running on a raspberry pi zero or 3 b I am using this device joy-it/RFID_RC522 I can confirm that it works with this library mxgxw/MFRC522-python Much thanks

  • sysfs: Omega2+ I²C failure due to MIPS ioctl encoding

    sysfs: Omega2+ I²C failure due to MIPS ioctl encoding

    Seeing ioctl()s on i2c device failing during a call to i2creg.Open() using periph/golang but not on the same device when using i2cdump. Running as root user in both cases. Completely reproducible.

    periph test app is conn/i2c/i2creg/example_test.go (renamed to example.go, built for mips, added func main())

    i2cdump strace -f output:

    root@Omega-DFEB:~# strace i2cdump -y -r 0-2 0 0x36 w
    execve("/usr/sbin/i2cdump", ["i2cdump", "-y", "-r", "0-2", "0", "0x36", "w"], [/* 12 vars */]) = 0
    set_thread_area(0x77b39d48)             = 0
    set_tid_address(0x77b32cac)             = 2623
    open("/etc/ld-musl-mipsel-sf.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
    open("/lib/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
    fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
    fstat64(3, {st_mode=S_IFREG|0644, st_size=76975, ...}) = 0
    read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\20(\0\0004\0\0\0"..., 936) = 936
    mmap2(NULL, 143360, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x77a6a000
    mmap2(0x77a8c000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12000) = 0x77a8c000
    close(3)                                = 0
    mprotect(0x413000, 4096, PROT_READ)     = 0
    open("/dev/i2c/0", O_RDWR|O_LARGEFILE)  = -1 ENOENT (No such file or directory)
    open("/dev/i2c-0", O_RDWR|O_LARGEFILE)  = 3
    ioctl(3, _IOC(0, 0x7, 0x5, 0), 0x7fa366d4) = 0 <--------------------- NOTE: This is the call that fails first
    ioctl(3, _IOC(0, 0x7, 0x3, 0), 0x36)    = 0
    ioctl(1, TIOCGWINSZ, 0x7fa36620)        = 0
    writev(1, [{iov_base="     0,8  1,9  2,a  3,b  4,c  5,"..., iov_len=43}, {iov_base="\n", iov_len=1}], 2     0,8  1,9  2,a  3,b  4,c  5,d  6,e  7,f
    ) = 44
    ioctl(3, _IOC(0, 0x7, 0x20, 0), 0x7fa36674) = 0
    ioctl(3, _IOC(0, 0x7, 0x20, 0), 0x7fa36674) = 0
    ioctl(3, _IOC(0, 0x7, 0x20, 0), 0x7fa36674) = 0
    writev(1, [{iov_base="00: 00fc ecfc 13ff              "..., iov_len=44}, {iov_base="\n", iov_len=1}], 200: 00fc ecfc 13ff                          
    ) = 45
    exit_group(0)                           = ?
    +++ exited with 0 +++
    root@Omega-DFEB:~# 
    

    But when I run the i2c example under strace -f we get:

    ...
    [pid  1744] write(1, "&{/dev/i2c-0 [I2C0] 0 0xe23dc}\n", 31&{/dev/i2c-0 [I2C0] 0 0xe23dc}
    ) = 31
    [pid  1744] write(1, "openerI2C.Open()\n", 17openerI2C.Open()
    ) = 17
    [pid  1744] openat(AT_FDCWD, "/dev/i2c-0", O_RDWR|O_LARGEFILE|O_CLOEXEC) = 5
    [pid  1744] epoll_ctl(4, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1860607744, u64=1860607744}}) = -1 EPERM (Operation not permitted)
    [pid  1744] epoll_ctl(4, EPOLL_CTL_DEL, 5, 0xc7cdac) = -1 EPERM (Operation not permitted)
    [pid  1744] write(1, "before ioctl call\n", 18before ioctl call
    ) = 18
    [pid  1744] ioctl(5, _IOC(_IOC_NONE, 0x7, 0x5, 0), 0xc50104) = -1 ENOTTY (Not a tty)
    [pid  1744] write(1, "returning error\n", 16returning error
    ) = 16
    [pid  1744] write(1, "I\302\262C buses available:\n", 22I²C buses available:
    ) = 22
    [pid  1744] write(1, "- /dev/i2c-0\n", 13- /dev/i2c-0
    ) = 13
    [pid  1744] write(1, "  0\n", 4  0
    )        = 4
    [pid  1744] write(1, "  I2C0\n", 7  I2C0
    )     = 7
    [pid  1744] openat(AT_FDCWD, "/dev/i2c-0", O_RDWR|O_LARGEFILE|O_CLOEXEC) = 6
    [pid  1744] epoll_ctl(4, EPOLL_CTL_ADD, 6, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1860607744, u64=1860607744}}) = -1 EPERM (Operation not permitted)
    [pid  1744] epoll_ctl(4, EPOLL_CTL_DEL, 6, 0xc7cd70) = -1 EPERM (Operation not permitted)
    
    
    ****************** This ioctl() fails ********************
    [pid  1744] ioctl(6, _IOC(_IOC_NONE, 0x7, 0x5, 0), 0xc50134) = -1 ENOTTY (Not a tty)
    
    
    [pid  1744] write(1, "returning error\n", 16returning error
    ) = 16
    [pid  1744] write(1, "  Failed to open: sysfs-i2c: ina"..., 59  Failed to open: sysfs-i2c: inappropriate ioctl for device) = 59
    [pid  1744] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x10} ---
    [pid  1744] rt_sigreturn()              = 0
    [pid  1744] nanosleep({tv_sec=0, tv_nsec=1000},  <unfinished ...>
    [pid  1746] <... futex resumed> )       = 1
    [pid  1744] <... nanosleep resumed> NULL) = 0
    [pid  1744] nanosleep({tv_sec=0, tv_nsec=1000},  <unfinished ...>
    [pid  1746] futex(0xc282b4, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
    [pid  1744] <... nanosleep resumed> NULL) = 0
    [pid  1744] write(2, "panic: ", 7panic: )      = 7
    [pid  1744] write(2, "runtime error: invalid memory ad"..., 64runtime error: invalid memory address or nil pointer dereference) = 64
    [pid  1744] write(2, "\n", 1
    )           = 1
    [pid  1744] write(2, "[signal ", 8[signal )     = 8
    [pid  1744] write(2, "SIGSEGV: segmentation violation", 31SIGSEGV: segmentation violation) = 31
    [pid  1744] write(2, " code=", 6 code=)       = 6
    [pid  1744] write(2, "0x1", 30x1)          = 3
    [pid  1744] write(2, " addr=", 6 addr=)       = 6
    [pid  1744] write(2, "0x10", 40x10)         = 4
    [pid  1744] write(2, " pc=", 4 pc=)         = 4
    [pid  1744] write(2, "0xe3ae0", 70xe3ae0)      = 7
    [pid  1744] write(2, "]\n", 2]
    )          = 2
    [pid  1744] write(2, "\n", 1
    )           = 1
    [pid  1744] write(2, "goroutine ", 10goroutine )  = 10
    [pid  1744] write(2, "1", 11)            = 1
    [pid  1744] write(2, " [", 2 [)           = 2
    [pid  1744] write(2, "running", 7running)      = 7
    [pid  1744] write(2, "]:\n", 3]:
    )         = 3
    [pid  1744] write(2, "main.ExampleAll", 15main.ExampleAll) = 15
    [pid  1744] write(2, "(", 1()            = 1
    [pid  1744] write(2, ")\n", 2)
    )          = 2
    [pid  1744] write(2, "\t", 1	)           = 1
    ...
    

    I've tried removing that ioctl() call and the same error occurs later:

    [pid  1720] openat(AT_FDCWD, "/dev/i2c-0", O_RDWR|O_LARGEFILE|O_CLOEXEC) = 6
    [pid  1720] epoll_ctl(4, EPOLL_CTL_ADD, 6, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1866661632, u64=1866661632}}) = -1 EPERM (Operation not permitted)
    [pid  1720] epoll_ctl(4, EPOLL_CTL_DEL, 6, 0x87cd6c) = -1 EPERM (Operation not permitted)
    [pid  1720] write(1, "returning i of I2C0\n", 20returning i of I2C0
    ) = 20
    
    ******************** This IOCTL fails ************************
    [pid  1720] ioctl(6, _IOC(_IOC_NONE, 0x7, 0x7, 0), 0x87cef4) = -1 ENOTTY (Not a tty)
    
    [pid  1720] clock_gettime(CLOCK_REALTIME, {tv_sec=1545341968, tv_nsec=65321400}) = 0
    [pid  1720] clock_gettime(CLOCK_MONOTONIC, {tv_sec=907, tv_nsec=372203156}) = 0
    [pid  1720] openat(AT_FDCWD, "/etc//localtime", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
    [pid  1720] write(2, "2018/12/20 21:39:28 sysfs-i2c: i"..., 622018/12/20 21:39:28 sysfs-i2c: inappropriate ioctl for device
    ) = 62
    [pid  1720] exit_group(1)               = ?
    [pid  1722] <... futex resumed>)        = ?
    [pid  1722] +++ exited with 1 +++
    [pid  1721] <... clock_gettime resumed> <unfinished ...>) = ?
    [pid  1721] +++ exited with 1 +++
    +++ exited with 1 +++
    root@Omega-DFEB:~# 
    

    I'm stumped. The device is opened differently though, i2cdump calls:

    open("/dev/i2c-0", O_RDWR|O_LARGEFILE)  = 3
    

    but golang calls:

    [pid  1744] openat(AT_FDCWD, "/dev/i2c-0", O_RDWR|O_LARGEFILE|O_CLOEXEC) = 6
    

    Could it be O_CLOEXEC? That looks entirely necessary as golang seems to fork a bunch...

    Any ideas?

  • gpio-read: bcm283x-gpio (GPIO7): pull cannot be used when subsystem gpiomem not initialized.

    gpio-read: bcm283x-gpio (GPIO7): pull cannot be used when subsystem gpiomem not initialized.

    Describe the bug A clear and concise description of what the bug is. While attempting to read from a GPIO pin on a RaspberryPi 1, I receive an error: gpio-read: bcm283x-gpio (GPIO7): pull cannot be used when subsystem gpiomem not initialized.

    To Reproduce Steps to reproduce the behavior:

    1. Run CLI commands to use periph tools
    go get periph.io/x/periph/cmd/...
    cd ~/go/bin
    ./gpio-read GPIO7
    
    1. Run it.
    2. See error

    Expected behavior A clear and concise description of what you expected to happen. I expect the pin to be set to read-mode, and a value returhed

    Platform (please complete the following information):

    • OS: Raspbian GNU/Linux 10 (buster)
    • Board: RaspberryPi 1

    This looks similar to #288, but I'm not running my Go code inside a docker container - just the plain logged-in user.

    I've also tried "granting" access to the devices listed in #288 via:

    sudo chmod a+rw /dev/gpiomem
    sudo chmod a+rw /dev/mem
    

    and I still get the error.

  • Unable to set GPIO pin pull on Raspberry Pi 4

    Unable to set GPIO pin pull on Raspberry Pi 4

    Describe the bug I am trying to configure a GPIO pin on the raspberry pi 4, more specifically the Pin number 29 (Connected to GPIO 5), and set it to pull down however when reading the pin it reports pull up.

    This works fine on a raspberry pi 3

    To Reproduce Steps to reproduce the behavior:

    1. Run program
    package main
    
    import (
    	"fmt"
    	"log"
    	"time"
    
    	"periph.io/x/periph/conn/gpio"
    	"periph.io/x/periph/host"
    	"periph.io/x/periph/host/rpi"
    )
    
    var (
    	readPin = rpi.P1_29
    )
    
    func main() {
    	fmt.Println("Initializing periph host...")
    	if _, err := host.Init(); err != nil {
    		log.Panicf("failed to initialize periph host: %v", err)
    	}
    
    	if err := readPin.In(gpio.PullDown, gpio.NoEdge); err != nil {
    		log.Panicf("failed to set read pin to In(): %v", err)
    	}
    
    	ticker := time.NewTicker(2 * time.Second)
    	want := gpio.Low
    
    	for {
    		select {
    		case <-ticker.C:
    			time.Sleep(time.Millisecond)
    			actual := readPin.Read()
    			if actual != want {
    				log.Printf("ERROR: Actual: %t != Wanted: %t", actual, want)
    				continue
    			}
    			log.Println("EVERYTHING WAS FINE")
    		}
    	}
    }
    
    1. Run it.
    2. See error Actual: true != Wanted: false

    Expected behavior It should set the Pin 29 to Pull Down (Meaning I get gpio.Low when reading it) thus printing only EVERYTHING WAS FINE

    Platform (please complete the following information):

    • OS: balenaOS 2.44.0+rev3 (64-bit BETA)
    • Raspberry Pi 4

    Additional context Compilation command: GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build main.go Periph version: v3.6.2 Go version: 1.13

    The code has been tested on several raspberry pi 3 without any issues

  • Support for BMP280

    Support for BMP280

    Hello,

    Can you please add support for the BMP280 sensor, i see that BME280 is supported which is basically the same (With the lack of humidity) but both sensors are backward and forward compatible, just the chip id is different 0x58 for BMP280 and 0x60 for BME280.

    Here's a image from official datasheet: datasheet https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf

    Thanks.

  • st7567: add experimental device driver for 128x64 dot matrix LCD

    st7567: add experimental device driver for 128x64 dot matrix LCD

    This adds experimental support for the st7567 LCD device which is used by the GFX HAT from Pimoroni.

    The example just places some pixels on the device and iterates over the possible contrast values, going into power save mode and waking up.

    The command line tool can take a PNG image and paints the black pixels onto the LCD.

    Example and command line tool have been tested with a GFX Hat.

  • onewire: experimental netlink-based bus master for Linux

    onewire: experimental netlink-based bus master for Linux

    This driver adds a gpio-based 1-wire master that uses the Linux netlink connector API to communicate with the w1 kernel module.

    Major caveat: the w1 netlink API does not support setting strong pull-ups after write operations. Devices such as the DS18B20 must be powered externally in order to work with this driver.

    Fixes #359

  • Set version of RPi for all known revisions

    Set version of RPi for all known revisions

    I needed to add support for the Raspberry Pi Zero W. I thought it would be wiser to specify revisions explicitly and I found a table here with an exhaustive list.

  • SH1106 support

    SH1106 support

    What kind of new feature are you looking for? (Keep the one that applies, please describe)

    • Hardware: SH1106

    Do you plan to:

    • contribute an initial driver in experimental: Yes
    • do all the work needed to get the driver promoted to _stable_¹: No

    We know the second question looks scary. Do not worry if you reply No to the stable question. It's still useful. It's still possible someone else will pick it up and finish the work.

    ¹ Wonder what it takes to promote a driver as stable? See https://periph.io/project/#driver-lifetime-management. A stable driver requires the smallest API surface, good unit test code coverage, good documentation and a page in https://periph.io/device/

  • improve arm64 support

    improve arm64 support

    • Hardware: rk3328
    • Software: linux 4.4.114

    on arm64 linux, syscall.EpollCreate failed with : function not implemented,so does gpio's WaitForEdge.

    we should use golang.org/x/sys/unix instead.

  • Getting PWM to work with Raspberry Pi Zero W

    Getting PWM to work with Raspberry Pi Zero W

    Hi,

    Whenever I use pi-blaster to output a pwm signal on a pin, it works correctly (the led turns on):

    sudo ./pi-blaster -D -g 18
    ...
    echo "18=0.75" > /dev/pi-blaster
    

    But when I try with periph, it doesn't work (I have no errors, but the pin doesn't output any current, the LED stays off):

    package main
    
    import (
    	"fmt"
    	"os"
    	"os/signal"
    	"time"
    
    	"periph.io/x/periph"
    	"periph.io/x/periph/conn/gpio"
    	"periph.io/x/periph/host/rpi"
    )
    
    func main() {
    	periph.Init()
    	p := rpi.P1_12 // GPIO18
    	pwm := p.(gpio.PinPWM)
    
    	err := pwm.PWM(gpio.Duty(50535), 100*time.Microsecond)
    	if err != nil {
    		fmt.Fprint(os.Stderr, err)
    		return
    	}
    
    	c := make(chan os.Signal, 1)
    	signal.Notify(c, os.Interrupt)
    	<-c
    }
    

    img_20171203_200641

  • Halt() does not unblock WaitForEdge()

    Halt() does not unblock WaitForEdge()

    According to the documentation, calling Halt() or In() on a pin should cause WaitForEdge() to unblock and return false. When I attempt to do this on a Raspberry Pi Zero W, however, WaitForEdge() does not become unblocked.

    package main
    
    import (
    	"fmt"
    	"time"
    
    	"periph.io/x/periph/conn/gpio"
    	"periph.io/x/periph/conn/gpio/gpioreg"
    	"periph.io/x/periph/host"
    )
    
    func main() {
    	if _, err := host.Init(); err != nil {
    		panic(err)
    	}
    
    	aPin := gpioreg.ByName("23")
    	aPin.In(gpio.PullUp, gpio.BothEdges)
    
    	go func() {
    		time.Sleep(1 * time.Second)
    
    		fmt.Println("calling Halt()")
    		aPin.Halt()
    		fmt.Println("called Halt()")
    	}()
    
    	fmt.Println("wait for edge")
    	aPin.WaitForEdge(-1)
    	fmt.Println("done waiting for edge")
    }
    

    This program will output:

    wait for edge
    calling Halt()
    called Halt()
    

    and then block indefinitely.

    Platform:

    • OS: Raspbian GNU/Linux 9
    • Board: Raspberry Pi Zero Wireless
  • environment: transfer and adapt Env and SenseEnv from physic into Weather and SenseWeather

    environment: transfer and adapt Env and SenseEnv from physic into Weather and SenseWeather

    As part of this work, make it use context.Context.

    The addition of the new packages can be done seamlessly in v3.5.0, but the removal of physic.Env and physic.SenseEnv is a breaking change.

  • conn: deprecate Halt()

    conn: deprecate Halt()

    Move the blocking operation context from the driver to the individual function call.

    See https://docs.google.com/document/d/1vQdZdoOMaIan7dKwcAzqHbfM_LCnnSMUQvqypRkjohM for more information.

    As such, Halt() will not be needed anymore.

  • gpio: add Group interface, to act on multiple GPIO as a single transaction

    gpio: add Group interface, to act on multiple GPIO as a single transaction

    https://periph.io/x/periph/conn/gpio doesn't enable acting on multiple GPIOs simultaneously. This is useful to simulate a protocol, for example with bitbang.

    Up to now the only API that exposes something close to that is https://periph.io/x/periph/host/bcm283x#PinsSet0To31 and https://periph.io/x/periph/host/bcm283x#PinsClear0To31. The https://periph.io/x/extra/hostextra/d2xx driver would also enable this but lack of clear API meant this functionality is not exposed. But these two are still fairly limited in scope.

    #371 would make make this much more available, as synchronized GPIO I/O could be done on any system running the linux kernel 4.8 or later. To expose this functionality, an API has to be designed first.

    Designing an API is challenging, as for proper synchonization, the operation must be hardware assisted. This means that GPIOs cannot be mix-and-matched, they must all belong to the same "GPIO source". There is no such concept at the moment, so this much be created first.

A directory of hardware related libs, tools, and tutorials for Go

Go + hardware This repo is a directory of tools, packages and tutorials to let you introduce Go in your hardware projects. Why Go? Go can target platf

Dec 30, 2022
ghw - Golang HardWare discovery/inspection library
ghw - Golang HardWare discovery/inspection library

ghw - Golang HardWare discovery/inspection library ghw is a small Golang library providing hardware inspection and discovery for Linux and Windows.

Jan 7, 2023
Golang PoC software for reliable file transfers over a data diode. DIY gigabit data diode hardware instructions
Golang PoC software for reliable file transfers over a data diode. DIY gigabit data diode hardware instructions

DIY Data Diode Simple DIY gigabit data diode (hardware and software). Presented at SEC-T 2021. Hardware By doing a simple hardware mod to a fiber conv

Dec 1, 2022
Server motherboard hardware monitoring

hardware-events This software helps with the monitoring of a server motherboard. The project started when I changed the FANs on a Supermicro motherboa

Jan 24, 2022
A golang CTF competition platform with high-performance, security and low hardware requirements.
A golang CTF competition platform with high-performance, security and low hardware requirements.

CTFgo - CTF Platform written in Golang A golang CTF competition platform with high-performance, security and low hardware requirements. Live Demo • Di

Oct 20, 2022
Uniform interface for interacting with network hardware via telnet/ssh

jgivc/console This package provides a uniform interface for interacting with network hardware via telnet/ssh This package uses part of reiver/go-telne

Dec 9, 2021
Hw-keyboard-remapper - This is key code remapper for the hardware keyboard

hw-keyboard-remapper hw-keyboard-remapper is key remapper independent the OS. ht

Jan 11, 2022
Thdl is a tool for easing the work with hardware description languages.
Thdl is a tool for easing the work with hardware description languages.

THDL Thdl is a tool for easing the work with hardware description languages. It is (and will always be) based solely on text processing, with no seman

Nov 17, 2022
Go package for the BeagleBone open source hardware

go-beaglebone Go package for the BeagleBone open source hardware Also check out https://github.com/SpaceLeap/go-embedded This package builds on top of

Jul 6, 2019
Go library for hardware I/O control, in the programming style of Arduino

hwio Introduction hwio is a Go library for interfacing with hardware I/O, particularly on SoC-based boards such as BeagleBone Black, Raspberry Pi and

Dec 9, 2022
Easy to use open source hardware to drive WS2811 LEDs with high-quality color

STOP DOING FADECANDY LEDs were not supposed to be given data pins YEARS of "temporal dithering" but no real-world use found for having more than three

Dec 29, 2022
Generate vector tiles for the entire planet on relatively low spec hardware.
Generate vector tiles for the entire planet on relatively low spec hardware.

Sequentially Generate Planet Mbtiles Sequentially generate and merge an entire planet.mbtiles vector tileset on low memory/power devices for free. com

Dec 21, 2022