Skip to content

Commit 232e9e3

Browse files
authored
esp32: fix I2C timeouts on larger transfers (#5674)
* esp32: fix I2C timeouts on larger transfers * fix: clearer comment
1 parent 7f1f99b commit 232e9e3

1 file changed

Lines changed: 18 additions & 8 deletions

File tree

src/machine/machine_esp32_i2c.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
242242
timeoutNS := int64(timeoutMS) * 1000000
243243
needAddress := true
244244
needRestart := false
245+
isRead := false
245246
var readTo []byte
246247
for cmdIdx, reg := 0, &i2c.Bus.COMD0; cmdIdx < len(cmd); {
247248
c := &cmd[cmdIdx]
@@ -253,6 +254,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
253254
cmdIdx++
254255

255256
case i2cCMD_WRITE:
257+
isRead = false
256258
count := 32
257259
if needAddress {
258260
needAddress = false
@@ -266,15 +268,17 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
266268
reg.Set(i2cCMD_WRITE | uint32(32-count))
267269
reg = nextAddress(reg)
268270

269-
if c.head < len(c.data) {
270-
reg.Set(i2cCMD_END)
271-
reg = nil
272-
} else {
271+
// Always end a write segment with END, so STOP goes out alone
272+
// in its own segment (ref: ESP32 TRM v5.8, section 21.3.5).
273+
reg.Set(i2cCMD_END)
274+
reg = nil
275+
if c.head >= len(c.data) {
273276
cmdIdx++
274277
}
275278
needRestart = true
276279

277280
case i2cCMD_READ:
281+
isRead = true
278282
if needAddress {
279283
needAddress = false
280284
i2c.Bus.SetDATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)
@@ -308,10 +312,16 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
308312
reg = nextAddress(reg)
309313
}
310314

311-
if split {
315+
if split && bytes > 0 {
316+
reg.Set(i2cCMD_END)
317+
readTo = c.data[c.head : c.head+bytes]
318+
reg = nil
319+
} else if split {
312320
reg.Set(i2cCMD_READLAST | 1)
313321
reg = nextAddress(reg)
314-
readTo = c.data[c.head : c.head+bytes+1] // read bytes + 1 last byte
322+
reg.Set(i2cCMD_END)
323+
readTo = c.data[c.head : c.head+1]
324+
reg = nil
315325
cmdIdx++
316326
} else {
317327
reg.Set(i2cCMD_END)
@@ -333,7 +343,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
333343
if nanotime() > end {
334344
// timeout leaves the bus in an undefined state, reset
335345
i2c.resetBus()
336-
if readTo != nil {
346+
if isRead {
337347
return errI2CReadTimeout
338348
}
339349
return errI2CWriteTimeout
@@ -345,7 +355,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
345355
case mask&esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk != 0:
346356
// timeout leaves the bus in an undefined state, reset
347357
i2c.resetBus()
348-
if readTo != nil {
358+
if isRead {
349359
return errI2CReadTimeout
350360
}
351361
return errI2CWriteTimeout

0 commit comments

Comments
 (0)