Don't advance the write address across TXDATA; deepen tx_bytes to 2048
Two coupled fixes, both exposed by batching TXDATA writes in the test app. 1. eff_addr advanced on EVERY data byte of a register-space write. But TXDATA (0x48) is a FIFO PORT, not a register: a whole frame is written to that one address. So an 8-byte write put byte 0 in TXDATA and bytes 1..7 into 0x49+, which the switch silently ignores. The frame was an eighth of its declared length, TXFrameDrain blocked waiting for the rest, and TI never set (hardware: txto=16, "no ACK after 20 tries"). SWISS WOULD HAVE HIT THIS. It writes an entire frame with bba_outs to BBA_WRTXFIFOD -- one transaction, one address -- so its TX would have delivered ONE BYTE per frame. The path was never exercised because the test app wrote TXDATA one byte per EXI transaction, giving every byte a fresh header at 0x48. Every other register must still advance, so that bba_outs can write PAR0-5 or MAR0-7 as a block; the exception is TXDATA only. 2. tx_bytes was 16 deep. SPI cannot back-pressure -- there is no way to tell the GC to wait -- so BBARegisterFile silently drops bytes when w_rdy is low, which makes the depth the only thing between a drain stall and a corrupted frame, not a buffering preference. 16 bytes is ~4.7 us at the EXI byte rate, and TXFrameDrain shares the W5100 bus arbiter with RX and the socket-3 UDP test, so any longer stall truncated a frame mid-flight. With (1) fixed, Swiss streams up to 1514 bytes in a single transaction, so 16 could never have held. Now 2048: a whole maximum-size frame plus margin, so a frame cannot be truncated even if the drain makes no progress for the entire transaction. Costs 3 of 27 free BRAMs (ICESTORM_RAM 3/30 -> 6/30, LC 68% -> 70%). Dennis spotted that the 8-byte workaround could not survive whole-frame writes, which is what prompted fixing the depth rather than shipping it. bba_tx_bytes() consequently streams 64-byte chunks (bba_write()'s buffer limit), so a 60-byte ACK is ONE transaction instead of sixty. T8 covers both and is mutation-tested: restoring the increment gives "1/8 bytes MISMATCH -- got [17], want [17, 34, 51, ...]". It now writes 64 bytes so it exercises the deepened FIFO too. --seeds 8: clk 27.6-29.4 MHz, EXI 51.2-64.7 MHz, 8/8 PASS. Best seed 1 (clk 29.35, EXI 60.80), flashed. STILL NO FLOW CONTROL on the TX path: a frame larger than 2048 would drop silently rather than error. Fine for ethernet's 1518 ceiling; revisit if the multiworld socket work ever wants larger payloads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -125,7 +125,7 @@ int bba_tx_bytes(const u8 *buf, u32 len)
|
||||
{
|
||||
u32 off = 0;
|
||||
|
||||
/* Stream in 8-byte chunks, ONE EXI transaction each.
|
||||
/* Stream in 64-byte chunks, ONE EXI transaction each.
|
||||
*
|
||||
* Writing byte by byte with bba_w8() costs a full EXI_Lock / EXI_Select /
|
||||
* header / EXI_Deselect / EXI_Unlock PER BYTE -- about sixty transactions
|
||||
@@ -142,14 +142,14 @@ int bba_tx_bytes(const u8 *buf, u32 len)
|
||||
* tries"). Byte-by-byte worked only because the per-byte EXI overhead
|
||||
* happened to give the drain time.
|
||||
*
|
||||
* 8 is half the FIFO depth: it cannot overflow even if the drain consumes
|
||||
* nothing for the whole transaction, while still cutting a 60-byte ACK
|
||||
* from ~60 transactions to 8. Do not raise it without deepening
|
||||
* tx_bytes or giving the TX path real back-pressure. */
|
||||
* tx_bytes is now 2048 deep -- a whole maximum-size frame -- so the old
|
||||
* 8-byte cap is gone and 64 (bba_write()'s buffer limit) sends a 60-byte
|
||||
* ACK in a SINGLE transaction. The depth is what makes this safe: SPI
|
||||
* cannot back-pressure, so the FIFO must absorb the entire burst. */
|
||||
while (off < len) {
|
||||
u32 n = len - off;
|
||||
int rc;
|
||||
if (n > 8) n = 8;
|
||||
if (n > 64) n = 64;
|
||||
rc = bba_write(REG_TXDATA, buf + off, n);
|
||||
if (rc < 0) return rc;
|
||||
off += n;
|
||||
|
||||
Reference in New Issue
Block a user