Skip to content

rp2040: SPI implementation #1991

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

Merged
merged 1 commit into from
Jul 31, 2021
Merged

Conversation

soypat
Copy link
Contributor

@soypat soypat commented Jul 9, 2021

Not tested yet. I've never contributed before and looking forward to learning what the workflow looks like. Solves #1987

@soypat
Copy link
Contributor Author

soypat commented Jul 11, 2021

Let me know of any comments so I can apply fixes and suggestions to i2c and PWM implementation branches!

@soypat soypat changed the title first revision of rp2040 SPI rp2040: SPI implementation Jul 11, 2021
@efectn
Copy link

efectn commented Jul 12, 2021

Have you tested yet? If not, i can test when i'm free.

@soypat
Copy link
Contributor Author

soypat commented Jul 12, 2021

Have you tested yet? If not, i can test when i'm free.

@efectn I have not. Having trouble building TinyGo :(

@soypat
Copy link
Contributor Author

soypat commented Jul 15, 2021

I've managed to build tinygo and flash programs to the pico. Currently dont have SPI devices on hand so I'll probably be PRing the i2c branch as soon as I get it working and then fix this branch (already noticed a couple bugs in how I use ReplaceBits)

@soypat soypat marked this pull request as draft July 24, 2021 17:04
@soypat
Copy link
Contributor Author

soypat commented Jul 25, 2021

So I have not gotten the driver working. I'm going to take a break from this driver and try the PWM out. I've managed to get the Loopback function working but struggling reading data from my SPI device (see details below).

Example program with loopback test
package main

import (
	"device/rp"
	"machine"
	"time"
)

var (
	LED  = machine.GPIO25
	b    = machine.SPI{Bus: rp.SPI0}
	uart = machine.UART0
	MISO = machine.GPIO4
	CS   = machine.GPIO5
	SCK  = machine.GPIO6
	MOSI = machine.GPIO7
)

func main() {
	// configure UART to print stuff
	{
		err := uart.Configure(machine.UARTConfig{BaudRate: 9600})
		if err != nil {
			panic(err)
		}
	}
	println("start program")
	time.Sleep(time.Millisecond)

	err := b.Configure(machine.SPIConfig{Frequency: 8.1e6,
		SDO: MOSI,
		SDI: MISO,
		SCK: SCK})

	if err != nil {
		println(err.Error())
	} else {
		println("spi baud:", b.GetBaudRate())
	}
	// Loopback test.
	b.Bus.SSPCR1.SetBits(rp.SPI0_SSPCR1_LBM)
	for i := 0; i < 10; i++ {
		ret, err := b.Transfer(uint8(i))
		if err != nil {
			println(err.Error())
		}
		println(i, ret)
	}
	// Output:
	// 0 0
	// 1 1
	// 2 2
	// 3 3
	// 4 4
	// 5 5
	// 6 6
	// 7 7
	// 8 8
	// 9 9
	// End loopback test.
	b.Bus.SSPCR1.ClearBits(rp.SPI0_SSPCR1_LBM)

	LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
	CS.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
	CS.Configure(machine.PinConfig{Mode: machine.PinOutput})
	CS.High() // Motorola SPI has Active Low.
	// Do SPI stuff
	for { // blinky when done.
		time.Sleep(time.Second)
		LED.Set(!LED.Get())
	}
}

@soypat soypat marked this pull request as ready for review July 28, 2021 02:45
@deadprogram
Copy link
Member

In order to test this on my rp2040 pico board, I had to add the following code:

diff --git a/src/machine/board_pico.go b/src/machine/board_pico.go
index 3a4d67b..e60fbec 100644
--- a/src/machine/board_pico.go
+++ b/src/machine/board_pico.go
@@ -2,6 +2,10 @@
 
 package machine
 
+import (
+       "device/rp"
+)
+
 // GPIO pins
 const (
        GP0  Pin = GPIO0
@@ -37,3 +41,18 @@ const (
        // Onboard crystal oscillator frequency, in MHz.
        xoscFreq = 12 // MHz
 )
+
+// SPI pins
+const (
+       SPI0_SCK_PIN Pin = GPIO18
+       SPI0_SDO_PIN Pin = GPIO19
+       SPI0_SDI_PIN Pin = GPIO16
+)
+
+// SPI on the RP2040
+var (
+       SPI0  = &_SPI0
+       _SPI0 = SPI{
+               Bus: rp.SPI0,
+       }
+)

SPI0 needs to be hooked up to a specific bus for it to be able to be used. The pin definitions are just added for clarity. See my comments above.

@deadprogram
Copy link
Member

By the way, the SPI interface worked on my pico using an APA102 LED strip. Good work @soypat!

@deadprogram
Copy link
Member

I think you still need to add the following to machine_rp2040.go:

// SPI on the RP2040
var (
	SPI0  = &_SPI0
	_SPI0 = SPI{
		Bus: rp.SPI0,
	}
	SPI1  = &_SPI1
	_SPI1 = SPI{
		Bus: rp.SPI1,
	}
)

Add that, and squash everything into a single commit, and I think we are about ready to merge this! 😸

spi working with loopback

SPI working

apply @deadprogram's suggestions

consolidate SPI board pin naming

fix up SPI configuration

add feather-rp2040 SPI pins

add arduino connect SPI pins

add SPI handle variables
@deadprogram
Copy link
Member

Thanks very much for all the work on this PR! Now merging.

@deadprogram deadprogram merged commit 98e70c9 into tinygo-org:dev Jul 31, 2021
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

Successfully merging this pull request may close these issues.

3 participants