nrf: add I2C timeout
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.
Этот коммит содержится в:
родитель
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
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче