machine/hifive1b: add support for SPI1
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
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
|
||||
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче