STM32L431 I2C master throws ARLO if SDA is pulled down externally before PE is set
OK so here is the finale of the trilogy (first two installments here and here).
If SDA is pulled low externally *after* I2C is enabled by setting I2C_CR1.PE, I2C_SR.BSY goes high; and if under that condition master communication is started, there's no notification/interrupt, but after SDA is released, communication commences as normally. This is the documented behaviour.
However, if SDA is pulled low externally *before* I2C is enabled by setting I2C_CR1.PE, it behaves differently. After starting communication by writing to I2C_CR2 (with START set), one pulse gets generated on SCL, and the communication ends with I2C_SR=0x201, i.e. ARLO (Arbitration Lost) set.
This is not documented.
Now this in practice probably causes less problems than the two previously mentioned issues. First, this genuinely can be detected by reading in state of the SDA pin in GPIO_IDR before communication; second, this does not result in the internal machine freezing in BUSY with no interrupt, or in errorneous TXIS interrupt; but in an interrupt indicating error so requiring some sort of intervention.
However, ARLO is a surprising interrupt to have in a single-master environment, and if from such consideration there's no handler in place, this may result in unexpected failures.
Also, in multi-master environment, the unexpected SCL pulse may cause the other master and/or slaves to be thrown out of sync.
There's also a surprising positive effect: the most common reason for SDA being stuck low is slave being out of sync (as described in the 9-pulse recovery in the I2C spec). In such case, if the unexpected ARLO interrupt is handled by I2C reset through PE pulsing, then the unexpected SCL pulse acts as that 9-pulse recovery, without need for explicitly writing one. Unfortunately, as this is not documented, it also should not be exploited as a feature.
JW
