fix(w5100): unlock NETLCKR before writing GWR/SUBR/SHAR/SIPR (W5100S)
Second W5100S-vs-W5100 gotcha found at bring-up: the W5100S has a Network Lock Register (NETLCKR, 0x0071) the original W5100 lacks. It defaults to 0x00 (locked), and while locked, ALL writes to GWR/SUBR/SHAR/SIPR are silently dropped -- so the chip has no source IP/MAC and the UDP/MACRAW send builds nothing (chip reports SEND_OK but transmits nothing; socket registers aren't locked, which is why an indirect write/readback of Sn_PORT succeeded). Fix: write the unlock value 0x3A to NETLCKR right after MR enables indirect mode, before the network-config writes. On the bench this flipped the board from silent to actually keying frames onto the wire (magjack activity LED now blinks). Also: - bba_top.py test model: RX buffer base 0x6000 -> 0xC000 to match the W5100S buffer-base fix (the model hardcoded the old W5100 address). - w5100_selftest.py: added an indirect-mode (IDM) write/readback probe of a socket register + IND= field in the UART report, to isolate direct-vs-indirect access (confirmed indirect works on the real chip). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,8 @@ _GAR0 = 0x0001 # Gateway IP, 4 bytes
|
||||
_SUBR0 = 0x0005 # Subnet mask, 4 bytes
|
||||
_SHAR0 = 0x0009 # Source MAC, 6 bytes
|
||||
_SIPR0 = 0x000F # Source IP, 4 bytes
|
||||
_NETLCKR = 0x0071 # W5100S Network Lock Register (WO) — GWR/SUBR/SHAR/SIPR are
|
||||
_NETLCK_UNLOCK = 0x3A # writable ONLY while NETLCKR==0x3A (default 0x00 = locked)
|
||||
_IR = 0x0015 # Interrupt register
|
||||
_IMR = 0x0016 # Interrupt mask
|
||||
_RMSR = 0x001A # RX memory size (2 bits/socket)
|
||||
@@ -565,7 +567,16 @@ class W5100ParallelMaster(Elaboratable):
|
||||
m.d.sync += wait_ctr.eq(wait_ctr + 1)
|
||||
|
||||
# MR = indirect + auto-increment (direct A=00).
|
||||
write_reg("MR_MODE", _MR, [_MR_IND | _MR_AI], "SHAR", direct=True)
|
||||
write_reg("MR_MODE", _MR, [_MR_IND | _MR_AI], "NETLCK", direct=True)
|
||||
|
||||
# W5100S-only: GWR/SUBR/SHAR/SIPR are LOCKED until NETLCKR (0x0071)
|
||||
# is written 0x3A (default 0x00 = locked). Without this, every
|
||||
# SHAR/SIPR/GAR/SUBR write below is silently DROPPED -> no source
|
||||
# MAC/IP -> the UDP/MACRAW send builds nothing and the chip transmits
|
||||
# nothing on the wire despite reporting SEND_OK (bench-confirmed
|
||||
# 2026-09-20; the original W5100 had no such lock). Indirect mode is
|
||||
# already on from MR_MODE, so this reaches 0x0071.
|
||||
write_reg("NETLCK", _NETLCKR, [_NETLCK_UNLOCK], "SHAR")
|
||||
|
||||
# SHAR = source MAC (6-byte auto-increment burst).
|
||||
with m.State("SHAR"):
|
||||
@@ -911,6 +922,7 @@ if __name__ == "__main__":
|
||||
EXPECTED = [
|
||||
("MR", _MR_RST),
|
||||
("MR", _MR_IND | _MR_AI),
|
||||
(_NETLCKR, _NETLCK_UNLOCK), # W5100S: unlock GWR/SUBR/SHAR/SIPR
|
||||
(_SHAR0 + 0, MAC[0]), (_SHAR0 + 1, MAC[1]), (_SHAR0 + 2, MAC[2]),
|
||||
(_SHAR0 + 3, MAC[3]), (_SHAR0 + 4, MAC[4]), (_SHAR0 + 5, MAC[5]),
|
||||
(_RMSR + 0, 0x55), (_RMSR + 1, 0x55),
|
||||
|
||||
Reference in New Issue
Block a user