Loaders, Auto-fit container not running

Hello everyone,


Currently, I am working on using LittlevGL via MicroPython on a microcontroller. The display module I am using is a customized module. I wrote the display driver for this module both in C and transferring it to MicroPython module.

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

The board I am using is STM32L4R9I Discovery.

What do you experience?

Give a detailed description. “It doesn’t work” is not enough information for us to diagnose the issue.
When I copy example code of Loader or Auto-fit Container (moving objects in general). When using STM32CubeIDE to compile the code and load it into the board. Loader is extremely lagging. Also, the auto fit container did not change in size. When running in Ubuntu (MicroPython), those object did not show any sign of changing. Other static object such as buttons work okay.

What do you expect?

I expect have a loader like this:

Code to reproduce

Use the ```c and ``` tags to format your code:

/*You code here*/
#include "lv_conf.h"
#include "display.h"
#include "lvgl/src/lv_hal/lv_hal.h"
#include "lvgl/lvgl.h"
#include "stm32l4xx_hal.h"
#include "stm32l4xx_hal_ltdc.h"
#include "stm32l4xx_hal_dma2d.h"
#include "stm32l4xx_hal_dsi.h"
#include "stm32l4xx_hal_rcc.h"
#include "stm32l4xx_hal_gfxmmu.h"

#include "stm32l4r9i_discovery.h"
#include "stm32l4r9i_discovery_lcd.h"
#include "stm32l4r9i_discovery_psram.h"

#include "log.h"

//**************STATIC PROTOTYPES**************

/* For LittlevGL */
static void my_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area,
		lv_color_t *color_p);
/* LCD */
/* RAM */
static void CopyBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize);
// ************STATIC VARIABLES***************

extern LTDC_HandleTypeDef hltdc_discovery;

extern DSI_HandleTypeDef hdsi_discovery;
DSI_VidCfgTypeDef hdsivideo_handle;
DSI_PLLInitTypeDef dsiPllInit;

static uint32_t *my_fb = (uint32_t*)LAYER0_ADDRESS;
static DMA2D_HandleTypeDef   hdma2d_discovery;
// ************ GLOBAL FUNCTION *************

// ********* initialize the display ***********

void tft_init(void) {
	log_debug("enter tft\r\n");
	/* Deactivate speculative/cache access to first FMC Bank to save FMC bandwidth */
	FMC_Bank1_R->BTCR[0] = 0x000030D2;

	static lv_disp_buf_t disp_buf;
	static lv_color_t buf1[390 * 10];
//	static lv_color_t buf2[390 * 10];
	lv_disp_buf_init(&disp_buf, buf1, NULL, 390 * 10);

	lv_disp_drv_t disp_drv;                 /*A variable to hold the drivers. Can be local variable*/
	lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
	disp_drv.buffer = &disp_buf;            /*Set an initialized buffer*/
	log_debug("enter flush \r\n");
	disp_drv.flush_cb = my_flush_cb;
	log_debug("finish flush \r\n");
	//lv_disp_t * disp;/*Set a flush callback to draw to the display*/
	lv_disp_drv_register(&disp_drv); /*Regis ter the driver and save the created display objects*/

static void my_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) {
	log_debug("in my_flush,enter CopyBuffer\r\n");
	CopyBuffer((uint32_t*)color_p, my_fb, area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area));
	log_debug("in my_flush,exit CopyBuffer\r\n");
	log_debug("in my_flush,enter FlushReady\r\n");
	log_debug("in my_flush,exit FlushReady\r\n");

  * @brief  Copy an input RGB888 buffer to output RGB888 with output offset
  * @param  pSrc: Pointer to source buffer
  * @param  pDst: Output color
  * @param  x: Start x position
  * @param  y: Start y position
  * @param  xsize: width
  * @param  ysize: height
  * @param  ColorMode: Input color mode
  * @retval None

static void CopyBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
  uint32_t destination = (uint32_t)pDst + (y * 768 + x) * 4;
  uint32_t source      = (uint32_t)pSrc;

  hdma2d_discovery.Instance = DMA2D;

  /*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
  hdma2d_discovery.Init.Mode           = DMA2D_M2M;
  hdma2d_discovery.Init.ColorMode      = DMA2D_OUTPUT_ARGB8888;
  hdma2d_discovery.Init.OutputOffset   = 768 - xsize; //// CHANGE FROM 1024 TO 768 TO FIX THE HORIZONTAL STRIBE
  hdma2d_discovery.Init.AlphaInverted  = DMA2D_REGULAR_ALPHA;  /* No Output Alpha Inversion */
  hdma2d_discovery.Init.RedBlueSwap    = DMA2D_RB_REGULAR;     /* No Output Red & Blue swap */
  hdma2d_discovery.Init.BytesSwap      = DMA2D_BYTES_REGULAR;  /* Regular output byte order */
  hdma2d_discovery.Init.LineOffsetMode = DMA2D_LOM_PIXELS;     /* Pixel mode                */

  /*##-2- Foreground Configuration ###########################################*/
  hdma2d_discovery.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
  hdma2d_discovery.LayerCfg[1].InputOffset    = 0;
  hdma2d_discovery.LayerCfg[1].AlphaMode      = DMA2D_NO_MODIF_ALPHA;
  hdma2d_discovery.LayerCfg[1].InputAlpha     = 0xFF;                /* Not used */
  hdma2d_discovery.LayerCfg[1].RedBlueSwap    = DMA2D_RB_SWAP; //DMA2D_RB_REGULAR;    /* No ForeGround Red/Blue swap */
  hdma2d_discovery.LayerCfg[1].AlphaInverted  = DMA2D_REGULAR_ALPHA; /* No ForeGround Alpha inversion */

  /* DMA2D Initialization */
  if(HAL_DMA2D_Init(&hdma2d_discovery) == HAL_OK)
    if(HAL_DMA2D_ConfigLayer(&hdma2d_discovery, 1) == HAL_OK)
      if (HAL_DMA2D_Start(&hdma2d_discovery, source, destination, xsize, ysize) == HAL_OK)
        /* Polling For DMA transfer */
        HAL_DMA2D_PollForTransfer(&hdma2d_discovery, 10);

Screenshot and/or video

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

What might be the cause of this problem? I read some similar issues as mine and their solution are enable LV_USE_ANIMATION ( set to 1 already) or reviewing flushing functions (I dont know what to fix).

Can you send a video for the preload issue?

Hi @embeddedt,

Here is the loading arc in C language:

And in MicroPython:

In MicroPython, there is only a small bit of the Arc on the screen (I hope you could see that - the camera is not so good). There is no sign of moving.

The issue in C appears to be that your display driver cannot flush the screen fast enough.

I assume MicroPython is using a different driver?

Hi @embeddedt,

the driver in C and MicroPython are the same. I test the driver in C then use the same code in MicroPython. I referred the SDL display module to write my own in MicroPython:

  • The code I posted above, display.c, is corresponding to SDL_monitor.c.
  • Then I wrote another file that is corresponding to modSDL, which basically is calling functions from display.c like init or flush, and registering module to be called in REPL.

That display.c is the same thing when running in C.

How can i improve the speed of screen flushing?

This is platform-specific. It depends on how your display is connected as well as how your function is written.

As an example of an optimization, on many displays, you can set a starting location and then copy a row of pixels, instead of having to set the location for each pixel.

Hi @embeddedt,

I already found how to fix the error. When running on IDE, the reason why the animation is slow because there is a function called Mfx_Event. There is a Delay which make the process slower. Also, We are going to find any delay that makes the loader slow.

In MicroPython, I wrote everything inside main.py and run via boot.py. Those 2 files are in the PYFLASH disk when plugging in the board. As far as I know, the main.py only run one, therefore, objects of lvgl are only initialized and displayed. I need to call the Refresh function again in order to run the loader.

Anyway, thanks for your reply.