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

EdgeDetection crashes Raspberry Pi 3 #35

Closed
eyJhb opened this issue Nov 26, 2018 · 16 comments
Closed

EdgeDetection crashes Raspberry Pi 3 #35

eyJhb opened this issue Nov 26, 2018 · 16 comments

Comments

@eyJhb
Copy link

eyJhb commented Nov 26, 2018

Using Detect and running a very basic program on the Raspberry Pi 3, will result in the whole Raspberry Pi locking up (and needing a forced restart).
This only happens on a pin with very many rises/falls, currently I am using this for a RF receiver, so there are quite a lot of rises/falls.

The code I am using is this ...

package main

import (
	"fmt"
	"time"

	rpio "github.com/stianeikeland/go-rpio"
)

// This program is just going to be
// a POC of the sender working.
// This should and WILL be cleaned up
// I do not care, I will not fucking
// write the report without having
// the time to do this properly

// Raspberry Pi 3 GPIO
// https://i.imgur.com/PPFf2ul.png
const rx_pin_nr = 2

var preamble = [8]int{1, 0, 1, 0, 1, 0, 1, 0}
var sfd = [8]int{1, 0, 1, 0, 1, 0, 1, 1}
var rx_pin rpio.Pin

func main() {
	// initialize go-rpio
	err := rpio.Open()

	if err != nil {
		fmt.Println(err)
	}

	// set our pin as a output
	rx_pin = rpio.Pin(rx_pin_nr)
	rx_pin.Input()
	rx_pin.Detect(rpio.RiseEdge)

	for {
		// sendData(test)
		fmt.Println("Running stuff")
		time.Sleep(100 * time.Millisecond)
	}
}

func check_sync() {

}

Not even doing anything with it. I don't know what the solution would be, but I think that we could get the interrupt etc. if we used such a system as epoll (http://man7.org/linux/man-pages/man7/epoll.7.html), I know it is uses for another Go system for GPIO interaction here - https://godoc.org/github.com/kidoman/embd

@eyJhb
Copy link
Author

eyJhb commented Nov 26, 2018

Edit, it is done using this - https://golang.org/pkg/syscall/#EpollCreate1

@drahoslove
Copy link
Collaborator

drahoslove commented Nov 27, 2018

Hi,
this seems to be the same issue as in #33, (which I am not able to reproduce, unfortunately). Does it freeze every time as soon as Detect method is called, or only when you connect it to RF receiver and generate some edges?

Could you provide me more info about your environment?

The approach using epoll seems interesting, I'll take the closer look into it sometime.

@eyJhb
Copy link
Author

eyJhb commented Nov 27, 2018 via email

@drahoslove
Copy link
Collaborator

Greate, also:

  1. Post output of hexdump -C /proc/device-tree/soc/ranges please. If the file does not exists try to upgrade your raspbian. (rPi3 uses different memmory base for mapping pheriperals registers, but if this file does not exists, it falls back to range for older Pi versions, which will cause the trouble on newer Pies)

  2. If you are not compiling on Pi directy, but using crosscompiling, don't forget to set GOARM=6. This was the isssue in Raspberry Pi Zero W compatibility issue #25.

@eyJhb
Copy link
Author

eyJhb commented Nov 27, 2018

  1. Using the newest version of raspbian downloaded from raspberrypi.org three days ago (and ran update/upgrade)
  2. Going a direct go run main.go when running my code.

But I will check number 1 tomorrow to make sure! :)

@eyJhb
Copy link
Author

eyJhb commented Nov 28, 2018

Setup

  • Raspberry Pi 3 model B v1.2
  • RF sender/receiver here
  • Power supply for RPi here - sometimes relevant for issues on the RPi..

Running the latest version of Raspbian (2018-11-13-raspbian-stretch-lite), having the latests updates using sudo apt update && sudo apt upgrade -y

pi@hub:~ $ uname -a
Linux hub 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l GNU/Linux
pi@hub:~ $ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.6 (stretch)
Release:	9.6
Codename:	stretch
pi@hub:~ $ 

Code execution

Running the code below WITHOUT the RF receiver attached, prints "works" and then exists the program and everything works fine.
But attaching the RF receiver, it will print out works and then just completely freeze up and I cannot ping the host, nmap it, ssh into it or anything. I need to unplug the power and plug it in again.

Currently I am just using the polling method, and checking the state each time.
There are not that many rises and falls, but it does of course still have some jitter sometimes.

main.go

package main

import (
	"fmt"
	"time"

	rpio "github.com/stianeikeland/go-rpio"
)

func main() {
	// initialize go-rpio
	err := rpio.Open()

	if err != nil {
		fmt.Println(err)
	}

	// set our pin as a output
	rx_pin := rpio.Pin(2)
	rx_pin.Input()
	rx_pin.Detect(rpio.RiseEdge)
	fmt.Println("Works..")
}

Output from hexdump

00000000  7e 00 00 00 3f 00 00 00  01 00 00 00 40 00 00 00  |~...?.......@...|
00000010  40 00 00 00 00 00 10 00                           |@.......|
00000018

Final notes

If you lived nearby, I would be able to give you a module for testing (if the university agrees), but doesn't look like it.

Please say if you need anymore information from me ! Or need me to test some more ;)

@drahoslove
Copy link
Collaborator

drahoslove commented Nov 28, 2018

Thanks for the info!
Everything looks fine, so I'm not sure what the problem is. But there are some ideas:

  1. Make sure you have disabled I2C interface in sudo raspi-config - I think it might be enabled by default which might cause your pin 2 to be changed from input mode to I2C.

  2. Are you sure your RF receiver is attached correctly? It seems it works at 5V, but GPIO pins are 3.3V so you should use the appropriate resistor at pin 2 to reduce the voltage.

  3. Not sure how the receiver works, but pin 2 on Pi has built'in 1.8kΩ pull-up resistor. You might try to use another pin for data, eg. 22 - and add rx_pin.PullDown() to your code - this would make more sense to me for detecting rising edges (but it might not be necessary for this receiver, I'm not too good at reading electrical diagrams, you probably know better).

  4. Does the system freeze when you try to emulate the activity on the data pin by hand? Eg. connect pin 2 using wire directly with GND/3.3V? Does it freeze when connecting to 5V? - this would point to 1)

And, I'm from Brno in the Czech Republic. I Guess you are from Germany? 🗺️ 🤔

@eyJhb
Copy link
Author

eyJhb commented Nov 29, 2018

Me neither.. It seems quite weird..

  1. I have tried disabling it in sudo raspi-config (though it looked like it was already disabled).
  2. Quite sure it is attached correctly, as everything works if I use it using polling (I can send and receive data using this without a hitch).
  3. Tried using pin 22 instead which still resulted in the previous behaviour. Added the rx_pin.PUllDown() and results in the previous behaviour.
  4. I have ran the tests for this lib running go test -v, with the connected pins (pin 2 connected to pin 3) which passed without complications (which should have been enough I would think?).

Denmark but close! Seems like quite a stretch.
But are there anything that I would be able to do from this point out, to debug it?
I am not new to debugging various code, but since this is some hardware interaction, I am not that trained in it (yet).

@drahoslove
Copy link
Collaborator

That is really some kind of magic.

Maybe pi just can't handle faster changes.
You can edit the test file and use pin in Clock mode, and gradually increase the frequency to see if there is problem in that. Actually I can do this myself.

Also we can try to use "asynchronous" GPAREN/GPAFEN registers for detection instead of "synchronous" GPREN/GPFEN registers. The difference is the synchronous looking for 011/100 patterns, and the other dont - so they should be able to detect even shorter pulses. Just change lines 351/352 in rpio.go to

renReg := p/32 + 31
fenReg := p/32 + 34

See chapter 6.1 in https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf if you are interested in details.

@roffe
Copy link

roffe commented Nov 30, 2018

package main

import (
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"os"
	"os/signal"
	"sync"
	"time"
)

func pour(pin rpio.Pin, sleep time.Duration) {
	fmt.Printf("Pouring: %f\n", sleep.Seconds())
	pin.High()
	time.Sleep(sleep)
	pin.Low()
	return
}

func main() {
	defer rpio.Close()
	if err := rpio.Open(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	Relay1 := rpio.Pin(18)
	Relay2 := rpio.Pin(22)
	Relay3 := rpio.Pin(26)

	Input1 := rpio.Pin(6)
	Input1.PullUp()

	Relay1.Output()
	Relay2.Output()
	Relay3.Output()

	Relay1.Low()
	Relay2.Low()
	Relay3.Low()

	Input1.Detect(rpio.FallEdge)

	fmt.Println("press button")

	for i := 0; i < 2; {
		if Input1.EdgeDetected() { // check if event occured
			fmt.Println("button pressed")
			pour(Relay1, 2*time.Second)
			pour(Relay2, 3*time.Second)
			i++
		}
		time.Sleep(5 * time.Second)
	}

	Input1.Detect(rpio.NoEdge) // disable edge event detection

}

this code crashes my Rpi3 as well after a button press is detected, it runs the first pour() then pi hardlocks and i have to pull power cable

Pin6 is connected to GND via a push button

@drahoslove
Copy link
Collaborator

drahoslove commented Nov 30, 2018

Solved!
tl;dr:
Add dtoverlay=gpio-no-irq to /boot/config.txt and restart your pi.

Explanation:
Thanks, roffe, for the example - finally something I could reproduce.
I realized that the difference between the unit test which works fine and the cases where something useful is connected to pin is that the number of edges generated is much higher than the number of calls to EdgeDetected(). (Single button press generates many edges too due to "switch bounce effect".)

Every edge event generates interruption as the side effect, but these are not handled by the system and after some number of unhandled interruptions it freezes.

In some update of Linux kernel (to which I switched after implementing the event detection functionality) the way the interruptions are handled changed. It worked before "by accident".
More info here: raspberrypi/linux#2550 (comment)

The solution above will disable all gpio interruption requests. But it is just workaround since it might break some other programs. Therefore I'll try to figure out a better solution. Either by disabling irq from within go-rpio, or better by reimplementing the detection functionality and actually handle the interruptions.

But disabling irq using dtoverlay in config should be good enough for now.

@roffe
Copy link

roffe commented Nov 30, 2018

@Drahoslav7 awesome, i'll have results in a few minutes after testing dtoverlay=gpio-no-irq

@roffe
Copy link

roffe commented Nov 30, 2018

@Drahoslav7 my code works like a charm with the dtoverlay setting no more freeze, thank you!

@drahoslove
Copy link
Collaborator

I'm happy we figured it out.
Hope it works for @eyJhb as well. Feel free to reopen this if not.

@eyJhb
Copy link
Author

eyJhb commented Nov 30, 2018

@Drahoslav7 haven't had time to test it, currently in the mid of getting all the code to work together before the deadline.
Will test it out :) - But wouldn't it be awesome, to have actual interrupts?

@wjessop
Copy link

wjessop commented Sep 6, 2023

I had this issue on my Pi 4B running the program as root. Adding dtoverlay=gpio-no-irq to the boot config fixed it. Using go-rpio v4.6.0.

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

No branches or pull requests

4 participants