Skip to content

[FIX] OpenCoresI2C: do not warn on STOP of read-only transaction#211

Open
eisbaw wants to merge 1 commit into
renode:masterfrom
eisbaw:fix/opencores-i2c-spurious-stop-warning
Open

[FIX] OpenCoresI2C: do not warn on STOP of read-only transaction#211
eisbaw wants to merge 1 commit into
renode:masterfrom
eisbaw:fix/opencores-i2c-spurious-stop-warning

Conversation

@eisbaw

@eisbaw eisbaw commented Jun 8, 2026

Copy link
Copy Markdown

Summary

If OpenCoresI2C.SendDataToSlave() is invoked unconditionally from a STOP handler then we get a log warning.

The existing guard conflated two distinct cases behind one WARNING:

  1. dataToSlave queue empty -- legitimate at the end of every read-only transaction. The slave address byte is consumed by the START handler via TryResolveSelectedSlave(); HandleWriteToSlaveCommand never runs for a read, so nothing is enqueued.
  2. dataToSlave queue non-empty but selectedSlave already nulled -- a genuine internal state inconsistency worth flagging.

The shared WARNING produces a misleading log line on every read transaction's STOP. Renode log coalescing collapses identical successive warnings, so the log shows one entry per test rather than one per read transaction, which makes the noise look even more like a real (single) failure when triaged.

The read transaction itself succeeds because the early return in the old guard prevented a spurious .Write([]) to the slave. The warning is functionally inert but cosmetically misleading.

Reproducer

Any unit test that uses OpenCoresI2C as a master and performs a read transaction (START, READ, STOP) prints:

[WARNING] i2c_master: Trying to send data to slave, but either no data is available or the slave is not selected

Minimal Robot:

Master Write       \${OC_TXRX}         0xA1          # read address byte (slave 0x50, R)
Master Write       \${OC_CMD_STATUS}   0x90          # START + WR bit
Master Write       \${OC_CMD_STATUS}   0x60          # RD + STOP -> warning fires here

Fix

Split the guard inside SendDataToSlave():

  • Empty queue -> silent return; (the common-and-correct path for read-only STOP).
  • Queue has data but selectedSlave == null -> warning naming the dropped byte count + clear the queue. This is the real anomaly the original warning was probably meant to flag.

The behaviour for normal write transactions is unchanged: the queue has data, `selectedSlave` is non-null, the flush proceeds.

Risk

Low. The only behavioural change is:

  • The common case (empty queue at STOP/repeated-START) no longer logs a WARNING.
  • The state-corruption case (queued data but no slave) gets a more precise WARNING and now clears the orphan queue rather than leaving it indefinitely.

No public API change; no register-map change; no semantics change for any well-formed I2C transaction.

Context

Encountered while building a Renode-based unit-test harness for a large set of I2C peripherals (GPIO expanders, sensors, ADC/DAC, EEPROM, bucks, etc.). Every read transaction in every test suite produced the warning, making CI artefacts hard to triage. Same upstream peripheral has at least one other known defect (general-call 0x00 address not supported) that I'd like to address in a follow-up PR.

AI

Made by Claude Opus 4.8. With human review. Small and focused, LGTM

SendDataToSlave() is invoked unconditionally from the STOP handler
(line 112) and the repeated-START handler (line 76) to flush any
queued TX data to the selected slave. The previous guard combined
two distinct cases:

  1. dataToSlave queue empty -- legitimate at the end of every
     read-only transaction (the address byte is consumed by the
     START handler via TryResolveSelectedSlave; no HandleWriteToSlave
     ever runs, so nothing is enqueued).
  2. dataToSlave queue non-empty but selectedSlave already nulled --
     genuine internal state inconsistency worth flagging.

Conflating both behind a single WARNING produced a misleading log
entry on every read transaction (one per test in suites that run
many tests, due to log coalescing), suggesting a failure where there
was none. The transaction itself succeeds because the early return
prevented a spurious .Write([]) to the slave.

This change:
  - Returns silently when the queue is empty (the common-and-correct
    case at STOP of a read transaction).
  - Keeps a WARNING for the actual anomaly (queue has data but no
    slave selected), now with a more specific message that names
    the byte count being dropped.

Reproducer: any unit test that uses OpenCoresI2C as a master and
performs a read transaction (START, READ, STOP) prints the warning
'Trying to send data to slave, but either no data is available or
the slave is not selected' even though the read succeeds.
@CLAassistant

CLAassistant commented Jun 8, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants