How to Debug "block already marked as free"

Description

I have an infrequent freeze in LVGL - asserting on updating a text label with “block already marked as free”.
The triggering code appears to be in my status bar update code (the status bar updates every 100ms, and I see this assert once a week maybe.) Looking for help on debugging this somehow.

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

NXP RT1052 with FreeRTOS

What LVGL version are you using?

V8.3.3

What do you want to achieve?

Debug this assert that happens very rarely, so hard to reproduce:

tlsf_assert(!block_is_free(block) && "block already marked as free");

What have you tried so far?

Ensured using MUTEX around lv_tick and lv_task handlers (separately) as that is the only hint I’ve seen about this assert thus far.

Code


void lv_ticker( void *pvParameters ) {
  TickType_t ticks = 10 / portTICK_PERIOD_MS;
  UI_SemaphoreInit();
  lv_interface_init();
  vTaskDelay(ticks);

  if (xTaskCreate(lv_redraw, "LV Redraw Task", 1024, NULL, 3, &lv_redraw_handle) != pdPASS){
    assert(0);
  }

  for( ;; ){
    vTaskDelay(ticks);
    UI_TakeMutex();
    lv_tick_inc(millisec); /*Tell LittelvGL that 10 milliseconds were elapsed*/
    UI_GiveMutex();
  }
}


void lv_redraw( void *pvParameters ) {
  //It will redraw the screen if required, handle input devices etc
  uint32_t millisec = 50;
  static uint8_t _100ms = 0;
  TickType_t ticks = millisec / portTICK_PERIOD_MS;

  for( ;; ){
    vTaskDelay(ticks);
    UI_TakeMutex();
    lv_task_handler();
    if (_100ms++ >= 5){
      _100ms = 0;
      status_refresh();
    }
    UI_GiveMutex();
  }
}

The assert is being triggered from the status_refresh above, which goes to call the below (as noted, this is called millions of times without a problem, and then eventually somehow it asserts:

    lv_label_set_text(screen->status_bar.bluetooth_label.obj, "");

Screen Shot 2023-10-13 at 11.01.47 AM

1 Like

I don’t have a solution but have the exact same issue. I am also locking updates with a mutex. What happens in your code if UI_TakeMutex() fails? Mine is in an if statement that skips the remaining steps if that fails.

// use mutex to insure nothing writes to LVGL during the render
#define lvglMutex(x)                                                    \
    do                                                                  \
    {                                                                   \
        if (xSemaphoreTake(xLVGLMutexHandle, (TickType_t)10) == pdTRUE) \
        {                                                               \
            {x};                                                        \
            xSemaphoreGive(xLVGLMutexHandle);                           \
        }                                                               \
    } while (0);

usage:

        lvglMutex(
            lv_timer_handler(); );