machine/i2c: add interface check and implementation where missing for SetBaudRate() (#3406)
* machine/i2c: add interface check and placeholder implementation where missing for SetBaudRate()
Этот коммит содержится в:
родитель
72b715fa99
коммит
935a293106
11 изменённых файлов: 104 добавлений и 42 удалений
|
@ -1,4 +1,4 @@
|
|||
//go:build atmega || nrf || sam || stm32 || fe310 || k210 || rp2040
|
||||
//go:build atmega || nrf || sam || stm32 || fe310 || k210 || rp2040 || mimxrt1062
|
||||
|
||||
package machine
|
||||
|
||||
|
@ -6,6 +6,17 @@ import (
|
|||
"errors"
|
||||
)
|
||||
|
||||
// If you are getting a compile error on this line please check to see you've
|
||||
// correctly implemented the methods on the I2C type. They must match
|
||||
// the i2cController interface method signatures type to type perfectly.
|
||||
// If not implementing the I2C type please remove your target from the build tags
|
||||
// at the top of this file.
|
||||
var _ interface { // 2
|
||||
Configure(config I2CConfig) error
|
||||
Tx(addr uint16, w, r []byte) error
|
||||
SetBaudRate(br uint32) error
|
||||
} = (*I2C)(nil)
|
||||
|
||||
// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
|
||||
//
|
||||
// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.
|
||||
|
@ -25,6 +36,7 @@ var (
|
|||
errI2CBusError = errors.New("I2C bus error")
|
||||
errI2COverflow = errors.New("I2C receive buffer overflow")
|
||||
errI2COverread = errors.New("I2C transmit buffer overflow")
|
||||
errI2CNotImplemented = errors.New("I2C operation not yet implemented")
|
||||
)
|
||||
|
||||
// I2CTargetEvent reflects events on the I2C bus
|
||||
|
|
|
@ -31,6 +31,11 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
// Activate internal pullups for twi.
|
||||
avr.PORTC.SetBits((avr.DIDR0_ADC4D | avr.DIDR0_ADC5D))
|
||||
|
||||
return i2c.SetBaudRate(config.Frequency)
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
// Initialize twi prescaler and bit rate.
|
||||
avr.TWSR.SetBits((avr.TWSR_TWPS0 | avr.TWSR_TWPS1))
|
||||
|
||||
|
@ -38,7 +43,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
||||
// NOTE: TWBR should be 10 or higher for controller mode.
|
||||
// It is 72 for a 16mhz board with 100kHz TWI
|
||||
avr.TWBR.Set(uint8(((CPUFrequency() / config.Frequency) - 16) / 2))
|
||||
avr.TWBR.Set(uint8(((CPUFrequency() / br) - 16) / 2))
|
||||
|
||||
// Enable twi module.
|
||||
avr.TWCR.Set(avr.TWCR_TWEN)
|
||||
|
|
|
@ -732,12 +732,13 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for the I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) {
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
// Synchronous arithmetic baudrate, via Arduino SAMD implementation:
|
||||
// SystemCoreClock / ( 2 * baudrate) - 5 - (((SystemCoreClock / 1000000) * WIRE_RISE_TIME_NANOSECONDS) / (2 * 1000));
|
||||
baud := CPUFrequency()/(2*br) - 5 - (((CPUFrequency() / 1000000) * riseTimeNanoseconds) / (2 * 1000))
|
||||
i2c.Bus.BAUD.Set(baud)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tx does a single I2C transaction at the specified address.
|
||||
|
|
|
@ -1228,12 +1228,13 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for the I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) {
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
// Synchronous arithmetic baudrate, via Adafruit SAMD51 implementation:
|
||||
// sercom->I2CM.BAUD.bit.BAUD = SERCOM_FREQ_REF / ( 2 * baudrate) - 1 ;
|
||||
baud := SERCOM_FREQ_REF/(2*br) - 1
|
||||
i2c.Bus.BAUD.Set(baud)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tx does a single I2C transaction at the specified address.
|
||||
|
|
|
@ -229,9 +229,10 @@ type I2CConfig struct {
|
|||
SDA Pin
|
||||
}
|
||||
|
||||
var i2cClockFrequency uint32 = 32000000
|
||||
|
||||
// Configure is intended to setup the I2C interface.
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
var i2cClockFrequency uint32 = 32000000
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
|
@ -241,7 +242,17 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
config.SCL = I2C0_SCL_PIN
|
||||
}
|
||||
|
||||
var prescaler = i2cClockFrequency/(5*config.Frequency) - 1
|
||||
i2c.SetBaudRate(config.Frequency)
|
||||
|
||||
config.SDA.Configure(PinConfig{Mode: PinI2C})
|
||||
config.SCL.Configure(PinConfig{Mode: PinI2C})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
var prescaler = i2cClockFrequency/(5*br) - 1
|
||||
|
||||
// disable controller before setting the prescale registers
|
||||
i2c.Bus.CTR.ClearBits(sifive.I2C_CTR_EN)
|
||||
|
@ -253,9 +264,6 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
// enable controller
|
||||
i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)
|
||||
|
||||
config.SDA.Configure(PinConfig{Mode: PinI2C})
|
||||
config.SCL.Configure(PinConfig{Mode: PinI2C})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the I2C frequency.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
i2cSetBaudRate(i2c.Bus, br)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tx does a single I2C transaction at the specified address.
|
||||
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
||||
i2cTransfer(i2c.Bus, &w[0], len(w), &r[0], len(r))
|
||||
|
@ -117,6 +123,9 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
|||
//export __tinygo_i2c_configure
|
||||
func i2cConfigure(bus uint8, scl Pin, sda Pin)
|
||||
|
||||
//export __tinygo_i2c_set_baud_rate
|
||||
func i2cSetBaudRate(bus uint8, br uint32)
|
||||
|
||||
//export __tinygo_i2c_transfer
|
||||
func i2cTransfer(bus uint8, w *byte, wlen int, r *byte, rlen int) int
|
||||
|
||||
|
|
|
@ -563,7 +563,19 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
config.SCL.SetFPIOAFunction(FUNC_I2C2_SCLK)
|
||||
}
|
||||
|
||||
div := CPUFrequency() / config.Frequency / 16
|
||||
i2c.SetBaudRate(config.Frequency)
|
||||
|
||||
i2c.Bus.INTR_MASK.Set(0)
|
||||
i2c.Bus.DMA_CR.Set(0x03)
|
||||
i2c.Bus.DMA_RDLR.Set(0)
|
||||
i2c.Bus.DMA_TDLR.Set(0x4)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
div := CPUFrequency() / br / 16
|
||||
|
||||
// Disable controller before setting the prescale register.
|
||||
i2c.Bus.ENABLE.Set(0)
|
||||
|
@ -574,11 +586,6 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
i2c.Bus.SS_SCL_HCNT.Set(uint32(div))
|
||||
i2c.Bus.SS_SCL_LCNT.Set(uint32(div))
|
||||
|
||||
i2c.Bus.INTR_MASK.Set(0)
|
||||
i2c.Bus.DMA_CR.Set(0x03)
|
||||
i2c.Bus.DMA_RDLR.Set(0)
|
||||
i2c.Bus.DMA_TDLR.Set(0x4)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,19 +6,6 @@ package machine
|
|||
|
||||
import (
|
||||
"device/nxp"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
errI2CWriteTimeout = errors.New("I2C timeout during write")
|
||||
errI2CReadTimeout = errors.New("I2C timeout during read")
|
||||
errI2CBusReadyTimeout = errors.New("I2C timeout on bus ready")
|
||||
errI2CSignalStartTimeout = errors.New("I2C timeout on signal start")
|
||||
errI2CSignalReadTimeout = errors.New("I2C timeout on signal read")
|
||||
errI2CSignalStopTimeout = errors.New("I2C timeout on signal stop")
|
||||
errI2CAckExpected = errors.New("I2C error: expected ACK not NACK")
|
||||
errI2CBusError = errors.New("I2C bus error")
|
||||
errI2CNotConfigured = errors.New("I2C interface is not yet configured")
|
||||
)
|
||||
|
||||
// I2CConfig is used to store config info for I2C.
|
||||
|
@ -150,7 +137,7 @@ func (i2c *I2C) setPins(c I2CConfig) (sda, scl Pin) {
|
|||
}
|
||||
|
||||
// Configure is intended to setup an I2C interface for transmit/receive.
|
||||
func (i2c *I2C) Configure(config I2CConfig) {
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
// init pins
|
||||
sda, scl := i2c.setPins(config)
|
||||
|
||||
|
@ -169,6 +156,14 @@ func (i2c *I2C) Configure(config I2CConfig) {
|
|||
|
||||
// reset clock and registers, and enable LPI2C module interface
|
||||
i2c.reset(freq)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c I2C) SetBaudRate(br uint32) error {
|
||||
// TODO: implement
|
||||
return errI2CNotImplemented
|
||||
}
|
||||
|
||||
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||
|
@ -212,13 +207,13 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// WriteRegister transmits first the register and then the data to the
|
||||
// WriteRegisterEx transmits first the register and then the data to the
|
||||
// peripheral device.
|
||||
//
|
||||
// Many I2C-compatible devices are organized in terms of registers. This method
|
||||
// is a shortcut to easily write to such registers. Also, it only works for
|
||||
// devices with 7-bit addresses, which is the vast majority.
|
||||
func (i2c I2C) WriteRegister(address uint8, register uint8, data []byte) error {
|
||||
func (i2c I2C) WriteRegisterEx(address uint8, register uint8, data []byte) error {
|
||||
option := transferOption{
|
||||
flags: transferDefault, // transfer options bit mask (0 = normal transfer)
|
||||
peripheral: uint16(address), // 7-bit peripheral address
|
||||
|
@ -232,13 +227,13 @@ func (i2c I2C) WriteRegister(address uint8, register uint8, data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ReadRegister transmits the register, restarts the connection as a read
|
||||
// ReadRegisterEx transmits the register, restarts the connection as a read
|
||||
// operation, and reads the response.
|
||||
//
|
||||
// Many I2C-compatible devices are organized in terms of registers. This method
|
||||
// is a shortcut to easily read such registers. Also, it only works for devices
|
||||
// with 7-bit addresses, which is the vast majority.
|
||||
func (i2c I2C) ReadRegister(address uint8, register uint8, data []byte) error {
|
||||
func (i2c I2C) ReadRegisterEx(address uint8, register uint8, data []byte) error {
|
||||
option := transferOption{
|
||||
flags: transferDefault, // transfer options bit mask (0 = normal transfer)
|
||||
peripheral: uint16(address), // 7-bit peripheral address
|
||||
|
@ -560,7 +555,7 @@ func (i2c *I2C) controllerReceive(rxBuffer []byte) resultFlag {
|
|||
return result
|
||||
}
|
||||
|
||||
// controllerReceive performs a polling transmit transfer on the I2C bus.
|
||||
// controllerTransmit performs a polling transmit transfer on the I2C bus.
|
||||
func (i2c *I2C) controllerTransmit(txBuffer []byte) resultFlag {
|
||||
txSize := len(txBuffer)
|
||||
for txSize > 0 {
|
||||
|
|
|
@ -246,13 +246,8 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
i2c.setPins(config.SCL, config.SDA)
|
||||
|
||||
i2c.mode = config.Mode
|
||||
|
||||
if i2c.mode == I2CModeController {
|
||||
if config.Frequency >= 400*KHz {
|
||||
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400)
|
||||
} else {
|
||||
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100)
|
||||
}
|
||||
i2c.SetBaudRate(config.Frequency)
|
||||
|
||||
i2c.enableAsController()
|
||||
} else {
|
||||
|
@ -262,6 +257,23 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the I2C frequency. It has the side effect of also
|
||||
// enabling the I2C hardware if disabled beforehand.
|
||||
//
|
||||
//go:inline
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
switch {
|
||||
case br >= 400*KHz:
|
||||
i2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K400)
|
||||
case br >= 250*KHz:
|
||||
i2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K250)
|
||||
default:
|
||||
i2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K100)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// signalStop sends a stop signal to the I2C peripheral and waits for confirmation.
|
||||
func (i2c *I2C) signalStop() error {
|
||||
tries := 0
|
||||
|
|
|
@ -157,6 +157,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
// TODO: implement
|
||||
return errI2CNotImplemented
|
||||
}
|
||||
|
||||
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
||||
|
||||
if err := i2c.controllerTransmit(addr, w); nil != err {
|
||||
|
|
|
@ -84,6 +84,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||
// TODO: implement
|
||||
return errI2CNotImplemented
|
||||
}
|
||||
|
||||
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
||||
if len(w) > 0 {
|
||||
if err := i2c.controllerTransmit(addr, w); nil != err {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче