SANBlaze I3C Controller Platform

V1532 Release Notes

Release Date: August 2026


Overview

V1532 adds reliable support for multi-packet MCTP messages received over I2C / SMBus. Prior releases handled MCTP responses that fit in a single packet; responses spanning multiple packets — a 4 KB NVMe-MI Identify Controller response arrives as 65 consecutive SMBus block writes — are now received, framed, and delivered to the host complete and in order.

The receive path was reworked to service the bus under interrupt rather than by polling, and to recover the receive engine from bus conditions that carry no data — notably the address-only probes issued by a bus scan. A target running V1532 remains present and responsive on a shared segment across arbitrary I2C traffic.

V1532 also raises the supported I2C / SMBus bus speed from 100 kHz to 400 kHz and 1 MHz, and adds optional per-transaction error reporting so a host driver can detect an incomplete response and retry it rather than parsing corrupt data.

V1532 preserves the V1531 read contract, ring buffer frame format, and command surface. Existing host code targeting V1531 runs unchanged, and behavior in I3C mode is unchanged.


What’s New

Multi-packet MCTP message support over I2C / SMBus

MCTP messages that span more than one packet are now received and delivered intact. Each transaction is committed as one framed ring entry and returned one entry per read, in arrival order, so a host MCTP stack reassembles the message from the packet headers exactly as it does on a single-packet response. No host or driver change is required.

Verified against a 4096-byte NVMe-MI Identify Controller response over I2C at 100 kHz:

Measure

Result

Packets received

65 of 65

Data bytes on the wire

4640

Address-phase NAKs

0

Data-phase NAKs

0

Packet CRC (PEC) failures

0

Message integrity check (MIC)

Pass

Response status

Success

Bus-scan resilience

A target running V1532 survives address-only transactions. Bus scans (i2cdetect) complete normally with the target present, and every other device on the segment remains visible during and after the scan. Repeated scans are stable. See “Target stopped responding after a bus scan” below.

400 kHz and 1 MHz bus support

Multi-packet MCTP is now supported at 400 kHz and 1 MHz in addition to 100 kHz. Set the bus speed on the drive with an NVMe-MI Configuration Set (configuration identifier 1, SMBus/I2C Frequency) and on the controller with sb_i3c_init; both must agree.

(
: ${SLOT:?Set your slot number with SLOT=N first}
echo "# Executing example on user SLOT=$SLOT"
# Controller
sb_i3c_init -d $SLOT -p i2c -c 400

# Drive: -w 01 = 100 kHz, 02 = 400 kHz, 03 = 1 MHz
mi -T smbus -d $SLOT -t 1 3 1 -p 0 -w 02

# Confirm
mi -T i2c -d $SLOT -t 1 4 1 -p 0
# Expected: SMBus/I2C Frequency: 2 (400 KHz)
)

Validated with a 4096-byte NVMe-MI Identify Controller response in a continuous loop:

Bus speed

Iterations

Failures

100 kHz

2,596

0

400 kHz

2,596

0

1 MHz

25,350

0

Speed support is drive-dependent and, at 1 MHz, hardware-dependent. See “1 MHz support is conditional” under Known Limitations before enabling it.

Optional per-transaction error reporting

A host driver can now ask the controller to report transactions that did not complete cleanly, instead of silently receiving a short or incomplete entry. This is opt-in per read — existing drivers are unaffected.

Set bit 1 of wValue on the data-read control transfer (0x52) in addition to the existing bit 0:

wValue bit 0 = 1   start packet (existing)
wValue bit 0 = 0   continue at wIndex (existing)
wValue bit 1 = 1   also report errors      (V1532, new)

wValue = 1   start packet, no error reporting   (pre-V1532 behavior)
wValue = 3   start packet, with error reporting

Bit 1 applies only to a start-packet call. When it is set, an entry that did not complete cleanly is returned with the top three bits of its 16-bit size field populated. An MCTP packet never exceeds 8191 bytes, so those bits were previously unused:

Bits 15:13

Meaning

000

No error

100

Message received without its first packet

101

Reserved

110

Length error — payload does not match the declared frame length

111

Packet lost, or message ended without its final packet

Bit 15 is the error flag; a host testing the size as a signed value sees a negative length. Mask the size with 0x1FFF before using it as a length. The size reported is the number of bytes actually present, not the number expected, and the entry must still be drained to completion like any other.

The firmware does not retry. It reports; the host decides. A host that does not set bit 1 sees exactly the pre-V1532 behavior.


What’s Fixed

Multi-packet responses terminated early on fast targets

Transfers from faster targets terminated with a NAK in the middle of a data phase, truncating the response. Slower targets on the same bus completed normally, which made the condition look target-specific rather than timing-dependent.

The receive FIFO was serviced by a polling loop. When servicing was delayed, the FIFO filled, the receive engine stalled mid-byte, and the clock line was held low long enough for the transmitting device to abandon the transfer.

V1532 services the receive FIFO from a hardware interrupt that drains it to empty on every event and hands bytes to a lock-free staging buffer consumed by the main loop. Measured FIFO occupancy is now one byte, so the stall condition cannot be reached. Staging buffer overruns are counted and reported; none have been observed.

Target stopped responding after a bus scan

After a bus scan, the target either stopped answering its address or held the data line low. In the latter case, devices probed after the target in the same scan also failed to respond — a scan that should have found every device on the segment reported only those preceding the target.

An SMBus quick-write probe carries an address and no data bytes. Because no data was received, the end-of-transfer path did not run, and the receive engine remained waiting on clock edges that a completed transaction never produces.

V1532 adds a liveness watchdog. When the bus has been idle for a defined interval with no receive activity, the receive engine is released and reinitialized. Address-only probes are fully recovered before the next transaction arrives. This condition is present in earlier releases and is not specific to multi-packet traffic.

Transfers truncated at repeating byte offsets

Transfers ended early at repeating offsets within a packet — consistently at the same positions across runs, on identical packet content.

End of transfer is inferred from a quiet interval on the bus. Some targets pause briefly mid-packet while assembling data. Where that pause exceeded the configured interval, the transfer was treated as complete and the receive engine was reinitialized while the packet was still arriving; the next byte then arrived at an engine that had already returned to idle.

V1532 re-derives the interval from measured bus behavior. It is set above the longest observed mid-packet pause and below the shortest observed gap between packets, so a mid-packet pause no longer ends a transfer and the engine is still ready before the next packet begins.

CCC detection active in I2C mode

Every I2C transaction produced additional interrupt activity, reducing receive headroom on the main loop.

The broadcast CCC detection engine has no function on an I2C bus, where CCCs do not exist, but remained enabled and attempted to parse ordinary I2C traffic as CCC frames. Every transaction produced an address mismatch and an interrupt.

V1532 parks CCC detection in I2C mode and releases its pins. It is restored automatically when the protocol is switched back to I3C, in either direction, so no manual step is required when changing modes.

Address-phase NAK on alternating transactions

During a continuous stream of packets, every second transaction was NAK’d at the address phase, halving effective throughput and interrupting multi-packet messages.

A START condition is signalled by the data line going low. Bus-idle detection sampled the line at a single instant, so a START occurring at the moment of sampling was indistinguishable from an idle bus, and recovery could run while an address was being received.

V1532 requires the idle condition to hold continuously for the full interval. Address and data clocking release the line within tens of microseconds, so active traffic can no longer satisfy the condition, while a genuinely stalled bus still recovers promptly.

Packet boundaries missed at higher bus speeds

At 400 kHz and above, transfers were truncated mid-packet or ran together, producing short entries, sequence gaps, or a response whose first packet never arrived. At 100 kHz the same code was stable.

The end of a transaction is identified by watching the data line change while the clock line is high. That check ran on a fixed schedule sized for 100 kHz timing. At 400 kHz the observation window is roughly four times narrower and at 1 MHz roughly twenty times narrower, so the check could land outside the transition entirely and reach the wrong conclusion.

V1532 samples both lines together in a single read rather than sequentially, removes the fixed schedule in favor of a continuous check, scales the bounding interval to the configured bus speed, and raises the priority of the receive interrupt above other activity so it is not delayed past the window. An interval that expires with the clock line still high is now treated as end-of-transaction, which it must be — a data bit cannot hold the clock high for twenty bit periods.

Incomplete messages delivered without indication

A message that lost its first or last packet was passed to the host looking structurally intact. The host detected the problem only when reassembly failed further along, and had no way to distinguish it from corrupt data.

Loss of the first packet leaves no ring entry to mark, and loss of the final packet means the end-of-message condition that would normally trigger a check never occurs.

V1532 detects both cases and marks the first entry the host will read, so the condition is reported before any data from that message is served. A message that stalls without completing is released after a bounded interval with the same indication rather than being held. Reporting requires the opt-in described under “Optional per-transaction error reporting”; without it, behavior is unchanged.

Stalled transfer held for 10 seconds

A transfer that lost bytes mid-frame was held open for 10 seconds before the receive engine recovered, and the partial frame was then committed as though it were whole.

The recovery interval was set far above any plausible bus event.

V1532 reduces it to 100 ms. The longest mid-transaction pause observed from any drive is under 11 ms, and is the same at every bus speed because it reflects the drive’s internal processing rather than the bit rate, so 100 ms retains roughly ten times margin. Frames that do not match their declared length are marked rather than committed silently.


Known Limitations

1 MHz support is drive-dependent

Not every drive that accepts a 1 MHz Configuration Set operates correctly at that rate. A drive may negotiate 1 MHz successfully and then fail all subsequent transactions. Confirm with a short traffic run after setting the speed, not with the Configuration Get read-back alone. All drives tested operate correctly at 100 kHz and 400 kHz.

Recommendation: use 400 kHz for data transfer. 1 MHz is suitable for speed validation and for drives confirmed to support it.

Bus speed is not preserved across a power cycle

Both the controller and the drive return to their default speed after a power cycle. Re-apply both settings as part of bring-up; setting only one leaves the two mismatched, which presents as a bus that enumerates but cannot carry traffic.

FW download throughput and I3C clock

A full 4.25 MB image downloads in roughly 80 seconds with per-chunk validation enabled. The remaining per-packet cost is dominated by host/USB transfer overhead, not the I3C wire, so the I3C clock rate has little effect on total download time: a full image takes roughly 84 seconds at 4 MHz and roughly 80 seconds at 8 MHz — within a few percent. Select the I3C clock for reliability, not speed.

The reliable maximum clock is setup-dependent — cabling, bus loading, and any inline instrumentation all affect it — and a moderate clock with margin is preferable to the highest clock that appears to work, since marginal signal integrity can produce a hard hang rather than a clean, recoverable error. To pick a clock on a given setup: bring the bus up at a candidate clock and confirm enumeration succeeds; if it does, that clock is safe for the download; if enumeration fails or is unreliable, step the clock down and retry. See User Guide §7 for the exact procedure.

Download time remains host- and drive-state dependent; the elapsed figure is indicative rather than guaranteed.

HDR-DDR mode not supported

V1532 operates in SDR mode only. HDR-DDR is scheduled for a future release.


Compatibility

Firmware

  • Runs on all iRiser hardware supported by V1531 — no hardware requirement changes.

  • No new memory or resource requirements beyond V1531.

Host CLI (sb_i3c)

  • ABI/API unchanged from V1531. No commands added, removed, or modified.

Ring buffer and host read path

  • Frame format is unchanged: one framed entry per transaction, one entry per read, in arrival order.

  • The USB command set is unchanged. Error reporting reuses a previously undefined bit of an existing request rather than adding a command.

  • No host or driver changes are required to receive multi-packet messages.

  • Error reporting is opt-in and default off. A driver that does not set wValue bit 1 sees byte-for-byte the pre-V1532 behavior, so new firmware is safe under an existing driver. A V1532-aware driver running against older firmware sees the bit ignored and no error entries; if the driver cannot otherwise determine the firmware version, treat absence of error reports as “not available” rather than “no errors occurred”.

Test suite (sb_i3c_test)

  • Update EXPECTED_VERSION to 1532 and include 1532 in ACCEPTED_VERSIONS.

  • All V1531 tests run unchanged.

Existing customer workflows

  • V1531 host code runs without modification.

  • V1531 SBExpress test scripts run without modification.

  • I3C mode behavior is unchanged.

  • Default bus speed is unchanged at 100 kHz. Higher speeds are opt-in.


Upgrade Path

Standard firmware update:

sb_i3c_update -d $SLOT /etc/iRiser/sanblaze_i3c_fw_v1532.uf2

Then re-run device discovery:

sb_i3c_find_all

Host-side device information — including reported firmware version — is discovered at boot and cached. After updating firmware in place, the cached information still describes the previous firmware, and host software that selects behavior based on reported version will continue to use the behavior associated with the cached value. This affects cached information only; the running firmware is unaffected.

sb_i3c_find_all refreshes cached information for every slot and re-establishes device bindings. The reported version for each device appears in its output:

Discovered devices:
slot=2  usb=1-5.2.7.4  tty=/dev/ttyACM3  ver=1532  i2c=/dev/i2c-2

Confirm ver= matches the firmware just installed before running traffic against the device.

No configuration migration is required. Persistent settings (clock frequencies in /tmp/NVMe/iRiser/<slot>/) are format-compatible.


Support

For questions, defect reports, or feature requests, contact SANBlaze support with the output of:

sb_i3c -d $SLOT status
sb_i3c -d $SLOT i3c_err_get
cat /tmp/NVMe/iRiser/$SLOT/i3c_*

For bus speed issues, also include the configured speed from both ends:

sb_i3c -d $SLOT status | grep Clock
mi -T i2c -d $SLOT -t 1 4 1 -p 0

The V1532 firmware version string is V1532. Confirm with:

sb_i3c -d $SLOT status | grep Version