machine/hifive1b: add support for SPI1

Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
Ron Evans 2019-10-28 17:36:57 +01:00 коммит произвёл Ayke
родитель 373fa6d69b
коммит 46d468b79d
4 изменённых файлов: 136 добавлений и 14 удалений

Просмотреть файл

@ -2,6 +2,8 @@
package machine
import "device/sifive"
const (
P00 Pin = 0
P01 Pin = 1
@ -36,3 +38,10 @@ const (
P30 Pin = 30
P31 Pin = 31
)
// SPI on the HiFive1.
var (
SPI1 = SPI{
Bus: sifive.QSPI1,
}
)

Просмотреть файл

@ -6,23 +6,23 @@ const (
D0 = P16
D1 = P17
D2 = P18
D3 = P19 // Green LED/PWM
D4 = P20 // PWM
D5 = P21 // Blue LED/PWM
D6 = P22 // Red LED/PWM
D3 = P19 // Green LED/PWM (PWM1_PWM1)
D4 = P20 // PWM (PWM1_PWM0)
D5 = P21 // Blue LED/PWM (PWM1_PWM2)
D6 = P22 // Red LED/PWM (PWM1_PWM3)
D7 = P16
D8 = NoPin // PWM?
D9 = P01
D10 = P02
D11 = P03
D12 = P04
D13 = P05
D10 = P02 // SPI1_CS0
D11 = P03 // SPI1_DQ0
D12 = P04 // SPI1_DQ1
D13 = P05 // SPI1_SCK
D14 = NoPin // not connected
D15 = P09 // does not seem to work?
D16 = P10 // PWM
D17 = P11 // PWM
D18 = P12 // SDA/PWM
D19 = P13 // SDL/PWM
D16 = P10 // PWM (PWM2_PWM0)
D17 = P11 // PWM (PWM2_PWM1)
D18 = P12 // SDA (I2C0_SDA)/PWM (PWM2_PWM2)
D19 = P13 // SDL (I2C0_SCL)/PWM (PWM2_PWM3)
)
const (
@ -40,3 +40,14 @@ const (
UART_TX_PIN = NoPin
UART_RX_PIN = NoPin
)
// SPI pins
const (
SPI0_SCK_PIN = NoPin
SPI0_MOSI_PIN = NoPin
SPI0_MISO_PIN = NoPin
SPI1_SCK_PIN = D13
SPI1_MOSI_PIN = D11
SPI1_MISO_PIN = D12
)

Просмотреть файл

@ -6,18 +6,30 @@ import (
"device/sifive"
)
const CPU_FREQUENCY = 16000000
type PinMode uint8
const (
PinInput PinMode = iota
PinOutput
PinPWM
PinSPI
PinI2C = PinSPI
)
// Configure this pin with the given configuration.
func (p Pin) Configure(config PinConfig) {
sifive.GPIO0.INPUT_EN.SetBits(1 << uint8(p))
if config.Mode == PinOutput {
switch config.Mode {
case PinOutput:
sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))
case PinPWM:
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
sifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p))
case PinSPI:
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
sifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p))
}
}
@ -59,3 +71,93 @@ func (uart UART) WriteByte(c byte) {
sifive.UART0.TXDATA.Set(uint32(c))
}
// SPI on the FE310. The normal SPI0 is actually a quad-SPI meant for flash, so it is best
// to use SPI1 or SPI2 port for most applications.
type SPI struct {
Bus *sifive.QSPI_Type
}
// 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 SPI interface.
func (spi SPI) Configure(config SPIConfig) error {
// Use default pins if not set.
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
}
// enable pins for SPI
config.SCK.Configure(PinConfig{Mode: PinSPI})
config.MOSI.Configure(PinConfig{Mode: PinSPI})
config.MISO.Configure(PinConfig{Mode: PinSPI})
// set default frequency
if config.Frequency == 0 {
config.Frequency = 4000000
}
// div = (SPI_CFG(dev)->f_sys / (2 * frequency)) - 1;
div := CPU_FREQUENCY/(2*config.Frequency) - 1
spi.Bus.DIV.Set(div)
// set mode
switch config.Mode {
case 0:
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
case 1:
spi.Bus.MODE.SetBits(sifive.QSPI_MODE_PHASE)
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
case 2:
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
spi.Bus.MODE.SetBits(sifive.QSPI_MODE_POLARITY)
case 3:
spi.Bus.MODE.SetBits(sifive.QSPI_MODE_PHASE | sifive.QSPI_MODE_POLARITY)
default: // to mode 0
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
}
// frame length
spi.Bus.FMT.SetBits(8 << sifive.QSPI_FMT_LENGTH_Pos)
// Set single line operation, by clearing all bits
spi.Bus.FMT.ClearBits(sifive.QSPI_FMT_PROTOCOL_Msk)
// set bit transfer order
if config.LSBFirst {
spi.Bus.FMT.SetBits(sifive.QSPI_FMT_ENDIAN)
} else {
spi.Bus.FMT.ClearBits(sifive.QSPI_FMT_ENDIAN)
}
return nil
}
// Transfer writes/reads a single byte using the SPI interface.
func (spi SPI) Transfer(w byte) (byte, error) {
// wait for tx ready
for spi.Bus.TXDATA.HasBits(sifive.QSPI_TXDATA_FULL) {
}
// write data
spi.Bus.TXDATA.Set(uint32(w))
// wait until receive has data
for spi.Bus.RXDATA.HasBits(sifive.QSPI_RXDATA_EMPTY) {
}
// return data
return byte(spi.Bus.RXDATA.Get() & sifive.QSPI_RXDATA_DATA_Msk), nil
}

Просмотреть файл

@ -1,4 +1,4 @@
// +build sam stm32,!stm32f407
// +build sam stm32,!stm32f407 fe310
package machine