mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 21:43:40 +00:00
machine/hifive1b: add support for SPI1
Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user