Skip to content

Solving a weird freeze up with LVGL v9 in Arduino_H7_Video using Giga Display Shield #1119

Description

@littlejohn657

I was adding some navigation features to a series that I had designed with LVGL 9 using Arduino_H7_Video (which has its own code for the display buffers that I tried to code into my code because I didn't know better and caused issues when I did this, but that's a different discussion). I was consistently getting a really strange freeze (solid red LED, so not an Mbed OS crash) that I could not trace to any particular issue in my code, so I asked ChatGPT for help. For reference, I'm working with an Arduino Giga Display on this project.

With ChatGPT, "we" were able to trace the issue to Arduino_H7_Video.cpp. It turns out that the issue was a repeated realloc() for the rotated buffer in that file, overwriting the allocated memory. ChatGPT suggested a patch to require Arduino_H7_Video.cpp to reuse the same buffer and resize it if there is a need for a larger buffer. This solved my issue, so I thought that I would share it in case anyone else is having the same issues.

In Arduino_H7_Video.cpp, (found at C:\Users**(your user profile)**\AppData\Local\Arduino15\packages\arduino\hardware\mbed_giga\4.6.0\libraries\Arduino_H7_Video\src), near the bottom, there is a section that goes:

#if __has_include("lvgl.h")
#if (LVGL_VERSION_MAJOR == 9)
static uint8_t* rotated_buf = nullptr;
void lvgl_displayFlushing(lv_display_t * disp, const lv_area_t * area, unsigned char * px_map) {
    uint32_t w     = lv_area_get_width(area);
    uint32_t h     = lv_area_get_height(area);
    lv_area_t* area_in_use = (lv_area_t *)area;

    // TODO: find a smart way to tackle sw rotation
    lv_display_rotation_t rotation = lv_display_get_rotation(disp);
    lv_area_t rotated_area;
    if (rotation != LV_DISPLAY_ROTATION_0) {
        rotated_buf = (uint8_t*)realloc(rotated_buf, w * h * 4);
        lv_color_format_t cf = lv_display_get_color_format(disp);
        #if (LVGL_VERSION_MINOR < 2) 
        rotation = LV_DISPLAY_ROTATION_90; // bugfix: force 90 degree rotation for lvgl 9.1 end earlier
        #endif
        lv_draw_sw_rotate(px_map, rotated_buf,
                          w, h, lv_draw_buf_width_to_stride(w, cf),
                          lv_draw_buf_width_to_stride(h, cf),
                          rotation, cf);

        rotated_area.x1 = lv_display_get_vertical_resolution(disp) - area->y2 - 1;
        rotated_area.y1 = area->x1;
        //rotated_area.y2 = dsi_getDisplayYSize() - area->x1 - 1;
        rotated_area.x2 = rotated_area.x1 + h - 1;
        rotated_area.y2 = rotated_area.y1 + w + 1;

        area_in_use = &rotated_area;
        px_map = rotated_buf;
        auto temp = w;
        w = h;
        h = temp;
    }

    uint32_t offsetPos  = (area_in_use->x1 + (dsi_getDisplayXSize() * area_in_use->y1)) * sizeof(uint16_t);

    dsi_lcdDrawImage((void *) px_map, (void *)(dsi_getActiveFrameBuffer() + offsetPos), w, h, DMA2D_INPUT_RGB565);
    lv_display_flush_ready(disp);         /* Indicate you are ready with the flushing*/
}
#else
void lvgl_displayFlushing(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p) {
    uint32_t width      = lv_area_get_width(area);
    uint32_t height     = lv_area_get_height(area);
    uint32_t offsetPos  = (area->x1 + (dsi_getDisplayXSize() * area->y1)) * sizeof(uint16_t);

    dsi_lcdDrawImage((void *) color_p, (void *)(dsi_getActiveFrameBuffer() + offsetPos), width, height, DMA2D_INPUT_RGB565);
    lv_disp_flush_ready(disp);         /* Indicate you are ready with the flushing*/
}

The problem seems to come from rotated_buf = (uint8_t*)realloc(rotated_buf, w * h * 4);

I replaced that section with this:

#if __has_include("lvgl.h")
#if (LVGL_VERSION_MAJOR == 9)

static uint8_t* rotated_buf = nullptr;
static size_t rotated_buf_size = 0;

void lvgl_displayFlushing(
  lv_display_t * disp,
  const lv_area_t * area,
  unsigned char * px_map)
{
  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);

  lv_area_t* area_in_use = (lv_area_t *)area;

  // TODO: find a smart way to tackle sw rotation
  lv_display_rotation_t rotation =
    lv_display_get_rotation(disp);

  lv_area_t rotated_area;

  if (rotation != LV_DISPLAY_ROTATION_0) {

    size_t requiredSize =
      (size_t)w * (size_t)h * 4;

    if (requiredSize > rotated_buf_size) {

        uint8_t *newBuf =
          (uint8_t *)realloc(
            rotated_buf,
            requiredSize);

        if (newBuf == nullptr) {
          lv_display_flush_ready(disp);
          return;
        }

      rotated_buf = newBuf;
      rotated_buf_size = requiredSize;
    }

    lv_color_format_t cf =
      lv_display_get_color_format(disp);

#if (LVGL_VERSION_MINOR < 2)
    rotation = LV_DISPLAY_ROTATION_90;
#endif

    lv_draw_sw_rotate(
      px_map,
      rotated_buf,
      w,
      h,
      lv_draw_buf_width_to_stride(w, cf),
      lv_draw_buf_width_to_stride(h, cf),
      rotation,
      cf);

    rotated_area.x1 =
      lv_display_get_vertical_resolution(disp)
      - area->y2 - 1;

    rotated_area.y1 = area->x1;

    rotated_area.x2 =
      rotated_area.x1 + h - 1;

    rotated_area.y2 =
      rotated_area.y1 + w + 1;

    area_in_use = &rotated_area;
    px_map = rotated_buf;

    auto temp = w;
    w = h;
    h = temp;
  }

  uint32_t offsetPos =
    (area_in_use->x1 +
      (dsi_getDisplayXSize() *
      area_in_use->y1))
    * sizeof(uint16_t);

  dsi_lcdDrawImage(
    (void *)px_map,
    (void *)(dsi_getActiveFrameBuffer()
              + offsetPos),
    w,
    h,
    DMA2D_INPUT_RGB565);

  lv_display_flush_ready(disp);
}

The major change is adding static size_t rotated_buf_size = 0; and replacing rotated_buf = (uint8_t*)realloc(rotated_buf, w * h * 4); with this:

    size_t requiredSize =
      (size_t)w * (size_t)h * 4;

    if (requiredSize > rotated_buf_size) {

        uint8_t *newBuf =
          (uint8_t *)realloc(
            rotated_buf,
            requiredSize);

        if (newBuf == nullptr) {
          lv_display_flush_ready(disp);
          return;
        }

      rotated_buf = newBuf;
      rotated_buf_size = requiredSize;
    }

I will caution everyone about potentially using this patch, as there is code in there that I don't understand, but it solve the issues that I was having. I've attached the patched file in case anyone wants to use it (again, use it at your own risk).

Arduino_H7_Video.cpp

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions