google/periph

MFRC522 hang on WaitForEdge

System-Glitch opened this issue · 2 comments

Describe the bug
I'm using the MFRC522 example to read data on a Mifare Classic tag without authentication on a Raspberry Pi 4B (Raspbian and SPI enabled). I changed the key to key := [6]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} and the auth method to PICC_AUTHENT1A.

The program hangs on irqChannel <- r.irqPin.WaitForEdge(timeout) in LowLevel.WaitForEdge until timeout, then writing "Didn't receive device data". If I edit the lib's code and change this line to irqChannel <- true, everything works perfectly.

To Reproduce
Steps to reproduce the behavior:

  1. Pin layout:
RC522 Pin Raspberry Pi Pin
3.3V Pin 1
RST Pin 22
GND Pin 9
MISO Pin 21
MOSI Pin 19
IRQ Pin 18
SCK Pin 23
SDA Pin 24
  1. Run program in debugger
package main

import (
	"fmt"
	"log"
	"time"

	"periph.io/x/periph/conn/spi/spireg"
	"periph.io/x/periph/experimental/devices/mfrc522"
	"periph.io/x/periph/experimental/devices/mfrc522/commands"
	"periph.io/x/periph/host"
	"periph.io/x/periph/host/rpi"
)

func main() {

	// Make sure periph is initialized.
	if _, err := host.Init(); err != nil {
		log.Fatal(err)
	}

	// Using SPI as an example. See package ./spi/spireg for more details.
	p, err := spireg.Open("")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(p)
	defer p.Close()

	rfid, err := mfrc522.NewSPI(p, rpi.P1_22, rpi.P1_18)
	if err != nil {
		log.Fatal(err)
	}

	// Idling device on exit.
	defer rfid.Halt()

	// Setting the antenna signal strength.
	rfid.SetAntennaGain(5)

	key := [6]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}

	timedOut := false
	cb := make(chan []byte)
	timer := time.NewTimer(10 * time.Second)

	// Stopping timer, flagging reader thread as timed out
	defer func() {
		timer.Stop()
		timedOut = true
		close(cb)
	}()

	go func() {
		log.Printf("Started %s", rfid.String())

		for {
			// Trying to read data from sector 8 block 0
			data, err := rfid.ReadCard(10*time.Second, byte(commands.PICC_AUTHENT1A), 2, 0, key)

			// If main thread timed out just exiting.
			if timedOut {
				return
			}

			// Some devices tend to send wrong data while RFID chip is already detected
			// but still "too far" from a receiver.
			// Especially some cheap CN clones which you can find on GearBest, AliExpress, etc.
			// This will suppress such errors.
			if err != nil {
				continue
			}

			cb <- data
			return
		}
	}()

	for {
		select {
		case <-timer.C:
			log.Fatal("Didn't receive device data")
			return
		case data := <-cb:
			log.Println(data)
			return
		}
	}

}

Goroutine should hang at the line mentioned above.

Expected behavior

IRQ WaitForEdge should not time out.

Platform:

  • OS: Raspbian 10 buster
  • Board Raspberry Pi 4B

Thanks for the report. I fear this is related to issue #432 or issue #425.

I suspect periph/devices@7cccb95 fixed it. Please update to periph.io/x/devices/v3/mfrc522 and file a bug at https://github.com/periph/devices if it still reproduces.