drivers icon indicating copy to clipboard operation
drivers copied to clipboard

sx127x LoRa example possible deadlock

Open soypat opened this issue 2 years ago • 11 comments

Steps to recreate

  • I've modified the sx127x.New function to accept a drivers.SPI instead of a machine.SPI
  • I've modified the example for the sx127x to run on the pico. See dropdown click box:

What I expected

Forever looping to catch LoRa packets and broadcast packets.

What happened

Program crashes on err := loraRadio.Tx(txmsg, LORA_DEFAULT_TXTIMEOUT_MS). Program stops executing and prints p.

I've tracked the crash to happen during or after this line. I suspect the program deadlocks since it is waiting for an event.

package main

// This example code demonstrates Lora RX/TX With SX127x driver
// You need to connect SPI, RST, CS, DIO0 (aka IRQ) and DIO1 to use.

import (
	"machine"
	"time"

	"tinygo.org/x/drivers/lora"
	"tinygo.org/x/drivers/sx127x"
)

const (
	LORA_DEFAULT_RXTIMEOUT_MS = 1000
	LORA_DEFAULT_TXTIMEOUT_MS = 5000
)

var (
	loraRadio *sx127x.Device
	txmsg     = []byte("Hello TinyGO")

	// We assume LoRa Featherwing module is connected to Raspberry Pi Pico:
	SX127X_PIN_RST  = machine.GP16
	SX127X_PIN_DIO0 = machine.GP6
	SX127X_PIN_DIO1 = machine.GP7
	// SPI definition for SX127x
	SX127X_SPI     = machine.SPI0
	SX127X_PIN_SCK = machine.GP2
	SX127X_PIN_TX  = machine.GP3
	SX127X_PIN_RX  = machine.GP4
	SX127X_PIN_CS  = machine.GP5
)

func dioIrqHandler(machine.Pin) {
	loraRadio.HandleInterrupt()
}

func main() {
	time.Sleep(5 * time.Second)
	println("\n# TinyGo Lora RX/TX test")
	println("# ----------------------")
	// machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
	SX127X_PIN_RST.Configure(machine.PinConfig{Mode: machine.PinOutput})

	SX127X_SPI.Configure(machine.SPIConfig{
		Frequency: 500000, Mode: 0,
		SCK: SX127X_PIN_SCK,
		SDO: SX127X_PIN_TX,
		SDI: SX127X_PIN_RX,
	})

	println("main: create and start SX127x driver")
	loraRadio = sx127x.New(SX127X_SPI, SX127X_PIN_RST)
	loraRadio.SetRadioController(sx127x.NewRadioControl(SX127X_PIN_CS, SX127X_PIN_DIO0, SX127X_PIN_DIO1))

	loraRadio.Reset()
	state := loraRadio.DetectDevice()
	if !state {
		panic("main: sx127x NOT FOUND !!!")
	} else {
		println("main: sx127x found")
	}

	// Prepare for Lora Operation
	loraConf := lora.Config{
		Freq:           lora.MHz_868_1,
		Bw:             lora.Bandwidth_125_0,
		Sf:             lora.SpreadingFactor9,
		Cr:             lora.CodingRate4_7,
		HeaderType:     lora.HeaderExplicit,
		Preamble:       12,
		Iq:             lora.IQStandard,
		Crc:            lora.CRCOn,
		SyncWord:       lora.SyncPrivate,
		LoraTxPowerDBm: 20,
	}

	loraRadio.LoraConfig(loraConf)

	var count uint
	for {
		tStart := time.Now()

		println("main: Receiving Lora for 10 seconds")
		for time.Since(tStart) < 10*time.Second {
			buf, err := loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
			if err != nil {
				println("RX Error: ", err)
			} else if buf != nil {
				println("Packet Received: len=", len(buf), string(buf))
			}
		}
		println("main: End Lora RX")
		println("LORA TX size=", len(txmsg), " -> ", string(txmsg))
		err := loraRadio.Tx(txmsg, LORA_DEFAULT_TXTIMEOUT_MS)
		if err != nil {
			println("TX Error:", err.Error())
		}
		count++
	}

}

soypat avatar Apr 08 '23 16:04 soypat

See the tinyglobo repo for a working example.

deadprogram avatar Apr 08 '23 16:04 deadprogram

I have used this board for a couple of talks and demos without problems. @soypat if you have a specific reproducer please do provide.

deadprogram avatar Jun 06 '23 07:06 deadprogram

There is a Details html dropdown in the issue description with the program I used: https://github.com/tinygo-org/drivers/issues/542#issue-1659571633

soypat avatar Jun 07 '23 00:06 soypat

What hardware did you use for the SX127x? Was it actually the featherwing? In which case, how did you connect the jumpers on the featherwing itself? https://github.com/tinygo-org/drivers/tree/release/sx127x#connecting

deadprogram avatar Jun 08 '23 12:06 deadprogram

Hmm, I'm not sure I understand the RST -> A CS -> B DIO1 -> C IRQ -> D comment. I was using regular commercial SX1278s working at 433MHz. I did the intuitive thing and looked at the code to know where to connect the pins. both DIO0, DIO1, RST, CS, SPI pins. Below is an image of the device used image

soypat avatar Jun 09 '23 04:06 soypat

Using TinyGo 0.28.1 with Pybadge+Featherwing

PXL_20230620_210731076

$ tinygo flash -target pybadge -monitor ./examples/sx127x/lora_rxtx/
Connected to /dev/ttyACM0. Press Ctrl-C to exit.

# TinyGo Lora RX/TX test
# ----------------------
main: create and start SX127x driver
main: sx127x found
main: Receiving Lora for 10 seconds
main: End Lora RX
LORA TX size= 12  ->  Hello TinyGO
main: Receiving Lora for 10 seconds
main: End Lora RX
LORA TX size= 12  ->  Hello TinyGO
main: Receiving Lora for 10 seconds
main: End Lora RX
LORA TX size= 12  ->  Hello TinyGO
main: Receiving Lora for 10 seconds
main: End Lora RX
LORA TX size= 12  ->  Hello TinyGO
main: Receiving Lora for 10 seconds
main: End Lora RX
LORA TX size= 12  ->  Hello TinyGO
main: Receiving Lora for 10 seconds

This is the code I am running: https://github.com/tinygo-org/drivers/blob/release/examples/sx127x/lora_rxtx/lora_rxtx.go

deadprogram avatar Jun 20 '23 21:06 deadprogram

        SX127X_SPI.Configure(machine.SPIConfig{
		Frequency: 500000, Mode: 0,
		SCK: SX127X_PIN_SCK,
		SDO: SX127X_PIN_TX,
		SDI: SX127X_PIN_RX,
	})

@soypat don't you actually want this?

SDI: SX127X_PIN_TX,
SDO: SX127X_PIN_RX,

deadprogram avatar Jun 20 '23 21:06 deadprogram

don't you actually want this?

Maybe? Not sure. Been a while since I had that setup running.

My current setup has Tx,Rx pins set up correctly and works OK without the gosched() calls introduced in TinyGo 0.28.1

soypat avatar Jun 25 '23 01:06 soypat