Python – Golang and SPI – attempted to initialize the RF522 drive

Golang and SPI – attempted to initialize the RF522 drive… here is a solution to the problem.

Golang and SPI – attempted to initialize the RF522 drive

I have a simple Python code to initialize MFRC522 device correct:

    import spidev

mode_reset = 0x0F

def spi_transfer(data):
        r = spi.xfer2(data)
        return r

def dev_write(address, value):
        r = spi_transfer([(address << 1) & 0x7E, value])
        print(">>",[(address << 1) & 0x7E, value], r)
        return r

def reset():
        dev_write(0x01, mode_reset)

spi = spidev. SpiDev()
    spi.open(0, 0)
    spi.max_speed_hz = 1000000
    print(spi.mode, spi.bits_per_word, spi.lsbfirst)
    reset()

Works just fine – it returns command code 15, but the same initialization routine implemented in Go doesn’t really work :

    package main

import (
        "fmt"
        "golang.org/x/exp/io/spi"
        "log"
    )

func main() {

spiDev, err := spi. Open(&spi. Devfs{
            Dev:      "/dev/spidev0.0",
            Mode:     spi. Mode(spi. Mode0),
            MaxSpeed: int64(1000000),
        })

spiDev.SetMode(spi. Mode0)
        spiDev.SetBitOrder(spi. MSBFirst)
        spiDev.SetBitsPerWord(8)

if err != nil {
            .log. Fatal(err)
        }

writeSpiData := func(dataIn []byte) (out []byte, err error) {
            out = make([]byte, len(dataIn))
            err = spiDev.Tx(dataIn, out)
            return
        }

devWrite := func(address int, data byte) (err error) {
            newData := [2]byte{(byte(address) << 1) & 0x7E, data}
            readBuf, err := writeSpiData(newData[0:])
            fmt. Println(">>", newData, readBuf)
            return
        }

if err != nil {
            .log. Fatal(err)
        }

devWrite(0x01, 0x0F)

fmt. Println("Done")

}

This one returns [0 0] which is wrong. Does anyone know what could have gone wrong there?

Solution

It looks like the SPI module in the Go release is not working as expected. I did some research using some logic analyzers and realized that the SPI command layer from exp/io/spi does not generate the appropriate commands.

Source code:

package main

import (
    "fmt"
    "golang.org/x/exp/io/spi"
    "log"
)

func main() {

spiDev, err := spi. Open(&spi. Devfs{
        Dev:      "/dev/spidev0.0",
        MaxSpeed: int64(1000000),
    })

spiDev.SetMode(spi. Mode0)
    spiDev.SetBitOrder(spi. MSBFirst)
    spiDev.SetBitsPerWord(8)

if err != nil {
        .log. Fatal(err)
    }

writeSpiData := func(dataIn []byte) (out []byte, err error) {
        out = make([]byte, len(dataIn))
        err = spiDev.Tx(dataIn, out)
        return
    }

devWrite := func(address int, data byte) (err error) {
        newData := [2]byte{(byte(address) << 1) & 0x7E, data}
        readBuf, err := writeSpiData(newData[0:])
        fmt. Println(">>", newData, readBuf)
        return
    }

if err != nil {
        .log. Fatal(err)
    }

devWrite(0x01, 0x0F)

fmt. Println("Done")

}

Result data log:

enter image description here

Now there is another driver, https://github.com/ecc1/spi the code is as follows:

package main

import (
    "fmt"
    "log"
    "github.com/ecc1/spi"
)

func main() {

spiDev, err := spi. Open("/dev/spidev0.0", 1000000, 0)

spiDev.SetMode(0)
    spiDev.SetBitsPerWord(8)
    spiDev.SetLSBFirst(false)
    spiDev.SetMaxSpeed(1000000)

if err != nil {
        .log. Fatal(err)
    }

writeSpiData := func(dataIn []byte) (err error) {
        err = spiDev.Transfer(dataIn)
        return
    }

devWrite := func(address int, data byte) (err error) {
        newData := [2]byte{(byte(address) << 1) & 0x7E, data}
        fmt. Print("<< ", newData, " ")
        err = writeSpiData(newData[0:])
        fmt. Println(">>", newData)
        return
    }

if err != nil {
        .log. Fatal(err)
    }

devWrite(0x01, 0x0F)

if err != nil {
        .log. Fatal(err)
    }

}

And the generated protocol dump is correct:

enter image description here

Related Problems and Solutions