fix(w5100): revert buffer base to 0x4000/0x6000 — IDM decodes only 15 bits
Reverts the 0x8000/0xC000 change from162dbf7, which was WRONG and actively broke transmission. The W5100S datasheet pseudo-code quotes 0x8000 (TX) / 0xC000 (RX) for the memory blocks, but the PARALLEL/indirect (IDM) interface only decodes a 15-bit offset. Bench-proven with an address-aliasing probe: writing distinct values to each candidate base and reading them back showed 0xC000 and 0x4000 are the SAME cell (0xC000 & 0x7FFF == 0x4000) while 0x6000 holds its own value. Consequence of the bad base: every payload byte written to 0x9800+i aliased down onto 0x0000+i, landing on SHAR (0x09-0x0E) and SIPR (0x0F-0x12) and overwriting them with the payload. The chip then transmitted frames with a garbage source MAC/IP, which the peer NIC drops without counting -- the "SEND_OK but rx_packets=0" symptom, and the bogus SIPR0 readback (0x50 was literally payload byte 15, 'P'). The NETLCKR unlock from9c4bc7ais a genuine W5100S requirement and stays. Also: - w5100_udptest.py: self-contained configure+send+readback probe (and the address-aliasing probe that found this), reports over UART. - scripts/build-flash.sh: sweep N seeds and flash the best (capture timing is seed-dependent, so the sweep is mandatory). - scripts/uart-console.py: interactive UART console, plus --send/--read one-shot modes for scripting. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Interactive UART console to the re-bba-rb board (FT2232H channel B).
|
||||
|
||||
The BBA default build runs an interactive shell on this port ("rebbarb> "):
|
||||
help list commands
|
||||
udp broadcast [msg] send a UDP broadcast on the test socket
|
||||
udp unicast <ip> [msg] send a UDP datagram to <ip>
|
||||
|
||||
The bring-up diagnostics (w5100_selftest / w5100_udptest / w5100_regdump) just
|
||||
stream a status line on the same port, so this works for those too.
|
||||
|
||||
Usage:
|
||||
sudo ./scripts/uart-console.py # /dev/ttyUSB1 @ 115200
|
||||
sudo ./scripts/uart-console.py /dev/ttyUSB0 115200
|
||||
./scripts/uart-console.py --send "udp broadcast hi" # one-shot, no tty
|
||||
./scripts/uart-console.py --read 5 # just dump 5s of output
|
||||
|
||||
Channel A of the FT2232H is the MPSSE/iceprog port; the UART is channel B, which
|
||||
is normally the SECOND ttyUSB (…USB1). Needs read/write on the device node —
|
||||
run under sudo, or add yourself to the port's group.
|
||||
|
||||
Quit the interactive console with Ctrl-] (or Ctrl-C).
|
||||
"""
|
||||
import sys, time, argparse
|
||||
|
||||
try:
|
||||
import serial
|
||||
except ImportError:
|
||||
sys.exit("needs pyserial: pip install pyserial")
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(add_help=True)
|
||||
ap.add_argument("port", nargs="?", default="/dev/ttyUSB1")
|
||||
ap.add_argument("baud", nargs="?", type=int, default=115200)
|
||||
ap.add_argument("--send", metavar="CMD",
|
||||
help="send one command, print the reply, exit")
|
||||
ap.add_argument("--read", metavar="SECONDS", type=float,
|
||||
help="just read for N seconds and exit (no tty needed)")
|
||||
args = ap.parse_args()
|
||||
|
||||
try:
|
||||
ser = serial.Serial(args.port, args.baud, timeout=0.1)
|
||||
except serial.SerialException as e:
|
||||
sys.exit(f"cannot open {args.port}: {e}\n(try: sudo {' '.join(sys.argv)})")
|
||||
|
||||
# ── one-shot modes (safe in scripts / no controlling terminal) ───────────
|
||||
if args.read is not None:
|
||||
end = time.time() + args.read
|
||||
while time.time() < end:
|
||||
data = ser.read(256)
|
||||
if data:
|
||||
sys.stdout.write(data.decode("ascii", "replace"))
|
||||
sys.stdout.flush()
|
||||
return
|
||||
|
||||
if args.send is not None:
|
||||
time.sleep(0.2); ser.reset_input_buffer()
|
||||
ser.write(args.send.encode() + b"\r")
|
||||
end = time.time() + 2.0
|
||||
buf = b""
|
||||
while time.time() < end:
|
||||
buf += ser.read(256)
|
||||
sys.stdout.write(buf.decode("ascii", "replace"))
|
||||
return
|
||||
|
||||
# ── interactive console ─────────────────────────────────────────────────
|
||||
import termios, tty, select
|
||||
print(f"[uart-console] {args.port} @ {args.baud} 8N1 — Ctrl-] to quit\r")
|
||||
fd = sys.stdin.fileno()
|
||||
try:
|
||||
old = termios.tcgetattr(fd)
|
||||
except termios.error:
|
||||
old = None
|
||||
try:
|
||||
if old is not None:
|
||||
tty.setraw(fd)
|
||||
while True:
|
||||
r, _, _ = select.select([sys.stdin, ser], [], [], 0.05)
|
||||
if ser in r:
|
||||
data = ser.read(4096)
|
||||
if data:
|
||||
sys.stdout.write(data.decode("ascii", "replace"))
|
||||
sys.stdout.flush()
|
||||
if sys.stdin in r:
|
||||
ch = sys.stdin.buffer.read(1)
|
||||
if not ch or ch == b"\x1d": # Ctrl-]
|
||||
break
|
||||
if ch == b"\n": # send CR, the shell wants it
|
||||
ch = b"\r"
|
||||
ser.write(ch)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
if old is not None:
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
||||
ser.close()
|
||||
print("\r\n[uart-console] closed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user