Remove the separate first lock scope that hid emoji_image_ before
destroying gif_controller_ (added by PR #1848). Instead, move the
gif_controller_ cleanup into each lock scope where new content is set,
so destruction and creation happen atomically. This prevents both the
original race condition crash AND the visible flickering.
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
Agent-Logs-Url: https://github.com/78/xiaozhi-esp32/sessions/2dd0ff3a-4556-47a6-8d40-a30e18c01923
* Initial plan
* Add GPIO_NUM_NC guards for LampController and SingleLed across all board files
Boards crash when LAMP_GPIO or BUILTIN_LED_GPIO is set to GPIO_NUM_NC because
LampController and SingleLed are instantiated unconditionally.
Fix: Guard LampController with `if (LAMP_GPIO != GPIO_NUM_NC)` in InitializeTools()
and guard SingleLed with `if (BUILTIN_LED_GPIO != GPIO_NUM_NC)` in GetLed(),
falling back to NoLed when GPIO is not connected.
Fixes the reported crash on bread-compact-wifi-lcd and hardens all similar boards.
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Fix crash when LAMP_GPIO or BUILTIN_LED_GPIO is GPIO_NUM_NC (minimal 2-file fix)
Instead of adding guards in every board file (36 files), fix the root cause
in just 2 source files:
1. SingleLed constructor: replace assert(gpio != GPIO_NUM_NC) with graceful
early return, leaving led_strip_ as nullptr (all methods already null-check it)
2. LampController constructor: add early return when gpio_num == GPIO_NUM_NC
This fixes the crash on bread-compact-wifi-lcd and any other board where
these GPIOs are set to GPIO_NUM_NC.
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Remove esp_timer_delete from destructor to match original behavior
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Initial plan
* Fix GIF emotion switching crash: hide emoji_image_ before destroying gif_controller_
The crash was caused by a race condition in SetEmotion() where two separate
DisplayLockGuard scopes allowed the LVGL render task to access freed GIF image
data between lock scopes. By hiding emoji_image_ before destroying
gif_controller_ in the same lock scope, LVGL won't try to render the image
with freed data during the gap.
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Initial plan
* Fix LVGL object deletion issue in SetChatMessage
- Refresh child_count after deleting first_child to avoid using stale count
- Add lv_obj_is_valid() checks before accessing deleted objects
- Prevent duplicate deletion by refreshing child_count before system message deletion
- Ensures last_child validation before scrolling to it
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Address code review feedback on LVGL object deletion fix
- Move last_child retrieval after deletion to avoid stale pointer
- Add child_count > 0 check before scrolling to prevent edge case issues
- Add lv_obj_is_valid() check for last_bubble for consistency
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Final review: LVGL object deletion fix complete
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Remove std::thread wrappers in display callbacks to fix thread safety
Remove detached threads that were calling SetChatMessage from download/upgrade
progress callbacks. The DisplayLockGuard mutex already provides thread safety,
so we can call display methods directly from the callback thread without
spawning additional threads, which were causing race conditions.
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
* Use Application::Schedule() for display updates in callbacks
Instead of calling SetChatMessage directly from download/upgrade progress
callbacks, queue the updates using Application::Schedule(). This prevents
blocking the network receive task and avoids potential UART FIFO overflow
issues with 4G modems. The scheduled callbacks execute in the main task
thread, maintaining proper thread safety.
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: 78 <4488133+78@users.noreply.github.com>