List of changes in no particular order.
First, clearing of TWSI_CONTROL_ACK is moved from twsi_transfer totwsi_transfer and twsi_intr are now protected with the statemutex to
machine in twsi_intr. Specifically, the bitensure a consistent view of the state.
msleep is cleapaired in thewith wakeup.
TWSI_STATUS_ADDR_R_ACK state when we want to read just one byte. We need toAll wakeup calls are consolidtaed.
The control register is written exactly once in response to hardware events.
do that because if we send ACK after a received byte a device can send usThe hardware executes a next stage of I2C protocol when the interrupt flag is cleared,
another byte and the code may write beyond the read buffer. The old codeso it is much easier to reason about what happens when with a single write to
did not work in a scenario where a single byte was read from an EEPROM
device with two byte addressing.
For example:
i2c -m tr -a 0x50 -d r -w 16 -o 0 -c 1 -v
The reason is that the first message (a write) has two bytes, so
TWSI_CONTROL_ACK was never clearedthe control register.
Second, add support for a transfer where a write is followed by a writeImproved diagnostic messages and code formatting.
In this case we do not need to send any stop or start or repeated start.Support for diagnostic messages is always compiled in
We can just keep wriwith the actual printing bytes. Anything else confuses the target devicecontrolled via a sysctl (disabled by default).
Such a transfer can be created by i2c tool, e.g.I2C is not super-fast protocols, for an EEPROM write atso having a bunch of extra condition checks
specific offset:should not hurt the performance.
i2c -m tr -a 0x50 -d w -w 16 -o 0 -c 8 -v < /dev/randomAlso, debug messages in register access functions require a higher debug level
i2c -m tr -a 0x50 -d r -w 16 -o 0 -c 16 -vas their information is mostly redundant.
SmallSupport for more transfer changes:ombinations and types.
- some errno error codes are replaced with iicbus error codesExamples:
- added diagnostic for the case where an interrupt is received without any- zero length transfers (start-address-stop),
active transfer- a write message with NO_STOP followed by another write message,
- (probably unneeded) all transfer parameters are fully setup before anya read message with NO_STOP flag followed by a write message (with implied repeated start)
Somewhat better code structure to handle conditions like end of message,
write to the control register
- added a 3 second timeout for a transfer to complete; this is mostly to
protect from indefinite hang in a case of any mistakes in the protocol
state machineend of all messages.
Detect and handle more unexpected conditions.
The latter is hardcoded at the moment.Always send STOP when any error (or unexpected condition) is detected.
Ensure that TWSI_CONTROL_ACK is always correctly or cleared depending on
Three seconds is a very long time from the point of I2C protocol and a quite
short time from a point of a human beinghow many octets we expect to receive.
In general, the handling of various states needs to be reviewed to make sureAdd KASSERT-s to ensure that the code correctly follows octet counts and
that:
- all combinations of transfer directions and start/stop flags are correctly
handled
- all message length are correctly handled
- there is never an access beyond data buffersnever tries to write or read beyond message data buffers.