Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LVGL & WIFI = Crash #310

Open
tremblayraphael29 opened this issue May 5, 2022 · 11 comments
Open

LVGL & WIFI = Crash #310

tremblayraphael29 opened this issue May 5, 2022 · 11 comments

Comments

@tremblayraphael29
Copy link

tremblayraphael29 commented May 5, 2022

We use GitHub issues for development related discussions.

Describe the issue
The problem only happens when I integrate a task that connects the esp32 to a wifi access point. In fact, the task is not even executed yet that I get a “Panic Core dump (LoadStore Error)”.
So the error does not come from an error in the task itself.

Code to reproduce the issue
lv_port_esp32 (lv_demo_widget) with wifi station connect task

ESP32 Chip version
ESP32 devkit (4 MB flash, chip revision 1, ESP32-D0WDQ6)

ESP-IDF version
version : 4.3

Compilation warnings/errors (if available)
Console terminal result :

I (26) boot: ESP-IDF v4.3.1-dirty 2nd stage bootloader
I (26) boot: compile time 16:37:41
I (27) boot: chip revision: 1
I (30) boot_comm: chip revision: 1, min. bootloader chip revision: 0
I (37) boot.esp32: SPI Speed : 80MHz
I (41) boot.esp32: SPI Mode : DIO
I (46) boot.esp32: SPI Flash Size : 4MB
I (51) boot: Enabling RNG early entropy source…
I (56) boot: Partition Table:
I (60) boot: ## Label Usage Type ST Offset Length
I (67) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (74) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (82) boot: 2 factory factory app 00 00 00010000 00100000
I (89) boot: End of partition table
I (93) boot_comm: chip revision: 1, min. application chip revision: 0
I (100) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=9c1b0h (639408) map
I (302) esp_image: segment 1: paddr=000ac1d8 vaddr=3ffb0000 size=02f3ch ( 12092) load
I (306) esp_image: segment 2: paddr=000af11c vaddr=40080000 size=00efch ( 3836) load
I (309) esp_image: segment 3: paddr=000b0020 vaddr=400d0020 size=4a088h (303240) map
I (408) esp_image: segment 4: paddr=000fa0b0 vaddr=40080efc size=0e2b4h ( 58036) load
I (428) esp_image: segment 5: paddr=0010836c vaddr=50000000 size=00010h ( 16) load
I (436) boot: Loaded app from partition at offset 0x10000
I (436) boot: Disabling RNG early entropy source…
I (449) cpu_start: Pro cpu up.
I (449) cpu_start: Starting app cpu, entry point is 0x400813ec
0x400813ec: call_start_cpu1 at C:/Users/Utilisateur/esp/esp-idf/components/esp_system/port/cpu_start.c:141
I (0) cpu_start: App cpu up.
I (463) cpu_start: Pro cpu start user code
I (463) cpu_start: cpu freq: 240000000
I (463) cpu_start: Application information:
I (467) cpu_start: Project name: lvgl-demo
I (473) cpu_start: App version: 2.1.0.0
I (478) cpu_start: Compile time: May 3 2022 08:59:31
I (484) cpu_start: ELF file SHA256: 6721320b3e46e617…
I (490) cpu_start: ESP-IDF: v4.3.1-dirty
I (495) heap_init: Initializing. RAM available for dynamic allocation:
I (502) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (508) heap_init: At 3FFB3FE8 len 0002C018 (176 KiB): DRAM
I (515) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (521) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (527) heap_init: At 4008F1B0 len 00010E50 (67 KiB): IRAM
I (534) spi_flash: detected chip: generic
I (538) spi_flash: flash io: dio
I (543) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (553) I2C: i2c_initialisation
I (553) I2C: mcp23008_initialisation
I (563) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (573) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (583) gpio: GPIO[32]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:3
I (593) gpio: GPIO[33]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:3
I (603) gpio: GPIO[39]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:3
I (603) gpio: GPIO[0]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
Opening Non-Volatile Storage (NVS) handle… Done
Reading restart counter from NVS …
intervalle_lavage= 100
The value is not initialized yet!
I (633) lvgl_helpers: Display buffer size: 53248
I (633) lvgl_helpers: Initializing SPI master for FT81X
I (643) lvgl_helpers: Configuring SPI host VSPI_HOST (2)
I (643) lvgl_helpers: MISO pin: 19, MOSI pin: 23, SCLK pin: 18, IO2/WP pin: 16, IO3/HD pin: 4
I (663) lvgl_helpers: Max transfer size: 212992 (bytes)
I (663) lvgl_helpers: Initializing SPI bus…
I (663) disp_spi: Adding SPI device
I (673) disp_spi: Clock speed: 23000000Hz, mode: 0, CS pin: 5
I (753) FT81X: Switching to QIO mode
I (773) FT81X: DummyReadBits = 2
I (1773) FT81X: CHIP ID (Display EVE3) = 124
REG_FREQUENCY = 72000000
Guru Meditation Error: Core 0 panic’ed (LoadStoreError). Exception was unhandled.
Core 0 register dump:
PC : 0x40118fc0 PS : 0x00060f30 A0 : 0x800e0d4c A1 : 0x3ffbace0
0x40118fc0: lv_style_get_prop_inlined at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/misc/lv_style.h:373
(inlined by) lv_style_get_prop at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/misc/lv_style.c:214
A2 : 0x3f4867b8 A3 : 0x00001032 A4 : 0x3ffbad00 A5 : 0x00000000
A6 : 0x00000010 A7 : 0x00000001 A8 : 0x00000100 A9 : 0x00000000
A10 : 0x400f43d8 A11 : 0x400f43d8 A12 : 0x400f42d8 A13 : 0x00000040
0x400f43d8: lv_disp_draw_buf_init at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/hal/lv_hal_disp.c:108
0x400f43d8: lv_disp_draw_buf_init at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/hal/lv_hal_disp.c:108
0x400f42d8: lv_font_get_glyph_dsc_fmt_txt at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/font/lv_font_fmt_txt.c:150
A14 : 0x00001001 A15 : 0x00000000 SAR : 0x0000001d EXCCAUSE: 0x00000003
EXCVADDR: 0x400f43d8 LBEG : 0x400013f9 LEND : 0x4000140d LCOUNT : 0xfffffffa
0x400f43d8: lv_disp_draw_buf_init at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/hal/lv_hal_disp.c:108
Backtrace:0x40118fbd:0x3ffbace0 0x400e0d49:0x3ffbad00 0x400e0dac:0x3ffbad50 0x400de437:0x3ffbad80 0x400fb929:0x3ffbada0 0x400fc42e:0x3ffbae40 0x40117bb9:0x3ffbae80 0x400da9a3:0x3f
0x400e115d:0x3ffbaf20 0x400d82ae:0x3ffbaf40 0x400d979b:0x3ffbb050 0x400d987b:0x3ffbb070 0x400d6d37:0x3ffbb090 0x400d6df3:0x3ffbb0b0 0x4008afbd:0x3ffbb140
0x40118fbd: lv_style_get_prop_inlined at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/misc/lv_style.h:373
(inlined by) lv_style_get_prop at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/misc/lv_style.c:214
0x400e0d49: get_prop_core at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_obj_style.c:587
0x400e0dac: lv_obj_get_style_prop at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_obj_style.c:220
0x400de437: lv_obj_get_style_border_width at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_obj_style_gen.h:298
(inlined by) lv_obj_get_content_coords at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_obj_pos.c:573
0x400fb929: lv_label_refr_text at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/widgets/lv_label.c:891
0x400fc42e: lv_label_event at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/widgets/lv_label.c:758
0x40117bb9: lv_obj_event_base at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_event.c:96
0x400da9a3: event_send_core at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_event.c:414
0x400daa52: lv_event_send at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_event.c:73
0x400e103d: lv_obj_refresh_style at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_obj_style.c:182
0x400e115d: lv_obj_add_style at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lvgl/src/core/lv_obj_style.c:103
0x400d82ae: infos_create at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lv_examples/lv_examples/src/lv_confortum/lv_confortum.c:370
0x400d979b: main_page at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lv_examples/lv_examples/src/lv_confortum/lv_confortum.c:222
0x400d987b: lv_confortum at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/components/lv_examples/lv_examples/src/lv_confortum/lv_confortum.c:192
0x400d6d37: create_demo_application at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/main/main.c:552
0x400d6df3: guiTask at C:\Users\Utilisateur\esp\esp-idf\lv_port_esp32_9\build/…/main/main.c:526 (discriminator 2)
0x4008afbd: vPortTaskWrapper at C:/Users/Utilisateur/esp/esp-idf/components/freertos/port/xtensa/port.c:168
ELF file SHA256: 6721320b3e46e617
Rebooting…

LOG LVGL DETAILS

[...]
[Trace] (17.592, +8) event_send_core: Sending event 34 to 0x3ffb6070 with 0x3ffb6218 param (in lv_event.c line #403)
[Trace] (17.603, +11) event_send_core: Sending event ended (in lv_event.c line #437)
[Trace] (17.610, +7) event_send_core: Sending event 38 to 0x3ffb6218 with 0x3ffdf590 param (in lv_event.c line #403)
[Trace] (17.621, +11) event_send_core: Sending event ended (in lv_event.c line #437)
[Trace] (17.628, +7) event_send_core: Sending event 38 to 0x3ffb6218 with 0x3ffdf590 param (in lv_event.c line #403)
[Trace] (17.639, +11) event_send_core: Sending event ended (in lv_event.c line #437)
Guru Meditation Error: Core 0 panic'ed (LoadStoreError). Exception was unhandled.
If possible, copy the compilation log into a file and attach it here

@derlaft
Copy link

derlaft commented Jan 30, 2023

I have based my example off this repo and I have spent EXTREMELY LONG TIME and nights debugging a similar issue. In short, this is fixed by two following things:

  • Adding IRAM_ATTR attribute to the lv_tick_task
  • Adding -DLV_ATTRIBUTE_TICK_INC=IRAM_ATTR to the platformio.ini build_flags (or applying LV_ATTRIBUTE_TICK_INC=IRAM_ATTR in your lvgl config).

When it manifests:

  • Your lvgl is running in one task
  • In the other task, you are performing some actions which require disabling memory access and cores, including but not limited to:
    • starting/stopping wireless connection Wifi.begin(...)
    • writing to flash memory, for example with Preferences.

Why it happens:

  • During that time, interrupt is fired and CPU jumps to the code. Without IRAM_ATTR the code is not in the cache, it's impossible to exec interruption handler
  • If you try to work around with noInterrupts() and interrupts(), you might reduce the scope of the problem, but instead you get some severe watchdog problems which cause unexpected restarts.

Hope it helps some people. I will try to create a PR to this repo a bit shortly after (but if someone wants to do that first, feel free to do so).

@Viatorus
Copy link

Hmm, we saw a MemFault/BusFault after executing lv_font_get_glyph_dsc_fmt_txt() in one of our nightly tests.

We never saw this kind of error before and we yet couldn't reproduce the issue.

I just saw you also mention "lv_font_get_glyph_dsc_fmt_txt" in your logs and we also use the the cache options of the microcontroller. But we are running on a STM32H7 so a really different platform...

@derlaft
Copy link

derlaft commented Feb 20, 2023

and we also use the the cache options of the microcontroller.

@Viatorus if that's the same issue, you can relatively easy rule it out:

  • Modify your application so that crash occurs every single time. In my case I had a function which saved settings to flash every minute. Instead I modified it to run 10 times a second, so random crash occured almost instantly after boot. That will help you identify the cause later.
  • Remove the timer which calls lv_tick_task. LVGL will be effectively broken, but all function calls will continue working as normal. If the application has stopped crashing, then you have the same issue as I had.
  • If you still have crashes, disable parts of your application one by one, until it stops crashing.

I just saw you also mention "lv_font_get_glyph_dsc_fmt_txt" in your logs

In my case stacktraces were basically useless, because the program memmory was not accessible. Therefore the execution jumped to random addresses of the code. Ideally debugger is needed to find a cause for such an issue, but unfortunately I didn't have any access to it.

@pafeltowicz
Copy link

I have a same problem.

void scanWifi(void *parameter) {
    lv_obj_t *display = (lv_obj_t *) parameter;
    lv_obj_t *list = lv_list_create(display);
    lv_obj_set_size(list, LV_PCT(100), LV_PCT(100));
    WiFi.begin();
    int n = WiFi.scanNetworks();
    Serial.println("[*] Scan done");
    if (n < 0) {
        Serial.println("[-] No WiFi networks found");
    } else {
        Serial.println((String) "[+] " + n + " WiFi networks found\n");
        for (int i = 0; i < n; ++i) {
            lv_list_add_btn(list, NULL, WiFi.SSID(i).c_str());
            vTaskDelay(10 / portTICK_PERIOD_MS);
        }
    }

    vTaskDelete(TaskHandle_2);
}
xTaskCreate(scanWifi, "scanWifi", 1024 * 10, (void *) display, 10, &TaskHandle_2);

@stale
Copy link

stale bot commented Apr 20, 2023

This issue or pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale This will not be worked on label Apr 20, 2023
@Potak0
Copy link

Potak0 commented Jan 24, 2024

Exactly the same issue. It simply crash and crash and took me long time trying to solve the problem by increasing stack amount,adding some vTaskDelay, some sort like that,but these did nothing good...as @derlaft 's advice,adding iram attr actually helps a lot. Now my issue is like random wdt reset. Working hard on it.

@stale stale bot removed the stale This will not be worked on label Jan 24, 2024
@derlaft
Copy link

derlaft commented Jan 24, 2024

@Potak0 btw I wrote a sligthly more detailed writeup here, it might contain a bit more details and debugging steps which could help you

@Potak0
Copy link

Potak0 commented Jan 24, 2024

@derlaft that does increased my understanding.thanks a lot.

@axlb97
Copy link

axlb97 commented Feb 9, 2024

I've also been dealing with a similar issue. In my case, the problem arises after calling the WiFi.begin() function. The microcontroller doesn't restart, but the display randomly glitches or stays black. I got the code from a design made in SquareLine Studio. I tried adding the attribute -DLV_ATTRIBUTE_TICK_INC=IRAM_ATTR to the platformio.ini build_flags, but it didn't improve things. As a temporary solution, I'm calling the "tft.init()" function after waiting for the wifi to connect. It's not the most sophisticated solution, but it buys me time to find a more accurate one.

WiFi.begin(ssid_sta, password_sta);  
WiFi.waitForConnectResult(1000);
tft.init();

The post from @derlaft explaining the origin of the problem helped me a lot. And wanting to understand better, I looked for diagrams of how the ESP32 is internally structured on the Espressif and Xtensa websites to see how the buses and modules are interconnected, but I didn't have any success.

@derlaft
Copy link

derlaft commented Feb 9, 2024

@axlb97 I've just checked my platformio.ini and it has also:

  • -DLV_ATTRIBUTE_TIMER_HANDLER=IRAM_ATTR
  • -DLV_ATTRIBUTE_FLUSH_READY=IRAM_ATTR

I don't remember why I added them (likely for performance), but double-checking if they help you should not hurt

What else comes to my mind:

@axlb97
Copy link

axlb97 commented Feb 10, 2024

@derlaft

@axlb97 I've just checked my platformio.ini and it has also:

  • -DLV_ATTRIBUTE_TIMER_HANDLER=IRAM_ATTR
  • -DLV_ATTRIBUTE_FLUSH_READY=IRAM_ATTR
    I don't remember why I added them (likely for performance), but double-checking if they help you should not hurt

I'm going to remove the call to tft.init() and add those attributes to platformio.ini to see if it improves. Calling tft.init() makes the display go black for a second and it's annoying.

If the device doesn't have a connection, it retries the reconnection every 20 seconds, so every 20 seconds tft.init() is called.
In setup(), i disabled the auto-reconnection with WiFi.setAutoreconnect(false).
But seeing that calling a function of tft to resolve the issue makes me suspect that it's maybe a problem with that library and not with lvgl, idk.
Since i need to have them finished soon since these devices are required in the laboratories where i work i started working on a parallel code where i use sprites to shape the interface, after all, it's a very simple design. But i haven't made much progress yet. i wasn't very happy with that because that way I can't use the Montserrat font.

What else comes to my mind:

  • Do you (or maybe the display) use ADC2? (It's shared with Wi-Fi)

Now that I notice, something like that. I don't use ADC2, but the DC pin of the display is connected to GPIO2 (ADC2_2), maybe causing issues.

Since the code related to lvgl is generated by Squareline Studio when exporting the project (I don't have any previous experience with lvgl before this. In fact, I came to know lvgl thanks to squareline studio while looking for an easy way to design my interfaces.) I couldn't find where the tasks are declared and what priority they are assigned. A similar function to the one you showed me is this one (also generated by Squareline Studio).

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    uint32_t w = (area->x2 - area->x1 + 1);
    uint32_t h = (area->y2 - area->y1 + 1);

    tft.startWrite();
    tft.setAddrWindow(area->x1, area->y1, w, h);
    tft.pushColors((uint16_t *)&color_p->full, w * h, true);
    tft.endWrite();

    lv_disp_flush_ready(disp);
}

I've created another task to execute the lv_timer_handler() function every 5ms
xTaskCreatePinnedToCore(taskDisplayHandler, "TaskDisplayHandler", 4096, NULL, 20, NULL, 1);
Its definition:

 LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
{
    TIMER_TRACE("begin");

    /*Avoid concurrent running of the timer handler*/
    static bool already_running = false;
    if(already_running) {
        TIMER_TRACE("already running, concurrent calls are not allow, returning");
        return 1;
    }
    already_running = true;

    if(lv_timer_run == false) {
        already_running = false; /*Release mutex*/
        return 1;
    }

    static uint32_t idle_period_start = 0;
    static uint32_t busy_time         = 0;

    uint32_t handler_start = lv_tick_get();

    if(handler_start == 0) {
        static uint32_t run_cnt = 0;
        run_cnt++;
        if(run_cnt > 100) {
            run_cnt = 0;
            LV_LOG_WARN("It seems lv_tick_inc() is not called.");
        }
    }

    /*Run all timer from the list*/
    lv_timer_t * next;
    do {
        timer_deleted             = false;
        timer_created             = false;
        LV_GC_ROOT(_lv_timer_act) = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll));
        while(LV_GC_ROOT(_lv_timer_act)) {
            /*The timer might be deleted if it runs only once ('repeat_count = 1')
             *So get next element until the current is surely valid*/
            next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), LV_GC_ROOT(_lv_timer_act));

            if(lv_timer_exec(LV_GC_ROOT(_lv_timer_act))) {
                /*If a timer was created or deleted then this or the next item might be corrupted*/
                if(timer_created || timer_deleted) {
                    TIMER_TRACE("Start from the first timer again because a timer was created or deleted");
                    break;
                }
            }

            LV_GC_ROOT(_lv_timer_act) = next; /*Load the next timer*/
        }
    } while(LV_GC_ROOT(_lv_timer_act));

    uint32_t time_till_next = LV_NO_TIMER_READY;
    next = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll));
    while(next) {
        if(!next->paused) {
            uint32_t delay = lv_timer_time_remaining(next);
            if(delay < time_till_next)
                time_till_next = delay;
        }

        next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), next); /*Find the next timer*/
    }

    busy_time += lv_tick_elaps(handler_start);
    uint32_t idle_period_time = lv_tick_elaps(idle_period_start);
    if(idle_period_time >= IDLE_MEAS_PERIOD) {
        idle_last         = (busy_time * 100) / idle_period_time;  /*Calculate the busy percentage*/
        idle_last         = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/
        busy_time         = 0;
        idle_period_start = lv_tick_get();
    }

    already_running = false; /*Release the mutex*/

    TIMER_TRACE("finished (%d ms until the next timer call)", time_till_next);
    return time_till_next;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants