From 9e61e6fe4d91a82dcb4d56b2226eb4d4a84f6e2f Mon Sep 17 00:00:00 2001 From: "Daniel M. Lambea" Date: Sat, 26 Sep 2020 08:20:43 +0100 Subject: [PATCH] nrf: add I2C error checking (#1392) * machine/nrf: add I2C error checking --- src/machine/machine_nrf.go | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go index 2539cb85..506f134e 100644 --- a/src/machine/machine_nrf.go +++ b/src/machine/machine_nrf.go @@ -258,12 +258,19 @@ func (i2c I2C) Configure(config I2CConfig) { // Tx does a single I2C transaction at the specified address. // It clocks out the given address, writes the bytes in w, reads back len(r) // bytes and stores them in r, and generates a stop condition on the bus. -func (i2c I2C) Tx(addr uint16, w, r []byte) error { +func (i2c I2C) Tx(addr uint16, w, r []byte) (err error) { i2c.Bus.ADDRESS.Set(uint32(addr)) + defer func() { + i2c.signalStop() + i2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_SUSPEND_Disabled) + }() + if len(w) != 0 { i2c.Bus.TASKS_STARTTX.Set(1) // start transmission for writing for _, b := range w { - i2c.writeByte(b) + if err = i2c.writeByte(b); err != nil { + goto cleanUp + } } } if len(r) != 0 { @@ -276,12 +283,18 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error { i2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_STOP) } i2c.Bus.TASKS_RESUME.Set(1) // re-start transmission for reading - r[i] = i2c.readByte() + if r[i], err = i2c.readByte(); err != nil { + // goto/break are practically equivalent here, + // but goto makes this more easily understandable for maintenance. + goto cleanUp + } } } + +cleanUp: i2c.signalStop() i2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_SUSPEND_Disabled) - return nil + return } // signalStop sends a stop signal when writing or tells the I2C peripheral that @@ -295,19 +308,28 @@ func (i2c I2C) signalStop() { } // writeByte writes a single byte to the I2C bus. -func (i2c I2C) writeByte(data byte) { +func (i2c I2C) writeByte(data byte) error { i2c.Bus.TXD.Set(uint32(data)) for i2c.Bus.EVENTS_TXDSENT.Get() == 0 { + if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 { + i2c.Bus.EVENTS_ERROR.Set(0) + return errI2CBusError + } } i2c.Bus.EVENTS_TXDSENT.Set(0) + return nil } // readByte reads a single byte from the I2C bus. -func (i2c I2C) readByte() byte { +func (i2c I2C) readByte() (byte, error) { for i2c.Bus.EVENTS_RXDREADY.Get() == 0 { + if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 { + i2c.Bus.EVENTS_ERROR.Set(0) + return 0, errI2CBusError + } } i2c.Bus.EVENTS_RXDREADY.Set(0) - return byte(i2c.Bus.RXD.Get()) + return byte(i2c.Bus.RXD.Get()), nil } // SPI on the NRF.