Question
STM32F429I-DISCO: flickering with DMA2D
Posted on June 08, 2014 at 22:51
I am working with the STM32F429I-DISCO board and trying to get a flicker-free display.
I am using double buffering to draw into one buffer while displaying the other. When done drawing all elements, I switch buffers. These buffers are in RGB565 and so is LTDC configured. The following function draws an ARGB8888 image with alpha channel onto the current buffer (the one that is not displayed) with blending and color mode conversion:static
void
gfx_draw_img_argb8888 (gfx_image_t* img, gfx_coord_t* coord)
{
DMA2D_InitTypeDef DMA2D_InitStruct;
DMA2D_FG_InitTypeDef DMA2D_FG_InitStruct;
DMA2D_BG_InitTypeDef DMA2D_BG_InitStruct;
uint32_t dest_address;
uint32_t source_address;
uint32_t offset;
uint16_t picture_width;
uint16_t picture_height;
picture_width = img->width;
picture_height = img->height;
// check for dimensions
if
(coord->source_w == 0)
return
;
if
(coord->source_h == 0)
return
;
if
(coord->source_x + coord->source_w > picture_width)
return
;
if
(coord->source_y + coord->source_h > picture_height)
return
;
if
(coord->dest_x + coord->source_w > LCD_MAX_X)
return
;
if
(coord->dest_y + coord->source_h > LCD_MAX_Y)
return
;
// target address in display RAM
dest_address = lcd_frame_buffer + 2 * (LCD_MAX_X * coord->dest_y + coord->dest_x);
// source address in image
offset = 4 * (picture_width * coord->source_y + coord->source_x);
source_address = (uint32_t)&img->pixel_data[offset];
DMA2D_DeInit ();
DMA2D_StructInit (&DMA2D_InitStruct);
DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_BLEND;
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = dest_address;
DMA2D_InitStruct.DMA2D_OutputGreen = 0;
DMA2D_InitStruct.DMA2D_OutputBlue = 0;
DMA2D_InitStruct.DMA2D_OutputRed = 0;
DMA2D_InitStruct.DMA2D_OutputAlpha = 0;
DMA2D_InitStruct.DMA2D_OutputOffset = LCD_MAX_X - coord->source_w;
DMA2D_InitStruct.DMA2D_NumberOfLine = coord->source_h;
DMA2D_InitStruct.DMA2D_PixelPerLine = coord->source_w;
DMA2D_Init (&DMA2D_InitStruct);
DMA2D_FG_StructInit (&DMA2D_FG_InitStruct);
DMA2D_FG_InitStruct.DMA2D_FGMA = source_address;
DMA2D_FG_InitStruct.DMA2D_FGO = picture_width - coord->source_w;
DMA2D_FG_InitStruct.DMA2D_FGCM = CM_ARGB8888;
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = NO_MODIF_ALPHA_VALUE;
DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = 0x00;
DMA2D_FGConfig (&DMA2D_FG_InitStruct);
DMA2D_BG_StructInit (&DMA2D_BG_InitStruct);
DMA2D_BG_InitStruct.DMA2D_BGMA = dest_address;
DMA2D_BG_InitStruct.DMA2D_BGO = LCD_MAX_X - coord->source_w;
DMA2D_BG_InitStruct.DMA2D_BGCM = CM_RGB565;
DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_MODE = NO_MODIF_ALPHA_VALUE;
DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_VALUE = 0x00;
DMA2D_BGConfig (&DMA2D_BG_InitStruct);
DMA2D_StartTransfer ();
while
(DMA2D_GetFlagStatus (DMA2D_FLAG_TC) == RESET);
}
I switch buffers every 30 ms to get a smooth animation and it already looks great. But I noticed flickering every time I call the function. Debugging it shows that DMA2D_StartTransfer() until the end of the function takes about 9 ms. During this time the screen flickers once. It seems that while DMA2D is running the LTDC does not properly refresh the screen. Maybe because memory is locked during transfer? My double buffers and the images are stored in SDRAM.
Any ideas how to avoid the flickering?
#dma2d-flicker-stm32f429-ltdc #ltdc-flicker-dma2d