[SOLVED] Lv_task_handler returns 4294967295


What MCU/Processor/Board and compiler are you using?


What do you experience?

Give a detailed description. “It doesn’t work” is not enough information for us to diagnose the issue.

my display flush function wasn’t being executed, so i checked what value lv_task_handler returns and it is a big number (4294967295), so I guess that’s why the flush function isn’t being called.

What do you expect?

Flush function being called so the display is updated as expected.

Code to reproduce

My code is in this branch: https://github.com/lvgl/lv_port_esp32/pull/110

I’m having this problem with a monochrome display (SSD1306), the same code works for LVGL v6 and TFT displays in LVGL v6 and v7.

Screenshot and/or video

If possible, add screenshots and/or videos about the current issue.

Using the LVGL log in TRACE level:

First off, congratulations; you’re the first person that I know of (besides me) to experiment with this feature. :slightly_smiling_face:

Do you have an input device registered? If it returns that value it means that there is no need to refresh anything until there is user input or an API call that invalidates an area.

I’m not really using it and we don’t have any indev registered, it’s only weird that i get back such big number. Here’s the output using an ST7789 display, same program, the biggest number i get back is 30.


There must be something funny going on on my configuration…

Seems like lv_task_handler is returning LV_NO_TASK_READY which is 0xFFFFFFFF or 4294967295 in decimal.

If _lv_ll_get_head returns NULL then lv_task_handler will return time_till_next equal to LV_NO_TASK_READY.

The problem is I created a label and because the flush function is not being called, not even once, the display doesn’t show the label. I’m sure it’s something silly.

This is how we create the label:

    /* Get the current screen  */
    lv_obj_t * scr = lv_disp_get_scr_act(NULL);

    /*Create a Label on the currently active screen*/
    lv_obj_t * label1 =  lv_label_create(scr, NULL);

    /*Modify the Label's text*/
    lv_label_set_text(label1, "Hello\nworld!");

    /* Align the Label to the center
     * NULL means align on parent (which is the screen now)
     * 0, 0 at the end means an x, y offset after alignment*/
    lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, 0);

When there’s no input device, there is no work to be done, hence LittlevGL returns LV_NO_TASK_READY telling you to enter your idle state (and wake up when input is available).

It should, however, refresh the display at least once. Are you creating the label before the call to lv_task_handler or in a separate thread? If you’re creating it in a different thread, you will need to manually wake up the lv_task_handler thread. I hadn’t thought of this when designing the API but it’s a limitation in the way it works right now.

If the coordinates are rounded to the full display size, LVGL is forced to refresh the display at once. It required screen sized display buffer(s) too.


Thanks for the help, yes, the label is being created before calling lv_task_handler. Everything is created on the same thread.

If I run the same project with other display controller I get one flush and the label is displayed correctly.

The display is 128x64 pixels, sorry, I don’t understood you, should I force flushing the display?

It’s strange that next is NULL on lines 182-184 of lv_task.c. I’m sure you called lv_init or other things wouldn’t work. Perhaps it’s worth using a debugger?

So I have some good news, I was using a double buffer, each of them are the size of the screen. If I remove one of them while keeping the other of the screen size I get a flush call and the label is displayed (not clear text) I guess I can fix that in one of the callbacks. Will update a photo once I have a chance.


    static lv_color_t buf1[DISP_BUF_SIZE]; // DISP_BUF_SIZE = 8192 = 128*64 (display size)
    static lv_color_t buf2[DISP_BUF_SIZE];
    static lv_disp_buf_t disp_buf;

    uint32_t size_in_px = DISP_BUF_SIZE;

    lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px);


    static lv_color_t buf1[DISP_BUF_SIZE]; // DISP_BUF_SIZE = 8192 = 128*64 (display size)
    static lv_disp_buf_t disp_buf;

    uint32_t size_in_px = DISP_BUF_SIZE;

    lv_disp_buf_init(&disp_buf, buf1, NULL, size_in_px);

  1. I had an issue with strange display output and update problems, which (besides other stuff) results from the two screen-sized buffers. It can be easily overlooked (although in the pdf documentation v7.0 on page 24, that with two screen-sized buffers set_px_cb cannot be used.

It would be maybe a good idea to check that there a not two screen-sized buffers used when a set_px function is set.

I’ll make a PR for changing the example in main.c to use the two buffers correctly.


  1. I now have a similar screen with my displays, which worked properly for v6. You can see that this is similar to the text written, “Hello world!” in my screenshot.It seems to be surrounding box?

Ok, I will wait for your modification to the main.c file, I will update the README on the meantime.
Do you think is there a problem if we use a single buffer apprach on monochrome displays?
So we can still use set_px_cb.

I think it’s solved (See https://github.com/lvgl/lv_port_esp32/pull/110#issuecomment-637864156)

So the problem was not related to the LV_NO_TASK_READY value?


  1. single buffer:
    No, it’s not a problem to only use a single buffer. At least for my application, the display update is fast enough.

  2. monochrome display:
    Yet, the monochrome display issue is solved for SSD1306. I created a PR for SH1107.

1 Like

I didn’t knew why lv_task_handler was returning that value, i assumed it was lvgl telling me that it didn’t have anything to do, like flushing the rendered buffer.

Great, thanks, I think the LVGL v7 PR is almost ready to be merged into master. I was setting the lvgl_esp32_driver code to work with both LVGL v6 and v7.

Just saw that you deleted the SH1107 PR, is there any issue?

The problem is if you use double buffering wit 2 screen-sized buffers and one buffer is rendered and flushed, LVGL needs to copy the changed area to the other buffer to keep them synchronized.

However, if set_px_cb is set, LVGL can’t copy the areas because it doesn’t know the size of the pixels and their alignment.

I have no good idea to fix it. We either

  • add a copy_cb but I’d like to avoid adding a new function to the display drivers only for this purpose
  • add a get_px_cb but it has the same problem as copy_cb
  • we can make LVGL to always refresh the whole screen in set_px_cb is set and there are 2 screen-sized buffers. This way it’s not required to synchronize the buffers as always the whole screen si redrawn. However, it badly can affect performance.

Do you have any idea?

@Carlos_Diaz I deleted my branch for the SH1107 PR too fast, just reopened. The PR is doing the same opa check as in ssd1306 code and can be merged.

@kisvegabor For me using only one single full-sized buffer for the pretty small monochrome displays is fine and the display update duration is absolutely sufficient for my needs. I understand your explanation and only have the ideas you already mentioned. So, I’d stick with this limitation.

But I’d suggest to add a check function to log an error message if two full-sized buffers and the set_px_cb are set. For example in lv_disp_drv_register. It would have saved me a couple of hours…