hd44780: fix state corruption during 4-bit read-back (busy-flag polling) - #583
hd44780: fix state corruption during 4-bit read-back (busy-flag polling)#583felixmertins wants to merge 1 commit into
Conversation
|
It looks like LLM outout. What shows it is correct? |
|
Yes, I use an LLM when writing things up. The findings themselves come from debugging my own firmware against this part, but fair point, prose doesn't prove anything. So I've added a regression test to the branch instead. The firmware (tests/atmega644_hd44780.c) brings the LCD up in 4-bit mode and polls the busy flag before every byte, wired bidirectionally like examples/board_hd44780/charlcd.c. The test driver then compares DDRAM against what was written. Results:
The mechanism is also easy to check by hand on master: hd44780_process_read() raises IRQ_HD44780_ALL with the read-back nibble (hd44780.c line 313), and the ALL case of the part's own pin hook (line 370) decodes RS, RW and E out of that value, without the REENTRANT guard that the D0..D7 case right below it has. So every status read rewrites the part's idea of RW. The test hooks into the existing tests/ machinery and runs as part of make run_tests. It needs one extra make rule because it links examples/parts/hd44780.c, which is not part of libsimavr. |
|
I am hampered as a reviewer by being unfamiliar with both the device and the emulation code. This looks like a fairly straightforward case of a bug in peripheral code's handling of input IRQs generated by its own actions, something that has been a problem for the ioport code in the core, as well. Is that correct? Very nice to see new test code and I am happy to merge this, except that is too verbose, both in the number of commits, their descriptions and in-code comments. Can you squash it to a single commit with a one or two-line description? I am struck by the difference in style between comments in the fix code and the test, and guessing that you wrote all the test code yourself. A personal re-write of the fix comments would be nice, but not essential. Alternatively, I can do a squash merge, but that will put my name on your submission (I think it will show both.) Please let me know. Thanks, G. |
…test The part decoded its own IRQ_HD44780_ALL raise during reads as pin input, clobbering RS/RW/E; and pinstate went stale while driving reads, so the filtered ioport IRQs swallowed the next same-level write. Both broke busy-flag polling.
|
Yes, that's it. The read path raises IRQ_HD44780_ALL with the nibble it drives back, and the part's own pin hook decodes that as if the firmware had set the pins, RW included. Same kind of thing as the ioport re-entry problems. The pinstate half is fallout from the same raise, the filtered ioport IRQs remember the driven level, so if pinstate stops tracking during reads, a later write of the same level never reaches the part. |
8bacfbd to
931b10e
Compare
Fixes #582
Two independent defects made the HD44780 part unusable with firmware
that polls the busy flag in 4-bit mode (standard bidirectional wiring as
in
examples/board_hd44780). Details, cycle traces and analysis in thelinked issue; summary:
hd44780: don't reinterpret our own readback as pin input—hd44780_process_read()raisesIRQ_HD44780_ALLwith the nibble itdrives back to the AVR; the part's own pin hook decoded that value as
a full pin set and clobbered RS/RW/E in
pinstate, so the discardstrobe of a busy poll was processed as a garbage write. The
ALLcase now honours
HD44780_PRIV_FLAG_REENTRANT, exactly like theD0 ... D7case already does.hd44780: track the data pins while driving a read back— theD0 ... D7early-return underREENTRANTleftpinstatestalewhile the FILTERED ioport pin IRQs cached the read-back level; a
subsequent firmware write of the same logic level produced no edge
notification and was latched with old data bits (single-bit
corruption in characters written after busy polls).
pinstatenowtracks the value the part drives itself — it is the real bus level,
nothing in the read path samples it, and the FILTERED D IRQs keep
the bidirectional connection loop-free.
Validation: my AVR project uses an HD44780 driver that busy-polls before
every byte. Unpatched, the display stays empty / fills with garbage
(traces in the issue). With these two commits, the full LCD regression
suite (init sequence, both DDRAM lines, writes right after busy polls)
passes with no board-side workarounds. No change for firmwares that use
timed writes only, and external users of
IRQ_HD44780_ALLas an inputare unaffected.