xiic_l.c: XIic_Send() / XIic_DynSend() can miss NACK on final transmitted byte and still report full byte count
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 1.2k
- Forks
- 1.1k
- PR merge metrics
- No merged PRs in 30d
Description
Bug Report
The low-level polled transmit path in the Xilinx IIC driver appears to miss a slave NACK when it occurs on the final transmitted data byte.
This affects both:
XIic_Send()viaSendData()XIic_DynSend()viaDynSendData()
Observed behavior
XIic_Send() can return the full requested byte count even though the slave NACKed the last transmitted byte.
In our case this shows up with an EEPROM write into a write-protected region:
- the target device does not actually update the memory cell
- the write should be rejected by the slave on the bus
- but
XIic_Send()still reports success, so higher layers interpret the transfer as successful
Why this looks like a driver bug
In SendData() the code checks XIIC_INTR_TX_ERROR_MASK only while waiting for the next TX_EMPTY condition before writing the next byte.
Relevant flow:
- wait for
TX_EMPTYor error - write one byte to
XIIC_DTR_REG_OFFSET - decrement
ByteCount - if
ByteCount == 0, exit loop - if
XIIC_STOP, wait only forXIIC_INTR_BNB_MASK - return success (
ByteCount == 0)
Because of this, if the slave NACK happens on the final transmitted byte, there is no final check for XIIC_INTR_TX_ERROR_MASK after the last byte has been written. The code only waits for bus-not-busy and then returns success.
The same pattern exists in DynSendData().
Affected code paths
SendData():
- error is checked here before the next byte:
if (IntrStatus & (XIIC_INTR_TX_ERROR_MASK |
XIIC_INTR_ARB_LOST_MASK |
XIIC_INTR_BNB_MASK)) {
return ByteCount;
}
- but after the final byte is written:
XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, *BufferPtr++);
ByteCount--;
- there is no final
TX_ERRORcheck, only:
if (Option == XIIC_STOP) {
while (1) {
if (XIic_ReadIisr(BaseAddress) & XIIC_INTR_BNB_MASK) {
break;
}
}
}
DynSendData() has the same issue.
Expected behavior
If the slave NACKs the final transmitted byte, XIic_Send() / XIic_DynSend() should not report the full requested byte count as sent.
A final-byte NACK should be reflected as an incomplete transfer, just like NACK on earlier bytes.
Impact
Higher-level drivers that use:
bytes_sent == requested_lengthas success, or- wrappers such as register writes built on top of
XIic_Send()
can falsely report success even though the slave rejected the final byte.
This is especially visible with devices that:
- ACK address and earlier bytes
- NACK only the final data byte in specific protocol situations
One real example is EEPROM write protection, where the device may ACK device address and internal address bytes, but NACK the protected data byte.
Suggested fix
After transmitting the final byte, and before returning success, explicitly check XIIC_INTR_TX_ERROR_MASK once more.
This should be done in:
SendData()DynSendData()
A fix would likely involve checking for TX_ERROR after the final byte has left the FIFO and before treating the transfer as successful, instead of only polling for BNB.
Version
The issue is present in the current xiic_l.c implementation containing:
XIic_Send()SendData()XIic_DynSend()DynSendData()
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in xiic_l.c by reading SendData() and DynSendData(), following the existing TX_ERROR checks and final BNB polling. Validate the behavior with a write-protected EEPROM or equivalent final-byte NACK case. Done means XIic_Send() and XIic_DynSend() report an incomplete transfer instead of the full byte count when the final byte is NACKed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100