AnsweredAssumed Answered

STM32F429I-DISCO: flickering with DMA2D

Question asked by floppes on Jun 8, 2014
Latest reply on Aug 16, 2016 by Rygel.Troy1818
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?

Outcomes