machine/esp32c3: corrected implementation for error handling and when to expect NACK

Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
deadprogram 2023-11-28 19:49:35 +01:00 коммит произвёл Ron Evans
родитель f91b6ad0df
коммит 19fb1bfafc

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

@ -788,7 +788,7 @@ type i2cCommand struct {
func nanotime() int64
func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
const intMask = esp.I2C_INT_CLR_END_DETECT_INT_CLR_Msk | esp.I2C_INT_CLR_TRANS_COMPLETE_INT_CLR_Msk | esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk | esp.I2C_INT_STATUS_NACK_INT_ST_Msk
const intMask = esp.I2C_INT_STATUS_END_DETECT_INT_ST_Msk | esp.I2C_INT_STATUS_TRANS_COMPLETE_INT_ST_Msk | esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk | esp.I2C_INT_STATUS_NACK_INT_ST_Msk
esp.I2C.INT_CLR.SetBits(intMask)
esp.I2C.INT_ENA.SetBits(intMask)
esp.I2C.SetCTR_CONF_UPGATE(1)
@ -801,6 +801,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
timeoutNS := int64(timeoutMS) * 1000000
needAddress := true
needRestart := false
readLast := false
var readTo []byte
for cmdIdx, reg := 0, &esp.I2C.COMD0; cmdIdx < len(cmd); {
c := &cmd[cmdIdx]
@ -808,7 +809,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
switch c.cmd {
case i2cCMD_RSTART:
reg.Set(i2cCMD_RSTART)
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
cmdIdx++
case i2cCMD_WRITE:
@ -824,7 +825,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
esp.I2C.SetFIFO_DATA_FIFO_RDATA(uint32(c.data[c.head]))
}
reg.Set(i2cCMD_WRITE | uint32(32-count))
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
if c.head < len(c.data) {
reg.Set(i2cCMD_END)
@ -840,14 +841,16 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
esp.I2C.SetFIFO_DATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)
esp.I2C.SLAVE_ADDR.Set(uint32(addr))
reg.Set(i2cCMD_WRITE | 1)
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
}
if needRestart {
// We need to send RESTART again after i2cCMD_WRITE.
reg.Set(i2cCMD_RSTART)
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
reg.Set(i2cCMD_WRITE | 1)
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
esp.I2C.SetFIFO_DATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)
needRestart = false
}
@ -862,11 +865,12 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
bytes = 32
}
reg.Set(i2cCMD_READ | uint32(bytes))
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
if split {
readLast = true
reg.Set(i2cCMD_READLAST | 1)
reg = (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(reg)) + 4)))
reg = nextAddress(reg)
readTo = c.data[c.head : c.head+bytes+1] // read bytes + 1 last byte
cmdIdx++
} else {
@ -894,7 +898,10 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
return errI2CWriteTimeout
}
}
if mask == esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk {
switch {
case mask&esp.I2C_INT_STATUS_NACK_INT_ST_Msk != 0 && !readLast:
return errI2CAckExpected
case mask&esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk != 0:
if readTo != nil {
return errI2CReadTimeout
}
@ -935,3 +942,7 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
func (i2c *I2C) SetBaudRate(br uint32) error {
return nil
}
func nextAddress(reg *volatile.Register32) *volatile.Register32 {
return (*volatile.Register32)(unsafe.Add(unsafe.Pointer(reg), 4))
}