This commit adds I2C timeouts for nrf51 and nrf52 (but not yet for
others like nrf52840).

Tested on the PineTime, where I now got a timeout instead of hanging and
resetting due to a watchdog reset.
Этот коммит содержится в:
Ayke van Laethem 2023-07-13 15:24:58 +02:00 коммит произвёл Ron Evans
родитель a7b205c26c
коммит 14ddba8519
2 изменённых файлов: 25 добавлений и 2 удалений

Просмотреть файл

@ -203,6 +203,8 @@ func (uart *UART) handleInterrupt(interrupt.Interrupt) {
} }
} }
const i2cTimeout = 0xffff // this is around 29ms on a nrf52
// I2CConfig is used to store config info for I2C. // I2CConfig is used to store config info for I2C.
type I2CConfig struct { type I2CConfig struct {
Frequency uint32 Frequency uint32
@ -261,11 +263,17 @@ func (i2c *I2C) Configure(config I2CConfig) error {
} }
// signalStop sends a stop signal to the I2C peripheral and waits for confirmation. // signalStop sends a stop signal to the I2C peripheral and waits for confirmation.
func (i2c *I2C) signalStop() { func (i2c *I2C) signalStop() error {
tries := 0
i2c.Bus.TASKS_STOP.Set(1) i2c.Bus.TASKS_STOP.Set(1)
for i2c.Bus.EVENTS_STOPPED.Get() == 0 { for i2c.Bus.EVENTS_STOPPED.Get() == 0 {
tries++
if tries >= i2cTimeout {
return errI2CSignalStopTimeout
}
} }
i2c.Bus.EVENTS_STOPPED.Set(0) i2c.Bus.EVENTS_STOPPED.Set(0)
return nil
} }
var rngStarted = false var rngStarted = false

Просмотреть файл

@ -72,12 +72,17 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
if len(r) == 0 { if len(r) == 0 {
// Stop the I2C transaction after the write. // Stop the I2C transaction after the write.
i2c.signalStop() err = i2c.signalStop()
} else { } else {
// The last byte read has already stopped the transaction, via // The last byte read has already stopped the transaction, via
// TWI_SHORTS_BB_STOP. But we still need to wait until we receive the // TWI_SHORTS_BB_STOP. But we still need to wait until we receive the
// STOPPED event. // STOPPED event.
tries := 0
for i2c.Bus.EVENTS_STOPPED.Get() == 0 { for i2c.Bus.EVENTS_STOPPED.Get() == 0 {
tries++
if tries >= i2cTimeout {
return errI2CSignalStopTimeout
}
} }
i2c.Bus.EVENTS_STOPPED.Set(0) i2c.Bus.EVENTS_STOPPED.Set(0)
} }
@ -87,12 +92,17 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
// writeByte writes a single byte to the I2C bus and waits for confirmation. // writeByte writes a single byte to the I2C bus and waits for confirmation.
func (i2c *I2C) writeByte(data byte) error { func (i2c *I2C) writeByte(data byte) error {
tries := 0
i2c.Bus.TXD.Set(uint32(data)) i2c.Bus.TXD.Set(uint32(data))
for i2c.Bus.EVENTS_TXDSENT.Get() == 0 { for i2c.Bus.EVENTS_TXDSENT.Get() == 0 {
if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 { if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
i2c.Bus.EVENTS_ERROR.Set(0) i2c.Bus.EVENTS_ERROR.Set(0)
return errI2CBusError return errI2CBusError
} }
tries++
if tries >= i2cTimeout {
return errI2CWriteTimeout
}
} }
i2c.Bus.EVENTS_TXDSENT.Set(0) i2c.Bus.EVENTS_TXDSENT.Set(0)
return nil return nil
@ -100,11 +110,16 @@ func (i2c *I2C) writeByte(data byte) error {
// readByte reads a single byte from the I2C bus when it is ready. // readByte reads a single byte from the I2C bus when it is ready.
func (i2c *I2C) readByte() (byte, error) { func (i2c *I2C) readByte() (byte, error) {
tries := 0
for i2c.Bus.EVENTS_RXDREADY.Get() == 0 { for i2c.Bus.EVENTS_RXDREADY.Get() == 0 {
if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 { if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
i2c.Bus.EVENTS_ERROR.Set(0) i2c.Bus.EVENTS_ERROR.Set(0)
return 0, errI2CBusError return 0, errI2CBusError
} }
tries++
if tries >= i2cTimeout {
return 0, errI2CReadTimeout
}
} }
i2c.Bus.EVENTS_RXDREADY.Set(0) i2c.Bus.EVENTS_RXDREADY.Set(0)
return byte(i2c.Bus.RXD.Get()), nil return byte(i2c.Bus.RXD.Get()), nil