I watched a lot DMA2D All the tutorials use blocking to refresh the screen , This consumes performance It's useless DMA, So I use DMA2D Interrupt to transfer data

Test platform

stm32f429 + Punctual atom 7 inch 1024x600 LCD screen 45MHZ Refresh rate + LVGL

Public conditions :

LTDC Refresh rate 45MHZ, open SDRAM Burst transmission , LVGL 2 Full size buffers

 

1 LVGL Not used DMA2D, Use register DMA2D transmission

LVGL to configure
#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the
disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 0 /*If enabling
LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include
path of CMSIS header of target processor e.g. "stm32f769xx.h" or
"stm32f429xx.h" */ #define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32f429xx.h"
LVGL port to configure
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area,
lv_color_t * color_p) { /*The most simple case (but also the slowest) to put
all pixels to the screen one-by-one*/
//LTDC_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)(color_p));
uint32_t h = area->y2 - area->y1; uint32_t w = area->x2 - area->x1; uint32_t
OffLineSrc = 1024 - (area->x2 - area->x1 +1); uint32_t addr =
LCD_FRAME_BUF_ADDR + 2*(1024*area->y1 + area->x1); // --- Blocking transmission --- // pattern
DMA2D->CR = 0x00000000UL | (1 << 9); // source address DMA2D->FGMAR =
(uint32_t)(uint16_t*)(color_p); // Destination address DMA2D->OMAR = (uint32_t)addr; // Input offset
DMA2D->FGOR = 0; // Output offset DMA2D->OOR = OffLineSrc; /* The foreground layer and the output area are both used RGB565 Color format */
DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565; DMA2D->OPFCCR =
LTDC_PIXEL_FORMAT_RGB565; DMA2D->NLR = (area->y2-area->y1+1) | ((area->x2
-area->x1 +1) << 16); /* Start transmission */ DMA2D->CR |= DMA2D_CR_START; /* wait for DMA2D Transmission complete */
while (DMA2D->CR & DMA2D_CR_START) {} lv_disp_flush_ready(disp_drv); }
run benckmark Probably 11fps

2  LVGL use DMA2D, Use register DMA2D transmission
#define LV_USE_GPU 0 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the
disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 1 /*If enabling
LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include
path of CMSIS header of target processor e.g. "stm32f769xx.h" or
"stm32f429xx.h" */ #define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32f429xx.h"
Add macro definition STM32F4

3  LVGL Not used DMA2D, Use register DMA2D Interrupt transmission

  Because if LVGL open DMA2D after , Will enter into DMA2D interrupt , So we have to judge whether it is LVGL Internal interruption , Or is your drawing interrupted , use volatile uint8_t
g_gpu_state = 0; Let's judge by this
#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the
disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 0 /*If enabling
LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include
path of CMSIS header of target processor e.g. "stm32f769xx.h" or
"stm32f429xx.h" */ #define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32f429xx.h" volatile
uint8_t g_gpu_state = 0; // DMA2D Transfer complete callback static void
mDMA2Dcallvack(DMA2D_HandleTypeDef *hdma2d) { if(g_gpu_state==1){ g_gpu_state =
0; lv_disp_flush_ready(&g_disp_drv); } } // dma2D use HAL initialization static void
dma2d_use_hal_init(void) { hdma2d.Instance = DMA2D; hdma2d.XferCpltCallback =
mDMA2Dcallvack; if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) { } } /* Initialize your
display and the required peripherals. */ static void disp_init(void) {
dma2d_use_reg_init(); } static void disp_flush(lv_disp_drv_t * disp_drv, const
lv_area_t * area, lv_color_t * color_p) { /*The most simple case (but also the
slowest) to put all pixels to the screen one-by-one*/
//LTDC_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)(color_p));
uint32_t h = area->y2 - area->y1; uint32_t w = area->x2 - area->x1; uint32_t
OffLineSrc = 1024 - (area->x2 - area->x1 +1); uint32_t addr =
LCD_FRAME_BUF_ADDR + 2*(1024*area->y1 + area->x1); // -- Interrupt transmission // pattern DMA2D->CR =
0x00000000UL | (1 << 9); // source address DMA2D->FGMAR = (uint32_t)(uint16_t*)(color_p);
// Destination address DMA2D->OMAR = (uint32_t)addr; // Input offset DMA2D->FGOR = 0; // Output offset
DMA2D->OOR = OffLineSrc; /* The foreground layer and the output area are both used RGB565 Color format */ DMA2D->FGPFCCR =
DMA2D_OUTPUT_RGB565; DMA2D->OPFCCR = DMA2D_OUTPUT_RGB565; // How many lines DMA2D->NLR =
(area->y2-area->y1+1) | ((area->x2 -area->x1 +1) << 16); // Turn on interrupt DMA2D->CR |=
DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE; /* Start transmission */ DMA2D->CR |= DMA2D_CR_START;
g_gpu_state = 1; }
4 3  LVGL use DMA2D, Use register DMA2D Interrupt transmission
#define LV_USE_GPU 0 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the
disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 1 /*If enabling
LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include
path of CMSIS header of target processor e.g. "stm32f769xx.h" or
"stm32f429xx.h" */ #define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32f429xx.h" volatile
uint8_t g_gpu_state = 0; // DMA2D Transfer complete callback static void
mDMA2Dcallvack(DMA2D_HandleTypeDef *hdma2d) { if(g_gpu_state==1){ g_gpu_state =
0; lv_disp_flush_ready(&g_disp_drv); } } // dma2D use HAL initialization static void
dma2d_use_hal_init(void) { hdma2d.Instance = DMA2D; hdma2d.XferCpltCallback =
mDMA2Dcallvack; if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) { } } /* Initialize your
display and the required peripherals. */ static void disp_init(void) {
dma2d_use_reg_init(); } static void disp_flush(lv_disp_drv_t * disp_drv, const
lv_area_t * area, lv_color_t * color_p) { /*The most simple case (but also the
slowest) to put all pixels to the screen one-by-one*/
//LTDC_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)(color_p));
uint32_t h = area->y2 - area->y1; uint32_t w = area->x2 - area->x1; uint32_t
OffLineSrc = 1024 - (area->x2 - area->x1 +1); uint32_t addr =
LCD_FRAME_BUF_ADDR + 2*(1024*area->y1 + area->x1); // -- Interrupt transmission // pattern DMA2D->CR =
0x00000000UL | (1 << 9); // source address DMA2D->FGMAR = (uint32_t)(uint16_t*)(color_p);
// Destination address DMA2D->OMAR = (uint32_t)addr; // Input offset DMA2D->FGOR = 0; // Output offset
DMA2D->OOR = OffLineSrc; /* The foreground layer and the output area are both used RGB565 Color format */ DMA2D->FGPFCCR =
DMA2D_OUTPUT_RGB565; DMA2D->OPFCCR = DMA2D_OUTPUT_RGB565; // How many lines DMA2D->NLR =
(area->y2-area->y1+1) | ((area->x2 -area->x1 +1) << 16); // Turn on interrupt DMA2D->CR |=
DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE; /* Start transmission */ DMA2D->CR |= DMA2D_CR_START;
g_gpu_state = 1; }
 

contrast :

1 Not used GPU, Use register DMA2D,11fps

2 use GPU, Use register DMA2D, 23fps

3 Not used GPU, Use register DMA2D Interrupt transmission , 11fps 

4 use GPU, Interrupt transmission , 30fps

In addition, I found that single buffer is much faster than double buffer , this bug It is estimated that it will be optimized in the future

because 1 and 3, fps It's equal because it takes too much time in color conversion , So interrupt and block mode is basically the same

It's said that it's faster to turn on optimization level and compiler level , You can try this

 

In addition, I write by myself DMA2D Interruption and adoption HAL There is no difference in the basic parameters of the callback , Therefore, it is recommended to use it directly HAL Callback of Library
void DMA2D_IRQHandler(void) { if ((DMA2D->ISR & DMA2D_FLAG_TC) != 0U) { if
((DMA2D->CR & DMA2D_IT_TC) != 0U) { DMA2D->CR &= ~DMA2D_IT_TC; DMA2D->IFCR
=DMA2D_FLAG_TC; if(g_gpu_state==1){ g_gpu_state = 0;
lv_disp_flush_ready(&g_disp_drv); } } } }
 

Technology
©2019-2020 Toolsou All rights reserved,
Hikvision - Embedded software written test questions C Language application 0 The length of array in memory and structure is 0 In depth analysis data structure --- The preorder of binary tree , Middle order , Subsequent traversal How to do it ipad Transfer of medium and super large files to computer elementui Shuttle box el-transfer Display list content text too long 2019 The 10th Blue Bridge Cup C/C++ A Summary after the National Games ( Beijing Tourism summary )unity Shooting games , Implementation of first person camera python of numpy Module detailed explanation and application case Study notes 【STM32】 Digital steering gear Horizontal and vertical linkage pan tilt Vue Used in Element Open for the first time el-dialog Solution for not getting element