Skip to content

Commit 6c3e64d

Browse files
authored
Merge pull request #2425 from LinuxCNC/fix-elbpcom
Fix elbpcom
2 parents f34122e + 0ec1e5a commit 6c3e64d

2 files changed

Lines changed: 114 additions & 31 deletions

File tree

docs/man/man1/elbpcom.1

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ Common options:
99
.BI [\-\-ip= IP ]
1010
.BI [\-\-port= PORT ]
1111
.BI [\-\-timeout= TIMEOUT ]
12+
.BI [\-\-space= MEMSPACE ]
13+
.BI [\-\-size= TRANSFER_SIZE ]
1214
.RE
1315

1416
Reading data:
1517
.RS
1618
.SY elbpcom
1719
.BI [ common\ options ]
18-
.BI \-\-space= SPACE
1920
.B [\-\-info]
2021
.BI \-\-address= ADDRESS
2122
.BI \-\-read= LENGTH
@@ -25,11 +26,17 @@ Writing data:
2526
.RS
2627
.SY elbpcom
2728
.BI [ common\ options ]
28-
.BI \-\-space= SPACE
2929
.BI \-\-address= ADDRESS
3030
.BI \-\-write= HEXDATA
3131
.RE
3232

33+
Read and decode memory space info area:
34+
.RS
35+
.SY elbpcom
36+
.BI [\-\-space= MEMSPACE ]
37+
.BI \-\-read-info
38+
.RE
39+
3340
Sending arbitrary packets:
3441
.RS
3542
.SY elbpcom
@@ -54,13 +61,21 @@ If not specified, the default values are
5461
.BI \-\-ip= 192.168.1.121
5562
.BI \-\-port= 27181
5663
.BI \-\-timeout= .2
64+
.BI \-\-space= 0
65+
.BI \-\-size= 0
5766
.RE
5867

68+
If the
69+
.B --size
70+
argument
71+
.I TRANSFER_SIZE
72+
is 0, elbpcom will look up the preferred transfer size of the space in the space's info area.
73+
5974
This example demonstrates reading the HOSTMOT2 identifying string from the
6075
IDROM in space 0:
6176
.RS
6277
.nf
63-
$ elbpcom \-\-space 0 \-\-address 0x104 \-\-read 8
78+
$ elbpcom \-\-address 0x104 \-\-read 8
6479
> 82420401
6580
< 484f53544d4f5432
6681
HOSTMOT2

src/hal/utils/elbpcom.py

Lines changed: 96 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,38 @@
2626
parser = optparse.OptionParser("%prog [options] [commands]",
2727
description="Communicate with Mesa ethernet cards using the LBP16 protocol")
2828
parser.add_option("-i", "--ip", dest="sip",
29-
help="IP address of board",
29+
help="IP address of board (default: 192.168.1.121)",
3030
metavar="X.Y.Z.W", default="192.168.1.121")
3131
parser.add_option("-p", "--port", dest="sport",
32-
help="UDP port of board", type="int", default=27181)
32+
help="UDP port of board (default: 27181)", type="int", default=27181)
3333
parser.add_option("-t", "--timeout", dest="timeout",
34-
help="Response timeout in seconds", type="float", default=.2)
35-
parser.add_option("-s", "--space", dest="space", default=None,
34+
help="Response timeout in seconds (default: 0.2)", type="float", default=.2)
35+
parser.add_option("-s", "--space", dest="space", default=0,
3636
choices = ["0", "1", "2", "3", "4", "5", "6", "7"],
37-
help="Address space to read or write")
37+
help="Address space to read or write (default: 0, the hm2 register file)")
3838
parser.add_option("--info", dest="info", action="store_true",
3939
default=False,
4040
help="Select info area for read operation (default: memory space)")
4141
parser.add_option("-a", "--address", type="int", dest="address", default=None,
4242
help="Base address to read or write")
4343
parser.add_option("-I", "--increment", dest="increment", action="store_true",
4444
default=True,
45-
help="auto-increment address")
45+
help="auto-increment address (enabled by default, use --no-increment to disable)")
4646
parser.add_option("-n", "--no-increment", dest="increment",
4747
action="store_false",
4848
help="do not auto-increment address")
49+
parser.add_option("--size", dest="size",
50+
help="Transfer size in number of bytes (default: look up preferred transfer size in the space's info area)",
51+
type="int", default=0)
4952
parser.add_option("-r", "--read", type="int", dest="read", default=None,
5053
help="Number of bytes to read")
5154
parser.add_option("-w", "--write", type="string", dest="write", default=None,
5255
help="Hex-coded Values to read")
56+
57+
parser.add_option("--read-info", dest="read_info", default=False,
58+
action="store_true",
59+
help="Read and decode the info area of the selected memory space.")
60+
5361
options, args = parser.parse_args()
5462
if options.space: options.space = int(options.space)
5563

@@ -58,14 +66,13 @@
5866
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
5967
s.settimeout(options.timeout)
6068

61-
def transact(sdata, quiet=False, response=True):
62-
sdata = "".join(sdata.split()).decode("hex")
69+
def transact(sdata:bytes, quiet=False, response=True):
6370
s.sendto(sdata, (options.sip, options.sport))
6471
if not response: return
6572
try:
6673
data, daddr = s.recvfrom(1280)
67-
if not quiet: print("<", data.encode("hex"))
68-
if not quiet: print(" ", re.sub('[^ -~]', '.', data))
74+
if not quiet: print("<", data.hex())
75+
if not quiet: print(" ", re.sub('[^ -~]', '.', data.decode('utf-7', errors='replace')))
6976
return data
7077
except socket.timeout:
7178
if not quiet: print("! no response")
@@ -80,21 +87,21 @@ def interact():
8087
except KeyboardInterrupt:
8188
pass
8289

83-
def make_read_request(space, info, size, increment, address, nbytes):
90+
def make_read_request(space:int, info:bool, size:int, increment:bool, address:int, nbytes:int) -> bytes:
8491
return struct.pack("<HH",
8592
(1<<14) | (space << 10) | (info << 13)
86-
| (sizemap[size] << 8) | (increment << 7) | (nbytes/size),
93+
| (sizemap[size] << 8) | (increment << 7) | int(nbytes/size),
8794
address)
8895

89-
def make_write_request(space, info, size, increment, address, bytes):
96+
def make_write_request(space:int, info:bool, size:int, increment:bool, address:int, data:bytes) -> bytes:
9097
return struct.pack("<HH",
9198
(1<<15) | (1<<14) | (space << 10) | (info << 13)
92-
| (sizemap[size] << 8) | (increment << 7) | (len(bytes) / size),
93-
address) + bytes
99+
| (sizemap[size] << 8) | (increment << 7) | int(len(data) / size),
100+
address) + data
94101

95-
def optimal_size(space, info, address, nbytes):
102+
def optimal_size(space:int, info:bool, address:int, nbytes:int):
96103
if info: return 2
97-
info = transact(make_read_request(space, True, 2, True, 2, 4).encode("hex"), quiet=True)
104+
info = transact(make_read_request(space, True, 2, True, 2, 4), quiet=True)
98105
if info is None:
99106
raise RuntimeError("Failed to get information about memory space %d" % space)
100107
memsizes, memranges = struct.unpack("<HH", info)
@@ -108,25 +115,86 @@ def optimal_size(space, info, address, nbytes):
108115
return b
109116
raise ValueError("Access size incompatible with address or length (address=%d nbytes=%d memsizes=%d)" % (address, nbytes, memsizes))
110117

118+
def get_uint16(data:bytes, offset:int):
119+
return (data[offset+1] << 8) | data[offset]
120+
121+
def print_info(data:bytes):
122+
print(f"info area for memory space {options.space}:")
123+
124+
cookie = get_uint16(data, 0)
125+
print(f" cookie: 0x{cookie:04x}")
126+
127+
memsize = get_uint16(data, 2)
128+
memsize_writable = memsize & 0x8000
129+
memsize_type = (memsize & 0x7f00) >> 8
130+
memsize_access = memsize & 0x000f
131+
print(f" memsize: 0x{memsize:04x}")
132+
133+
print(" Writable" if memsize_writable else " Read-Only")
134+
135+
if (memsize_type == 0x01):
136+
print(" type=01 (Register)")
137+
elif (memsize_type == 0x02):
138+
print(" type=02 (Memory)")
139+
elif (memsize_type == 0x0e):
140+
print(" type=0e (EEPROM)")
141+
elif (memsize_type == 0x0f):
142+
print(" type=0f (Flash)")
143+
else:
144+
print(f" type={memsize_type:02x}(unknown)")
145+
146+
print(f" access=0x{memsize_access:01x}", end='')
147+
if memsize_access & 0x1:
148+
print(" 8-bit", end='')
149+
if memsize_access & 0x2:
150+
print(" 16-bit", end='')
151+
if memsize_access & 0x4:
152+
print(" 32-bit", end='')
153+
if memsize_access & 0x8:
154+
print(" 64-bit", end='')
155+
print()
156+
157+
memranges = get_uint16(data, 4)
158+
e = (memranges & 0xf800) >> 11
159+
p = (memranges & 0x07c0) >> 6
160+
s = memranges & 0x003f
161+
print(f" memranges: 0x{memranges:04x}")
162+
print(f" erase block size: {e} ({2**e} bytes)")
163+
print(f" page size: {p} ({2**p} bytes)")
164+
print(f" Ps address range: {s} ({2**s} bytes)")
165+
166+
addr_ptr = get_uint16(data, 6)
167+
print(f" addr ptr: 0x{addr_ptr:04x}")
168+
169+
name = str(data[8:], encoding='utf-7')
170+
print(f" name: {name}")
171+
172+
111173
if options.read:
112-
if options.space is None: raise SystemExit("--read must specify --space")
113174
if options.address is None: raise SystemExit("--read must specify --address")
114-
size = optimal_size(options.space, options.info, options.address, options.read if options.increment else 0)
115-
command = make_read_request(options.space, options.info, size, options.increment, options.address, options.read)
116-
command = command.encode("hex")
117-
print(">", command)
175+
if options.size == 0:
176+
options.size = optimal_size(options.space, options.info, options.address, options.read if options.increment else 0)
177+
command = make_read_request(options.space, options.info, options.size, options.increment, options.address, options.read)
178+
print(">", command.hex())
118179
transact(command)
119180

120181
elif options.write:
121-
if options.space is None: raise SystemExit("--write must specify --space")
122182
if options.address is None: raise SystemExit("--write must specify --address")
123-
write = options.write.decode("hex")
124-
size = optimal_size(options.space, options.info, options.address, len(write) if options.increment else 0)
125-
command = make_write_request(options.space, options.info, size, options.increment, options.address, write)
126-
command = command.encode("hex")
127-
print(">", command)
183+
write = bytes.fromhex(options.write)
184+
if options.size == 0:
185+
options.size = optimal_size(options.space, options.info, options.address, len(write) if options.increment else 0)
186+
command = make_write_request(options.space, options.info, options.size, options.increment, options.address, write)
187+
print(">", command.hex())
128188
transact(command, response=False)
129189

190+
elif options.read_info:
191+
if options.size == 0:
192+
options.size = optimal_size(options.space, True, 0x0000, 16)
193+
command = make_read_request(options.space, True, options.size, options.increment, 0x00, 0x10)
194+
print(">", command.hex())
195+
data = transact(command)
196+
print_info(data)
197+
130198
elif args:
131199
for a in args:
132200
transact(a)

0 commit comments

Comments
 (0)