Skip to content

fix(c14): LCD flush never acknowledged; tidy STICK_DEAD_ZONE on gx15 and t15pro - #7688

Merged
pfeerick merged 2 commits into
mainfrom
pfeerick/c14-flush-and-deadzone
Aug 21, 2026
Merged

fix(c14): LCD flush never acknowledged; tidy STICK_DEAD_ZONE on gx15 and t15pro#7688
pfeerick merged 2 commits into
mainfrom
pfeerick/c14-flush-and-deadzone

Conversation

@pfeerick

@pfeerick pfeerick commented Aug 21, 2026

Copy link
Copy Markdown
Member

Two fixes found while preparing the 2.12.3 backport series (#7687). Both apply to main in their own right.

fix(c14): LCD flush never acknowledged, locking up the radio

#7483 moved responsibility for signalling flush completion out of flushLcd() and into the drivers — it no longer calls lv_disp_flush_ready() after invoking the flush callback, so each driver must call lcdFlushed() itself. Every other driver was updated at the time; targets/c14 was missed.

startLcdRefresh() is synchronous — it busy-waits for the LTDC shadow register reload and returns — so nothing ever acknowledges the flush. LVGL leaves draw_buf->flushing set and the next refresh spins forever in the wait loop in lv_refr.c, since disp_drv.wait_cb is only populated under SIMU.

Expected symptoms on hardware: the radio reaches the splash screen and stops. The bootloader carries the same contract change in boot_lcd.cpp, and bootloaderUF2()'s loop is what calls usbStart() and drives the flashing state machine — so once it wedges on the second frame the UF2 drive never appears either, and recovery needs DFU mode.

Confirmed on C14 hardware. Was missed in #7494.

chore(build): use the renamed STICK_DEAD_ZONE option on gx15 and t15pro

#7638 replaced the stale commented-out declaration with a real option(... OFF) for t22, tx15, tx16smk3 and v12, but missed two targets:

  • gx15 — still on the old plural name in both places, so if(STICKS_DEAD_ZONE) was always false
  • t15pro — already used the singular name in the guard, but left its option() declaration commented out

In both cases the option was never declared, so the guard was dead and the sticks dead zone could not be enabled at all. Declaring it explicitly is also what stops the value leaking in from another target's CMake cache, which is the bug #7638 set out to fix.

No functional change — the option defaults OFF, so -DSTICK_DEAD_ZONE is still never added, and neither yaml_datastructs_gx15.cpp nor yaml_datastructs_t15pro.cpp is affected; both already carry YAML_PADDING(3) in that slot, matching t22. Turning either on is a separate decision that would need the YAML regenerated.

Testing

Built clean on this branch: c14 (1,352,276), gx15 (1,374,460), t15pro (1,368,200).

#7483 moved the responsibility for signalling flush completion out of
flushLcd() and into the drivers: it no longer calls lv_disp_flush_ready()
after invoking the flush callback, so each driver has to call lcdFlushed()
itself. Every other driver was updated at the time; targets/c14 was missed.

startLcdRefresh() is synchronous - it busy-waits for the LTDC shadow
register reload and returns - so nothing else ever acknowledges the flush.
LVGL leaves draw_buf->flushing set, and the next refresh spins forever in
the wait loop in lv_refr.c, since disp_drv.wait_cb is only populated under
SIMU. The radio reaches the splash screen and stops.

The same applies to the bootloader, which carries the identical contract
change in boot_lcd.cpp: bootloaderUF2()'s loop calls usbStart() and drives
the flashing state machine, so once it wedges on the second frame the UF2
drive never appears and recovery needs DFU mode.

Found while backporting #7483 to 2.12, where boards/helloradio-h750 was
missing the call as well - that one already had it here.
#7638 replaced the stale commented-out declaration with a real
option(... OFF) for t22, tx15, tx16smk3 and v12, but missed two targets:

  gx15   - still on the old plural name in both places, so
           if(STICKS_DEAD_ZONE) was always false
  t15pro - already used the singular name in the guard, but left its
           option() declaration commented out

In both cases the option was never declared, so the guard was dead and the
sticks dead zone could not be enabled at all. Declaring it explicitly is
also what stops the value leaking in from another target's CMake cache,
which is the bug #7638 set out to fix.

No functional change: the option defaults OFF, so -DSTICK_DEAD_ZONE is
still never added and neither yaml_datastructs_gx15.cpp nor
yaml_datastructs_t15pro.cpp is affected - both already carry
YAML_PADDING(3) in that slot, matching t22. Turning either on is a
separate decision that would need the YAML regenerated.
@pfeerick pfeerick added this to the 3.0 milestone Aug 21, 2026
@pfeerick pfeerick added bug 🪲 Something isn't working house keeping 🧹 Cleanup of code and house keeping compilation Related to compiling the firmware and firmware options labels Aug 21, 2026
@pfeerick
pfeerick merged commit e0e42ee into main Aug 21, 2026
45 checks passed
@pfeerick
pfeerick deleted the pfeerick/c14-flush-and-deadzone branch August 21, 2026 02:51
@pfeerick pfeerick mentioned this pull request Aug 21, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug 🪲 Something isn't working compilation Related to compiling the firmware and firmware options house keeping 🧹 Cleanup of code and house keeping

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant