LVGL with GPU known as DMA2d


I want to use DMA2D for LCD flushing

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

Custom board with stm32f429IGT6

What LVGL version are you using?


What do you want to achieve?

As mentioned in the title use DMA2D for LCD flushing. In other words, I want to use DMA2D to copy a 2d buffer into another buffer.

What have you tried so far?

The nested for{for{}} is able to flush the LCD well, but the two other commented functions are not doing well. In other words, I don’t know what is the right way of using them. The LCD_FB is a pointer to the LCD start point in ram.

static void tft_lcd_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p) 
	for(int y = area->y1; y <= area->y2; y++)
    	for(int x = area->x1; x <= area->x2; x++)
			LCD_FB[x+(y * LV_HOR_RES_MAX)]=(color_p++->full);  //pixelColor;
//	HAL_DMA2D_Start(&hdma2d, &color_p[0], &LCD_FB[0], 800, 480);
//	lv_gpu_stm32_dma2d_fill(LCD_FB, 800*480, color_p, 800, 480);

Here’s the gist of my implementation. It relies on LVGL’s built-in DMA2D support being enabled.

#define SCREEN_W 480
static void disp_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p) {
    uint16_t *fbp16 = <framebuffer address>;
    lv_coord_t area_w = lv_area_get_width(area);
    lv_gpu_stm32_dma2d_copy(&fbp16[(area->y1 * SCREEN_W) + area->x1], SCREEN_W, color_p, area_w, area_w, lv_area_get_height(area));

Dear @embeddedt
You cleared my mistake,
I thought that that the fill function transmits the source array to the destination, but it seems the transmission should be done through another which is the copy function.

Thank you for correcting me. I will inform the result.

Dear @embeddedt
Now the DMA2D works and I see the GUI. But it is not really satisfying.

First I see no difference between using “nested for” or DMA2D while I have some sort of animations. I checked the widget demo and the animation’s speed was not good on my board. The maximum speed I have on my chip is 168 MHz. So far I hadn’t used the RTOS for this case and a while loop as follows
does the job.

  while (1)

Second I don’t understand why should the first parameter of lv_gpu_stm32_dma2d_copy point to the end of the buffer instead of the beginning of the buffer. (correct me if I am wrong)

What is the size of the LVGL working buffer (not framebuffer)?

If it’s flushing the entire screen at once, area->x1 and area->y1 are 0, and it points to the start of the buffer. Otherwise, it points to the starting position for partial refreshes.

@embeddedt What is the LVGL working buffer?

It’s called a draw_buf as of v8, but it’s the one you register with lv_disp_buf_init (I forget the exact name of it in v7).