Browse Source

stm32: support SPI on L4 series

pull/1833/head
Kenneth Bell 4 years ago
committed by Ron Evans
parent
commit
25f3adb47e
  1. 2
      lib/stm32-svd
  2. 50
      src/machine/board_nucleol432kc.go
  3. 16
      src/machine/machine_stm32_spi.go
  4. 4
      src/machine/machine_stm32f103.go
  5. 4
      src/machine/machine_stm32f405.go
  6. 4
      src/machine/machine_stm32f407.go
  7. 4
      src/machine/machine_stm32l0.go
  8. 64
      src/machine/machine_stm32l4.go
  9. 2
      src/machine/spi.go

2
lib/stm32-svd

@ -1 +1 @@
Subproject commit c6b5be976f440196dcd819a8d9a52c6786f67990
Subproject commit 3a0b0829b70bf930c74fb69d887bee28005e7d99

50
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() {

16
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.

4
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

4
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)

4
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

4
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

64
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)
}

2
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

Loading…
Cancel
Save