github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_fe310.go (about)

     1  //go:build fe310
     2  
     3  package machine
     4  
     5  import (
     6  	"device/sifive"
     7  	"runtime/interrupt"
     8  	"unsafe"
     9  )
    10  
    11  const deviceName = sifive.Device
    12  
    13  func CPUFrequency() uint32 {
    14  	return 320000000 // 320MHz
    15  }
    16  
    17  const (
    18  	PinInput PinMode = iota
    19  	PinOutput
    20  	PinPWM
    21  	PinSPI
    22  	PinI2C = PinSPI
    23  )
    24  
    25  // Configure this pin with the given configuration.
    26  func (p Pin) Configure(config PinConfig) {
    27  	sifive.GPIO0.INPUT_EN.SetBits(1 << uint8(p))
    28  	switch config.Mode {
    29  	case PinOutput:
    30  		sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))
    31  	case PinPWM:
    32  		sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
    33  		sifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p))
    34  	case PinSPI:
    35  		sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
    36  		sifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p))
    37  	}
    38  }
    39  
    40  // Set the pin to high or low.
    41  func (p Pin) Set(high bool) {
    42  	if high {
    43  		sifive.GPIO0.PORT.SetBits(1 << uint8(p))
    44  	} else {
    45  		sifive.GPIO0.PORT.ClearBits(1 << uint8(p))
    46  	}
    47  }
    48  
    49  // Get returns the current value of a GPIO pin when the pin is configured as an
    50  // input or as an output.
    51  func (p Pin) Get() bool {
    52  	val := sifive.GPIO0.VALUE.Get() & (1 << uint8(p))
    53  	return (val > 0)
    54  }
    55  
    56  // Return the register and mask to enable a given GPIO pin. This can be used to
    57  // implement bit-banged drivers.
    58  //
    59  // Warning: only use this on an output pin!
    60  func (p Pin) PortMaskSet() (*uint32, uint32) {
    61  	return (*uint32)(unsafe.Pointer(&sifive.GPIO0.PORT)), sifive.GPIO0.PORT.Get() | (1 << uint8(p))
    62  }
    63  
    64  // Return the register and mask to disable a given GPIO pin. This can be used to
    65  // implement bit-banged drivers.
    66  //
    67  // Warning: only use this on an output pin!
    68  func (p Pin) PortMaskClear() (*uint32, uint32) {
    69  	return (*uint32)(unsafe.Pointer(&sifive.GPIO0.PORT)), sifive.GPIO0.PORT.Get() &^ (1 << uint8(p))
    70  }
    71  
    72  type UART struct {
    73  	Bus    *sifive.UART_Type
    74  	Buffer *RingBuffer
    75  }
    76  
    77  var (
    78  	UART0  = &_UART0
    79  	_UART0 = UART{Bus: sifive.UART0, Buffer: NewRingBuffer()}
    80  )
    81  
    82  func (uart *UART) Configure(config UARTConfig) {
    83  	if config.BaudRate == 0 {
    84  		config.BaudRate = 115200
    85  	}
    86  	// The divisor is:
    87  	//   fbaud = fin / (div + 1)
    88  	// Restating to get the divisor:
    89  	//   div = fin / fbaud - 1
    90  	// But we're using integers, so we should take care of rounding:
    91  	//   div = (fin + fbaud/2) / fbaud - 1
    92  	divisor := (CPUFrequency()+config.BaudRate/2)/config.BaudRate - 1
    93  	sifive.UART0.DIV.Set(divisor)
    94  	sifive.UART0.TXCTRL.Set(sifive.UART_TXCTRL_ENABLE)
    95  	sifive.UART0.RXCTRL.Set(sifive.UART_RXCTRL_ENABLE)
    96  	sifive.UART0.IE.Set(sifive.UART_IE_RXWM) // enable the receive interrupt (only)
    97  	intr := interrupt.New(sifive.IRQ_UART0, _UART0.handleInterrupt)
    98  	intr.SetPriority(5)
    99  	intr.Enable()
   100  }
   101  
   102  func (uart *UART) handleInterrupt(interrupt.Interrupt) {
   103  	rxdata := uart.Bus.RXDATA.Get()
   104  	c := byte(rxdata)
   105  	if uint32(c) != rxdata {
   106  		// The rxdata has other bits set than just the low 8 bits. This probably
   107  		// means that the 'empty' flag is set, which indicates there is no data
   108  		// to be read and the byte is garbage. Ignore this byte.
   109  		return
   110  	}
   111  	uart.Receive(c)
   112  }
   113  
   114  func (uart *UART) writeByte(c byte) error {
   115  	for sifive.UART0.TXDATA.Get()&sifive.UART_TXDATA_FULL != 0 {
   116  	}
   117  
   118  	sifive.UART0.TXDATA.Set(uint32(c))
   119  	return nil
   120  }
   121  
   122  func (uart *UART) flush() {}
   123  
   124  // SPI on the FE310. The normal SPI0 is actually a quad-SPI meant for flash, so it is best
   125  // to use SPI1 or SPI2 port for most applications.
   126  type SPI struct {
   127  	Bus *sifive.QSPI_Type
   128  }
   129  
   130  // SPIConfig is used to store config info for SPI.
   131  type SPIConfig struct {
   132  	Frequency uint32
   133  	SCK       Pin
   134  	SDO       Pin
   135  	SDI       Pin
   136  	LSBFirst  bool
   137  	Mode      uint8
   138  }
   139  
   140  // Configure is intended to setup the SPI interface.
   141  func (spi SPI) Configure(config SPIConfig) error {
   142  	// Use default pins if not set.
   143  	if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
   144  		config.SCK = SPI0_SCK_PIN
   145  		config.SDO = SPI0_SDO_PIN
   146  		config.SDI = SPI0_SDI_PIN
   147  	}
   148  
   149  	// enable pins for SPI
   150  	config.SCK.Configure(PinConfig{Mode: PinSPI})
   151  	config.SDO.Configure(PinConfig{Mode: PinSPI})
   152  	config.SDI.Configure(PinConfig{Mode: PinSPI})
   153  
   154  	// set default frequency
   155  	if config.Frequency == 0 {
   156  		config.Frequency = 4000000 // 4MHz
   157  	}
   158  
   159  	// div = (SPI_CFG(dev)->f_sys / (2 * frequency)) - 1;
   160  	div := CPUFrequency()/(2*config.Frequency) - 1
   161  	spi.Bus.DIV.Set(div)
   162  
   163  	// set mode
   164  	switch config.Mode {
   165  	case 0:
   166  		spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
   167  		spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
   168  	case 1:
   169  		spi.Bus.MODE.SetBits(sifive.QSPI_MODE_PHASE)
   170  		spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
   171  	case 2:
   172  		spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
   173  		spi.Bus.MODE.SetBits(sifive.QSPI_MODE_POLARITY)
   174  	case 3:
   175  		spi.Bus.MODE.SetBits(sifive.QSPI_MODE_PHASE | sifive.QSPI_MODE_POLARITY)
   176  	default: // to mode 0
   177  		spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
   178  		spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
   179  	}
   180  
   181  	// frame length
   182  	spi.Bus.FMT.SetBits(8 << sifive.QSPI_FMT_LENGTH_Pos)
   183  
   184  	// Set single line operation, by clearing all bits
   185  	spi.Bus.FMT.ClearBits(sifive.QSPI_FMT_PROTOCOL_Msk)
   186  
   187  	// set bit transfer order
   188  	if config.LSBFirst {
   189  		spi.Bus.FMT.SetBits(sifive.QSPI_FMT_ENDIAN)
   190  	} else {
   191  		spi.Bus.FMT.ClearBits(sifive.QSPI_FMT_ENDIAN)
   192  	}
   193  
   194  	return nil
   195  }
   196  
   197  // Transfer writes/reads a single byte using the SPI interface.
   198  func (spi SPI) Transfer(w byte) (byte, error) {
   199  	// wait for tx ready
   200  	for spi.Bus.TXDATA.HasBits(sifive.QSPI_TXDATA_FULL) {
   201  	}
   202  
   203  	// write data
   204  	spi.Bus.TXDATA.Set(uint32(w))
   205  
   206  	// wait until receive has data
   207  	data := spi.Bus.RXDATA.Get()
   208  	for data&sifive.QSPI_RXDATA_EMPTY > 0 {
   209  		data = spi.Bus.RXDATA.Get()
   210  	}
   211  
   212  	// return data
   213  	return byte(data), nil
   214  }
   215  
   216  // I2C on the FE310-G002.
   217  type I2C struct {
   218  	Bus sifive.I2C_Type
   219  }
   220  
   221  var (
   222  	I2C0 = (*I2C)(unsafe.Pointer(sifive.I2C0))
   223  )
   224  
   225  // I2CConfig is used to store config info for I2C.
   226  type I2CConfig struct {
   227  	Frequency uint32
   228  	SCL       Pin
   229  	SDA       Pin
   230  }
   231  
   232  var i2cClockFrequency uint32 = 32000000
   233  
   234  // Configure is intended to setup the I2C interface.
   235  func (i2c *I2C) Configure(config I2CConfig) error {
   236  	if config.Frequency == 0 {
   237  		config.Frequency = 100 * KHz
   238  	}
   239  
   240  	if config.SDA == 0 && config.SCL == 0 {
   241  		config.SDA = I2C0_SDA_PIN
   242  		config.SCL = I2C0_SCL_PIN
   243  	}
   244  
   245  	i2c.SetBaudRate(config.Frequency)
   246  
   247  	config.SDA.Configure(PinConfig{Mode: PinI2C})
   248  	config.SCL.Configure(PinConfig{Mode: PinI2C})
   249  
   250  	return nil
   251  }
   252  
   253  // SetBaudRate sets the communication speed for I2C.
   254  func (i2c *I2C) SetBaudRate(br uint32) error {
   255  	var prescaler = i2cClockFrequency/(5*br) - 1
   256  
   257  	// disable controller before setting the prescale registers
   258  	i2c.Bus.CTR.ClearBits(sifive.I2C_CTR_EN)
   259  
   260  	// set prescaler registers
   261  	i2c.Bus.PRER_LO.Set(uint32(prescaler & 0xff))
   262  	i2c.Bus.PRER_HI.Set(uint32((prescaler >> 8) & 0xff))
   263  
   264  	// enable controller
   265  	i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)
   266  
   267  	return nil
   268  }
   269  
   270  // Tx does a single I2C transaction at the specified address.
   271  // It clocks out the given address, writes the bytes in w, reads back len(r)
   272  // bytes and stores them in r, and generates a stop condition on the bus.
   273  func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
   274  	var err error
   275  	if len(w) != 0 {
   276  		// send start/address for write
   277  		i2c.sendAddress(addr, true)
   278  
   279  		// ACK received (0: ACK, 1: NACK)
   280  		if i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_RX_ACK) {
   281  			return errI2CAckExpected
   282  		}
   283  
   284  		// write data
   285  		for _, b := range w {
   286  			err = i2c.writeByte(b)
   287  			if err != nil {
   288  				return err
   289  			}
   290  		}
   291  	}
   292  	if len(r) != 0 {
   293  		// send start/address for read
   294  		i2c.sendAddress(addr, false)
   295  
   296  		// ACK received (0: ACK, 1: NACK)
   297  		if i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_RX_ACK) {
   298  			return errI2CAckExpected
   299  		}
   300  
   301  		// read first byte
   302  		r[0] = i2c.readByte()
   303  		for i := 1; i < len(r); i++ {
   304  			// send an ACK
   305  			i2c.Bus.CR_SR.Set(^uint32(sifive.I2C_CR_ACK))
   306  
   307  			// read data and send the ACK
   308  			r[i] = i2c.readByte()
   309  		}
   310  
   311  		// send NACK to end transmission
   312  		i2c.Bus.CR_SR.Set(sifive.I2C_CR_ACK)
   313  	}
   314  
   315  	// generate stop condition
   316  	i2c.Bus.CR_SR.Set(sifive.I2C_CR_STO)
   317  	return nil
   318  }
   319  
   320  // Writes a single byte to the I2C bus.
   321  func (i2c *I2C) writeByte(data byte) error {
   322  	// Send data byte
   323  	i2c.Bus.TXR_RXR.Set(uint32(data))
   324  
   325  	i2c.Bus.CR_SR.Set(sifive.I2C_CR_WR)
   326  
   327  	// wait until transmission complete
   328  	for i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_TIP) {
   329  	}
   330  
   331  	// ACK received (0: ACK, 1: NACK)
   332  	if i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_RX_ACK) {
   333  		return errI2CAckExpected
   334  	}
   335  
   336  	return nil
   337  }
   338  
   339  // Reads a single byte from the I2C bus.
   340  func (i2c *I2C) readByte() byte {
   341  	i2c.Bus.CR_SR.Set(sifive.I2C_CR_RD)
   342  
   343  	// wait until transmission complete
   344  	for i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_TIP) {
   345  	}
   346  
   347  	return byte(i2c.Bus.TXR_RXR.Get())
   348  }
   349  
   350  // Sends the address and start signal.
   351  func (i2c *I2C) sendAddress(address uint16, write bool) error {
   352  	data := (address << 1)
   353  	if !write {
   354  		data |= 1 // set read flag in transmit register
   355  	}
   356  
   357  	// write address to transmit register
   358  	i2c.Bus.TXR_RXR.Set(uint32(data))
   359  
   360  	// generate start condition
   361  	i2c.Bus.CR_SR.Set((sifive.I2C_CR_STA | sifive.I2C_CR_WR))
   362  
   363  	// wait until transmission complete
   364  	for i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_TIP) {
   365  	}
   366  
   367  	return nil
   368  }