99 строки
2,3 КиБ
Go
99 строки
2,3 КиБ
Go
// +build stm32
|
|
|
|
package machine
|
|
|
|
// Peripheral abstraction layer for SPI on the stm32 family
|
|
|
|
import (
|
|
"device/stm32"
|
|
"unsafe"
|
|
)
|
|
|
|
// SPIConfig is used to store config info for SPI.
|
|
type SPIConfig struct {
|
|
Frequency uint32
|
|
SCK Pin
|
|
MOSI Pin
|
|
MISO Pin
|
|
LSBFirst bool
|
|
Mode uint8
|
|
}
|
|
|
|
// Configure is intended to setup the STM32 SPI1 interface.
|
|
// Features still TODO:
|
|
// - support SPI2 and SPI3
|
|
// - allow setting data size to 16 bits?
|
|
// - allow setting direction in HW for additional optimization?
|
|
// - hardware SS pin?
|
|
func (spi SPI) Configure(config SPIConfig) {
|
|
// enable clock for SPI
|
|
enableAltFuncClock(unsafe.Pointer(spi.Bus))
|
|
|
|
// Get SPI baud rate based on the bus speed it's attached to
|
|
var conf uint32 = spi.getBaudRate(config)
|
|
|
|
// set bit transfer order
|
|
if config.LSBFirst {
|
|
conf |= stm32.SPI_CR1_LSBFIRST
|
|
}
|
|
|
|
// set polarity and phase on the SPI interface
|
|
switch config.Mode {
|
|
case Mode0:
|
|
conf &^= (1 << stm32.SPI_CR1_CPOL_Pos)
|
|
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
|
case Mode1:
|
|
conf &^= (1 << stm32.SPI_CR1_CPOL_Pos)
|
|
conf |= (1 << stm32.SPI_CR1_CPHA_Pos)
|
|
case Mode2:
|
|
conf |= (1 << stm32.SPI_CR1_CPOL_Pos)
|
|
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
|
case Mode3:
|
|
conf |= (1 << stm32.SPI_CR1_CPOL_Pos)
|
|
conf |= (1 << stm32.SPI_CR1_CPHA_Pos)
|
|
default: // to mode 0
|
|
conf &^= (1 << stm32.SPI_CR1_CPOL_Pos)
|
|
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
|
}
|
|
|
|
// set to SPI master
|
|
conf |= stm32.SPI_CR1_MSTR
|
|
|
|
// disable MCU acting as SPI slave
|
|
conf |= stm32.SPI_CR1_SSM | stm32.SPI_CR1_SSI
|
|
|
|
// now set the configuration
|
|
spi.Bus.CR1.Set(conf)
|
|
|
|
// init pins
|
|
if config.SCK == 0 && config.MOSI == 0 && config.MISO == 0 {
|
|
config.SCK = SPI0_SCK_PIN
|
|
config.MOSI = SPI0_MOSI_PIN
|
|
config.MISO = SPI0_MISO_PIN
|
|
}
|
|
spi.configurePins(config)
|
|
|
|
// enable SPI interface
|
|
spi.Bus.CR1.SetBits(stm32.SPI_CR1_SPE)
|
|
}
|
|
|
|
// Transfer writes/reads a single byte using the SPI interface.
|
|
func (spi SPI) Transfer(w byte) (byte, error) {
|
|
// Write data to be transmitted to the SPI data register
|
|
spi.Bus.DR.Set(uint32(w))
|
|
|
|
// Wait until transmit complete
|
|
for !spi.Bus.SR.HasBits(stm32.SPI_SR_TXE) {
|
|
}
|
|
|
|
// Wait until receive complete
|
|
for !spi.Bus.SR.HasBits(stm32.SPI_SR_RXNE) {
|
|
}
|
|
|
|
// Wait until SPI is not busy
|
|
for spi.Bus.SR.HasBits(stm32.SPI_SR_BSY) {
|
|
}
|
|
|
|
// Return received data from SPI data register
|
|
return byte(spi.Bus.DR.Get()), nil
|
|
}
|