tinygo/src/machine/machine_fe310.go
Ayke van Laethem 768c652468 machine: rename CPU_FREQUENCY -> CPUFrequency()
These all-caps constants aren't in the Go style, so rename it to
CPUFrequency (which is more aligned with Go style). Additionally, make
it a function so that it is possible to add support for changing the
frequency in the future.

Tested by running `make smoketest`. None of the outputs did change.
2019-12-16 20:34:39 +01:00

165 строки
3,8 КиБ
Go

// +build fe310
package machine
import (
"device/sifive"
)
func CPUFrequency() uint32 {
return 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))
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))
}
}
// Set the pin to high or low.
func (p Pin) Set(high bool) {
if high {
sifive.GPIO0.PORT.SetBits(1 << uint8(p))
} else {
sifive.GPIO0.PORT.ClearBits(1 << uint8(p))
}
}
// Get returns the current value of a GPIO pin.
func (p Pin) Get() bool {
val := sifive.GPIO0.VALUE.Get() & (1 << uint8(p))
println(sifive.GPIO0.VALUE.Get())
return (val > 0)
}
type UART struct {
Bus *sifive.UART_Type
Buffer *RingBuffer
}
var (
UART0 = UART{Bus: sifive.UART0, Buffer: NewRingBuffer()}
)
func (uart UART) Configure(config UARTConfig) {
// Assuming a 16Mhz Crystal (which is Y1 on the HiFive1), the divisor for a
// 115200 baud rate is 138.
sifive.UART0.DIV.Set(138)
sifive.UART0.TXCTRL.Set(sifive.UART_TXCTRL_ENABLE)
}
func (uart UART) WriteByte(c byte) {
for sifive.UART0.TXDATA.Get()&sifive.UART_TXDATA_FULL != 0 {
}
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 := CPUFrequency()/(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
}