Conversation
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
PR Summary by QodoMAX7456: Bound display-clear polling to prevent scheduler stalls
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
1. Later refreshes can erase new output
|
| break; | ||
| } | ||
| if (cmpTimeUs(micros(), clearStart) > MAX7456_CLEAR_TIMEOUT_US) { | ||
| state.registers.dmm = dmm & ~DMM_CLEAR_DISPLAY; |
There was a problem hiding this comment.
1. Later refreshes can erase new output 🐞 Bug ≡ Correctness
max7456RefreshAll() caches dmm & ~DMM_CLEAR_DISPLAY on timeout, so the documented stuck value 0x06 changes the persistent shadow from 0x00 to 0x02 instead of preserving the requested mode. On the next resync, bit 2 is added to that shadow to produce the defined vertical-clear command 0x06, while the function stops waiting after 2 ms and immediately redraws, allowing the deferred clear to remove freshly written content.
Agent Prompt
## Issue description
The timeout path derives the persistent DMM shadow from the anomalous hardware readback. A stuck `0x06` response therefore preserves the vertical-clear selector and changes all later refresh commands.
## Fix Focus Areas
- src/main/drivers/max7456.c[648-665]
## Recommended Fix
On timeout, retain the pre-command `state.registers.dmm` value rather than copying the untrusted DMM readback; the clear bit was only ORed into the bus write and is not present in the shadow. Add coverage that repeatedly returns `0x06`, times out, and verifies that the next clear command remains the original shadow plus only `DMM_CLEAR_DISPLAY`.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Fixed in f115375: on timeout the DMM shadow is now left as written instead of being taken from the readback, so a stuck 0x06 can no longer turn later clears into deferred VSYNC clears.
d31a558 to
d0f484b
Compare
max7456RefreshAll() polls DMM bit 2 in an unbounded loop after issuing a clear. On an AT7456E-based board (NewBeeDrone LionBee, AT32F435) the bit never clears (DMM reads back 0x06), so the OSD task spins forever. The scheduler then starves the serial task: USB VCP enumerates but accepts no data, which is indistinguishable from a boot hang. Bound the wait to 2 ms (the datasheet clear time is ~20 us). Betaflight does not poll this bit at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d0f484b to
f115375
Compare
Problem
max7456RefreshAll()setsDMM_CLEAR_DISPLAYand then polls DMM bit 2 in an unboundedwhile (1)until the chip clears it. On a NewBeeDrone LionBee (AT32F435, AT7456E-compatible OSD) the bit never clears: DMM reads back0x06. The OSD task spins forever and starves the serial task. USB VCP still enumerates but accepts no data, so the board looks hung at boot.Cause
The busy loop has no timeout. Betaflight's MAX7456 driver never polls this bit.
Fix
Bound the wait to 2 ms (
MAX7456_CLEAR_TIMEOUT_US). The datasheet clear time is about 20 µs, so a working chip still leaves the loop on the first or second read. If the chip never clears the bit, the refresh carries on instead of hanging.On timeout the DMM shadow is left as written rather than taken from the readback. The stuck value
0x06has bit 1 set, and keeping it would turn every later clear into a deferred VSYNC clear that can erase freshly drawn characters (thanks to the Qodo review for catching this).How it was found / tested
spiBusReadRegistercalled from this loop.