aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKenneth Bell <[email protected]>2021-04-11 08:28:04 -0700
committerRon Evans <[email protected]>2021-04-21 21:09:41 +0200
commit25f3adb47ec715234599bb0d892ad79277400a5b (patch)
treecc1a4a54ffea3c4e4d094f72baa3417390cc37d7
parentb9043b649df2933d294813daa480a381619c1c7b (diff)
downloadtinygo-25f3adb47ec715234599bb0d892ad79277400a5b.tar.gz
tinygo-25f3adb47ec715234599bb0d892ad79277400a5b.zip
stm32: support SPI on L4 series
m---------lib/stm32-svd0
-rw-r--r--src/machine/board_nucleol432kc.go50
-rw-r--r--src/machine/machine_stm32_spi.go16
-rw-r--r--src/machine/machine_stm32f103.go4
-rw-r--r--src/machine/machine_stm32f405.go4
-rw-r--r--src/machine/machine_stm32f407.go4
-rw-r--r--src/machine/machine_stm32l0.go4
-rw-r--r--src/machine/machine_stm32l4.go64
-rw-r--r--src/machine/spi.go2
9 files changed, 137 insertions, 11 deletions
diff --git a/lib/stm32-svd b/lib/stm32-svd
-Subproject c6b5be976f440196dcd819a8d9a52c6786f6799
+Subproject 3a0b0829b70bf930c74fb69d887bee28005e7d9
diff --git a/src/machine/board_nucleol432kc.go b/src/machine/board_nucleol432kc.go
index a8cc31ac1..cb92a9613 100644
--- a/src/machine/board_nucleol432kc.go
+++ b/src/machine/board_nucleol432kc.go
@@ -13,20 +13,53 @@ const (
LED_GREEN = PB3
)
-// UART pins
const (
+ // Arduino Pins
+ A0 = PA0
+ A1 = PA1
+ A2 = PA3
+ A3 = PA4
+ A4 = PA5
+ A5 = PA6
+ A6 = PA7
+ A7 = PA2
+
+ D0 = PA10
+ D1 = PA9
+ D2 = PA12
+ D3 = PB0
+ D4 = PB7
+ D5 = PB6
+ D6 = PB1
+ D7 = PC14
+ D8 = PC15
+ D9 = PA8
+ D10 = PA11
+ D11 = PB5
+ D12 = PB4
+ D13 = PB3
+)
+
+const (
+ // UART pins
// PA2 and PA15 are connected to the ST-Link Virtual Com Port (VCP)
UART_TX_PIN = PA2
UART_RX_PIN = PA15
-)
-// I2C pins
-const (
+ // I2C pins
// With default solder bridge settings:
// PB6 / Arduino D5 / CN3 Pin 8 is SCL
// PB7 / Arduino D4 / CN3 Pin 7 is SDA
I2C0_SCL_PIN = PB6
I2C0_SDA_PIN = PB7
+
+ // SPI pins
+ SPI1_SCK_PIN = PB3
+ SPI1_SDI_PIN = PB5
+ SPI1_SDO_PIN = PB4
+ SPI0_SCK_PIN = SPI1_SCK_PIN
+ SPI0_SDI_PIN = SPI1_SDI_PIN
+ SPI0_SDO_PIN = SPI1_SDO_PIN
)
var (
@@ -40,15 +73,20 @@ var (
RxAltFuncSelector: 3,
}
UART1 = &UART0
-)
-var (
// I2C1 is documented, alias to I2C0 as well
I2C1 = &I2C{
Bus: stm32.I2C1,
AltFuncSelector: 4,
}
I2C0 = I2C1
+
+ // SPI1 is documented, alias to SPI0 as well
+ SPI1 = &SPI{
+ Bus: stm32.SPI1,
+ AltFuncSelector: 5,
+ }
+ SPI0 = SPI1
)
func init() {
diff --git a/src/machine/machine_stm32_spi.go b/src/machine/machine_stm32_spi.go
index f46113e67..626234920 100644
--- a/src/machine/machine_stm32_spi.go
+++ b/src/machine/machine_stm32_spi.go
@@ -1,4 +1,4 @@
-// +build stm32,!stm32f7x2,!stm32l5x2,!stm32l4x2
+// +build stm32,!stm32f7x2,!stm32l5x2
package machine
@@ -6,6 +6,7 @@ package machine
import (
"device/stm32"
+ "runtime/volatile"
"unsafe"
)
@@ -86,7 +87,12 @@ func (spi SPI) Configure(config SPIConfig) {
// now set the configuration
spi.Bus.CR1.Set(conf)
- spi.Bus.CR2.SetBits((conf & stm32.SPI_CR1_SSM_Msk) >> 16)
+
+ // Series-specific configuration to set 8-bit transfer mode
+ spi.config8Bits()
+
+ // enable SPI
+ spi.Bus.CR1.SetBits(stm32.SPI_CR1_SPE)
}
// Transfer writes/reads a single byte using the SPI interface.
@@ -103,8 +109,10 @@ func (spi SPI) Transfer(w byte) (byte, error) {
// 5. Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.
// put output word (8-bit) in data register (DR), which is parallel-loaded
- // into shift register, and shifted out on MOSI.
- spi.Bus.DR.Set(uint32(w))
+ // into shift register, and shifted out on MOSI. Some series have 16-bit
+ // register but writes must be strictly 8-bit to output a byte. Writing
+ // 16-bits indicates a packed transfer (2 bytes).
+ (*volatile.Register8)(unsafe.Pointer(&spi.Bus.DR.Reg)).Set(w)
// wait for SPI bus receive buffer not empty bit (RXNE) to be set.
// warning: blocks forever until this condition is met.
diff --git a/src/machine/machine_stm32f103.go b/src/machine/machine_stm32f103.go
index e1c91ca03..556785789 100644
--- a/src/machine/machine_stm32f103.go
+++ b/src/machine/machine_stm32f103.go
@@ -161,6 +161,10 @@ var (
SPI0 = SPI1
)
+func (spi SPI) config8Bits() {
+ // no-op on this series
+}
+
// Set baud rate for SPI
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
var conf uint32
diff --git a/src/machine/machine_stm32f405.go b/src/machine/machine_stm32f405.go
index d70b6a712..92ad79f65 100644
--- a/src/machine/machine_stm32f405.go
+++ b/src/machine/machine_stm32f405.go
@@ -67,6 +67,10 @@ type SPI struct {
AltFuncSelector uint8
}
+func (spi SPI) config8Bits() {
+ // no-op on this series
+}
+
func (spi SPI) configurePins(config SPIConfig) {
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
diff --git a/src/machine/machine_stm32f407.go b/src/machine/machine_stm32f407.go
index 72c157ccb..6ffafcd3b 100644
--- a/src/machine/machine_stm32f407.go
+++ b/src/machine/machine_stm32f407.go
@@ -70,6 +70,10 @@ type SPI struct {
AltFuncSelector uint8
}
+func (spi SPI) config8Bits() {
+ // no-op on this series
+}
+
// Set baud rate for SPI
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
var conf uint32
diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go
index 886c3985a..f4df17aba 100644
--- a/src/machine/machine_stm32l0.go
+++ b/src/machine/machine_stm32l0.go
@@ -184,6 +184,10 @@ type SPI struct {
AltFuncSelector uint8
}
+func (spi SPI) config8Bits() {
+ // no-op on this series
+}
+
// Set baud rate for SPI
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
var conf uint32
diff --git a/src/machine/machine_stm32l4.go b/src/machine/machine_stm32l4.go
index 95e1eb0fe..7b52f68a5 100644
--- a/src/machine/machine_stm32l4.go
+++ b/src/machine/machine_stm32l4.go
@@ -182,3 +182,67 @@ func enableAltFuncClock(bus unsafe.Pointer) {
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)
}
}
+
+//---------- SPI related types and code
+
+// SPI on the STM32Fxxx using MODER / alternate function pins
+type SPI struct {
+ Bus *stm32.SPI_Type
+ AltFuncSelector uint8
+}
+
+func (spi SPI) config8Bits() {
+ // Set rx threshold to 8-bits, so RXNE flag is set for 1 byte
+ // (common STM32 SPI implementation does 8-bit transfers only)
+ spi.Bus.CR2.SetBits(stm32.SPI_CR2_FRXTH)
+}
+
+// Set baud rate for SPI
+func (spi SPI) getBaudRate(config SPIConfig) uint32 {
+ var conf uint32
+
+ // Default
+ if config.Frequency == 0 {
+ config.Frequency = 4e6
+ }
+
+ localFrequency := config.Frequency
+
+ // set frequency dependent on PCLK prescaler. Since these are rather weird
+ // speeds due to the CPU freqency, pick a range up to that frquency for
+ // clients to use more human-understandable numbers, e.g. nearest 100KHz
+
+ // These are based on 80MHz peripheral clock frquency
+ switch {
+ case localFrequency < 312500:
+ conf = stm32.SPI_CR1_BR_Div256
+ case localFrequency < 625000:
+ conf = stm32.SPI_CR1_BR_Div128
+ case localFrequency < 1250000:
+ conf = stm32.SPI_CR1_BR_Div64
+ case localFrequency < 2500000:
+ conf = stm32.SPI_CR1_BR_Div32
+ case localFrequency < 5000000:
+ conf = stm32.SPI_CR1_BR_Div16
+ case localFrequency < 10000000:
+ conf = stm32.SPI_CR1_BR_Div8
+ // NOTE: many SPI components won't operate reliably (or at all) above 10MHz
+ // Check the datasheet of the part
+ case localFrequency < 20000000:
+ conf = stm32.SPI_CR1_BR_Div4
+ case localFrequency < 40000000:
+ conf = stm32.SPI_CR1_BR_Div2
+ default:
+ // None of the specific baudrates were selected; choose the lowest speed
+ conf = stm32.SPI_CR1_BR_Div256
+ }
+
+ return conf << stm32.SPI_CR1_BR_Pos
+}
+
+// Configure SPI pins for input output and clock
+func (spi SPI) configurePins(config SPIConfig) {
+ config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
+ config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
+ config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
+}
diff --git a/src/machine/spi.go b/src/machine/spi.go
index 6bea0141d..80f7c133d 100644
--- a/src/machine/spi.go
+++ b/src/machine/spi.go
@@ -1,4 +1,4 @@
-// +build !baremetal stm32,!stm32f7x2,!stm32l5x2,!stm32l4x2 fe310 k210 atmega
+// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 atmega
package machine