You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(I started writing this as a comment on #312 but it got long, so I've made it its own issue)
Re https://glasgow-embedded.org/latest/use/repl-script.html#uart which i had a look at because Attie mentioned it in today's meeting, experimenting with it, it appears that the default iface.read() will read "whatever is available, possibly nothing": see
# Flush the buffer, so that everything written before the read reaches the device.
awaitself.flush(wait=False)
iflengthisNoneandlen(self._in_buffer) >0:
# Just return whatever is in the buffer.
length=len(self._in_buffer)
eliflengthisNone:
# Return whatever is received in the next transfer, even if it's nothing.
# (Gateware doesn't normally submit zero-length packets, so, unless that changes
# or customized gateware is used, we'll always get some data here.)
self._in_stalls+=1
awaitself._in_tasks.wait_one()
length=len(self._in_buffer)
with the default length=None. Which means as presented the example is a bit racey (I started looking into this as on my second write/read cycle in a run I got a partial return, even with "types by hand" delays, and while experimenting I got an empty byte string even after writing bytes).
It might be worth adding a note to the UART REPL example in the documentation to the effect that iface.read() will return "whatever is immediately available, which might not be the whole message as shown in the example". Or perhaps explicitly calling iface.read(length=6) to force reading all bytes expected to be returned for more user-reproducibility. (FTR, I wasn't that surprised by the short read, given it's a byte oriented serial line; but I was a bit surprised by having an iface.read() finish returning a zero length byte string when I had written something.)
Relatedly, help(iface) doesn't include any description of how the length parameter is interpreted on read(), which might be worth adding. Eg, "if length is omitted or None returns data immediately available; otherwise waits until required number of bytes have been received". Which I think would be a doc string on glasglow.access.direct.demultiplexer.DirectDemultiplexerInterface.read() since AFAICT that's what the REPL user is encouraged to use for interactive help:
ewen@parthenon:~$ glasgow repl uart -V 3.3
I: g.device.hardware: device already has bitstream ID d45fa78180875415078a05fcec3dd124
I: g.cli: running handler for applet 'uart'
I: g.applet.interface.uart: port(s) A, B voltage set to 3.3 V
I: g.applet.interface.uart: dropping to REPL; use 'help(iface)' to see available APIs
>>> type(iface)
<class 'glasgow.access.direct.demultiplexer.DirectDemultiplexerInterface'>
>>>
ETA: Example of the "zero bytes read" read (in this case on the same command line, to make it faster to reproduce; but I did also get this with "up arrow, run again" one command per command line earlier):
The UART should simply not return a DirectDemultiplexerInterface directly. In our chat I have called that out as incorrect and we should fix this instead of messing with documentation.
(I started writing this as a comment on #312 but it got long, so I've made it its own issue)
Re https://glasgow-embedded.org/latest/use/repl-script.html#uart which i had a look at because Attie mentioned it in today's meeting, experimenting with it, it appears that the default
iface.read()
will read "whatever is available, possibly nothing": seeglasgow/software/glasgow/access/direct/demultiplexer.py
Lines 227 to 241 in 05c44bd
length=None
. Which means as presented the example is a bit racey (I started looking into this as on my second write/read cycle in a run I got a partial return, even with "types by hand" delays, and while experimenting I got an empty byte string even after writing bytes).It might be worth adding a note to the UART REPL example in the documentation to the effect that
iface.read()
will return "whatever is immediately available, which might not be the whole message as shown in the example". Or perhaps explicitly callingiface.read(length=6)
to force reading all bytes expected to be returned for more user-reproducibility. (FTR, I wasn't that surprised by the short read, given it's a byte oriented serial line; but I was a bit surprised by having aniface.read()
finish returning a zero length byte string when I had written something.)Relatedly,
help(iface)
doesn't include any description of how thelength
parameter is interpreted onread()
, which might be worth adding. Eg, "if length is omitted or None returns data immediately available; otherwise waits until required number of bytes have been received". Which I think would be a doc string onglasglow.access.direct.demultiplexer.DirectDemultiplexerInterface.read()
since AFAICT that's what the REPL user is encouraged to use for interactive help:ETA: Example of the "zero bytes read" read (in this case on the same command line, to make it faster to reproduce; but I did also get this with "up arrow, run again" one command per command line earlier):
UART REPL example showing some racey behaviour
(Note also the final
iface.read()
which caught up on the outstanding message.)Example of partial message reads, including parts of two messages
(FTR, all of this is expected, but IMHO should be documented as expected to avoid user surprise.)
The text was updated successfully, but these errors were encountered: