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
|
package machine
|
||||||
|
|
||||||
|
import "device/sifive"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
P00 Pin = 0
|
P00 Pin = 0
|
||||||
P01 Pin = 1
|
P01 Pin = 1
|
||||||
|
@ -36,3 +38,10 @@ const (
|
||||||
P30 Pin = 30
|
P30 Pin = 30
|
||||||
P31 Pin = 31
|
P31 Pin = 31
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SPI on the HiFive1.
|
||||||
|
var (
|
||||||
|
SPI1 = SPI{
|
||||||
|
Bus: sifive.QSPI1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
@ -6,23 +6,23 @@ const (
|
||||||
D0 = P16
|
D0 = P16
|
||||||
D1 = P17
|
D1 = P17
|
||||||
D2 = P18
|
D2 = P18
|
||||||
D3 = P19 // Green LED/PWM
|
D3 = P19 // Green LED/PWM (PWM1_PWM1)
|
||||||
D4 = P20 // PWM
|
D4 = P20 // PWM (PWM1_PWM0)
|
||||||
D5 = P21 // Blue LED/PWM
|
D5 = P21 // Blue LED/PWM (PWM1_PWM2)
|
||||||
D6 = P22 // Red LED/PWM
|
D6 = P22 // Red LED/PWM (PWM1_PWM3)
|
||||||
D7 = P16
|
D7 = P16
|
||||||
D8 = NoPin // PWM?
|
D8 = NoPin // PWM?
|
||||||
D9 = P01
|
D9 = P01
|
||||||
D10 = P02
|
D10 = P02 // SPI1_CS0
|
||||||
D11 = P03
|
D11 = P03 // SPI1_DQ0
|
||||||
D12 = P04
|
D12 = P04 // SPI1_DQ1
|
||||||
D13 = P05
|
D13 = P05 // SPI1_SCK
|
||||||
D14 = NoPin // not connected
|
D14 = NoPin // not connected
|
||||||
D15 = P09 // does not seem to work?
|
D15 = P09 // does not seem to work?
|
||||||
D16 = P10 // PWM
|
D16 = P10 // PWM (PWM2_PWM0)
|
||||||
D17 = P11 // PWM
|
D17 = P11 // PWM (PWM2_PWM1)
|
||||||
D18 = P12 // SDA/PWM
|
D18 = P12 // SDA (I2C0_SDA)/PWM (PWM2_PWM2)
|
||||||
D19 = P13 // SDL/PWM
|
D19 = P13 // SDL (I2C0_SCL)/PWM (PWM2_PWM3)
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -40,3 +40,14 @@ const (
|
||||||
UART_TX_PIN = NoPin
|
UART_TX_PIN = NoPin
|
||||||
UART_RX_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"
|
"device/sifive"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const CPU_FREQUENCY = 16000000
|
||||||
|
|
||||||
type PinMode uint8
|
type PinMode uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
PinOutput
|
PinOutput
|
||||||
|
PinPWM
|
||||||
|
PinSPI
|
||||||
|
PinI2C = PinSPI
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configure this pin with the given configuration.
|
// Configure this pin with the given configuration.
|
||||||
func (p Pin) Configure(config PinConfig) {
|
func (p Pin) Configure(config PinConfig) {
|
||||||
sifive.GPIO0.INPUT_EN.SetBits(1 << uint8(p))
|
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))
|
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))
|
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
|
package machine
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче