cancel
Showing results for 
Search instead for 
Did you mean: 

Double FrameBuffer issue with STM32F469I-DISCO

TDele.1
Associate III

Hello,

In order to do some complex animation like screen slide transition, I would like to add a second framebuffer to my touchGFX project on the STM32F469I-DISCO board (800x480 screen). According to the documentation given by ST, I've got 16 MB of external SDRAM to work with which should be more than enough. I've tried the following configurations with CUBEMX:

Framebuffer Strategy: Double Buffer

Buffer Location: By Address

Start Address: 0xC0000000

Start Address 2: 0xC00BB800

AND

Framebuffer Strategy: Double Buffer

Buffer Location: By Allocation

However, when I launch the project on the dev board, the screen always freezes and a lot of colored points appeared. How can I fix this issue ?

Thanks in advance,

Tristan

1 ACCEPTED SOLUTION

Accepted Solutions
Romain DIELEMAN
ST Employee

Hi,

For slide transitions you need to enable the "animation storage" in the setFrameBufferStartAddresses() function within TouchGFXGeneratedHAL.cpp in the TouchGFX/target/generated folder of your project. Since this file will be overwritten when you generate code from STM32CubeMX you will need to overwrite this function in TouchGFXHAL.cpp in TouchGFX/target folder in the TouchGFXHAL::initialize() function as below. I set it to 0xC017 7000 since you should not write over the double buffer (I cant remember however if the double buffer is 100% necessary and if you could do this instead: setFrameBufferStartAddresses((void*)0xC0000000, (void*)0, (void*)0xC00BB800); )

void TouchGFXHAL::initialize()
{
    GPIO::init();
 
    // Calling parent implementation of initialize().
    //
    // To overwrite the generated implementation, omit call to parent function
    // and implemented needed functionality here.
    // Please note, HAL::initialize() must be called to initialize the framework.
 
    TouchGFXGeneratedHAL::initialize();
    setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC00BB800, (void*)0xC0177000);
 
    lockDMAToFrontPorch(false);
 
    mcuInstr.init();
    setMCUInstrumentation(&mcuInstr);
    enableMCULoadCalculation(true);
 
    setButtonController(&btnctrl);
}

/Romain

View solution in original post

5 REPLIES 5
awiernie
Senior II

I use a STM32F479, also with double framebuffer.

One issue was that the display ram and the framebuffer is placed at address 0xC0000000 but moving objects into the SDRAM would store it also in this area. Therefore I stored there dummy data as large as the framebuffers and some more.

My code looks like this:

void TouchGFXGeneratedHAL::initialize()

{

  HAL::initialize();

  registerEventListener(*(Application::getInstance()));

  setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC00BB800, (void*)0);

}

static void MX_LTDC_Init(void)

{

 /* USER CODE BEGIN LTDC_Init 0 */

 /* USER CODE END LTDC_Init 0 */

 LTDC_LayerCfgTypeDef pLayerCfg = {0};

 LTDC_LayerCfgTypeDef pLayerCfg1 = {0};

 /* USER CODE BEGIN LTDC_Init 1 */

 /* USER CODE END LTDC_Init 1 */

 hltdc.Instance = LTDC;

 hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;

 hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AH;

 hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;

 hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

 hltdc.Init.HorizontalSync = 48;

 hltdc.Init.VerticalSync = 3;

 hltdc.Init.AccumulatedHBP = 88;

 hltdc.Init.AccumulatedVBP = 32;

 hltdc.Init.AccumulatedActiveW = 888;

 hltdc.Init.AccumulatedActiveH = 512;

 hltdc.Init.TotalWidth = 928;

 hltdc.Init.TotalHeigh = 525;

 hltdc.Init.Backcolor.Blue = 0;

 hltdc.Init.Backcolor.Green = 0;

 hltdc.Init.Backcolor.Red = 0;

 if (HAL_LTDC_Init(&hltdc) != HAL_OK)

 {

  Error_Handler();

 }

 pLayerCfg.WindowX0 = 0;

 pLayerCfg.WindowX1 = 800;

 pLayerCfg.WindowY0 = 0;

 pLayerCfg.WindowY1 = 480;

 pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;

 pLayerCfg.Alpha = 255;

 pLayerCfg.Alpha0 = 0;

 pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;

 pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;

 pLayerCfg.FBStartAdress = 0xC0000000;

 pLayerCfg.ImageWidth = 800;

 pLayerCfg.ImageHeight = 480;

 pLayerCfg.Backcolor.Blue = 0;

 pLayerCfg.Backcolor.Green = 0;

 pLayerCfg.Backcolor.Red = 0;

 if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)

 {

  Error_Handler();

 }

 pLayerCfg1.WindowX0 = 0;

 pLayerCfg1.WindowX1 = 0;

 pLayerCfg1.WindowY0 = 0;

 pLayerCfg1.WindowY1 = 0;

 pLayerCfg1.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;

 pLayerCfg1.Alpha = 0;

 pLayerCfg1.Alpha0 = 0;

 pLayerCfg1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;

 pLayerCfg1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;

 pLayerCfg1.FBStartAdress = 0;

 pLayerCfg1.ImageWidth = 0;

 pLayerCfg1.ImageHeight = 0;

 pLayerCfg1.Backcolor.Blue = 0;

 pLayerCfg1.Backcolor.Green = 0;

 pLayerCfg1.Backcolor.Red = 0;

 if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg1, 1) != HAL_OK)

 {

  Error_Handler();

 }

 /* USER CODE BEGIN LTDC_Init 2 */

 /* USER CODE END LTDC_Init 2 */

}

TDele.1
Associate III

Thank you for your reply.

My configuration directly produced by TouchGFX designer was the following:

void TouchGFXGeneratedHAL::initialize()

{

  HAL::initialize();

  registerEventListener(*(Application::getInstance()));

  setFrameBufferStartAddresses((void*)0xC0000000, (void*)0, (void*)0);

}

static void MX_LTDC_Init(void)

{

 /* USER CODE BEGIN LTDC_Init 0 */

 /* USER CODE END LTDC_Init 0 */

 LTDC_LayerCfgTypeDef pLayerCfg = {0};

 LTDC_LayerCfgTypeDef pLayerCfg1 = {0};

 /* USER CODE BEGIN LTDC_Init 1 */

 /* USER CODE END LTDC_Init 1 */

hltdc.Instance = LTDC;

 hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;

 hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;

 hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;

 hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

 hltdc.Init.HorizontalSync = 1;

 hltdc.Init.VerticalSync = 1;

 hltdc.Init.AccumulatedHBP = 2;

 hltdc.Init.AccumulatedVBP = 2;

 hltdc.Init.AccumulatedActiveW = 202;

 hltdc.Init.AccumulatedActiveH = 482;

 hltdc.Init.TotalWidth = 203;

 hltdc.Init.TotalHeigh = 483;

 hltdc.Init.Backcolor.Blue = 0;

 hltdc.Init.Backcolor.Green = 0;

 hltdc.Init.Backcolor.Red = 0;

 if (HAL_LTDC_Init(&hltdc) != HAL_OK)

 {

  Error_Handler();

 }

 pLayerCfg.WindowX0 = 0;

 pLayerCfg.WindowX1 = 200;

 pLayerCfg.WindowY0 = 0;

 pLayerCfg.WindowY1 = 480;

 pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;

 pLayerCfg.Alpha = 255;

 pLayerCfg.Alpha0 = 0;

 pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;

 pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;

 pLayerCfg.FBStartAdress = 0xC0000000;

 pLayerCfg.ImageWidth = 200;

 pLayerCfg.ImageHeight = 480;

 pLayerCfg.Backcolor.Blue = 0;

 pLayerCfg.Backcolor.Green = 0;

 pLayerCfg.Backcolor.Red = 0;

 if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)

 {

  Error_Handler();

 }

 pLayerCfg1.WindowX0 = 0;

 pLayerCfg1.WindowX1 = 0;

 pLayerCfg1.WindowY0 = 0;

 pLayerCfg1.WindowY1 = 0;

 pLayerCfg1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;

 pLayerCfg1.Alpha = 0;

 pLayerCfg1.Alpha0 = 0;

 pLayerCfg1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;

 pLayerCfg1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;

 pLayerCfg1.FBStartAdress = 0;

 pLayerCfg1.ImageWidth = 0;

 pLayerCfg1.ImageHeight = 0;

 pLayerCfg1.Backcolor.Blue = 0;

 pLayerCfg1.Backcolor.Green = 0;

 pLayerCfg1.Backcolor.Red = 0;

 if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg1, 1) != HAL_OK)

 {

  Error_Handler();

 }

I'v tried putting the same configuration you used into CUBEMX and the screen is still made up of random colors. I also do not know how you manage to store dummy data into the framebuffer location within the RAM but doing this might solve my issue.

Tristan

Romain DIELEMAN
ST Employee

Hi,

For slide transitions you need to enable the "animation storage" in the setFrameBufferStartAddresses() function within TouchGFXGeneratedHAL.cpp in the TouchGFX/target/generated folder of your project. Since this file will be overwritten when you generate code from STM32CubeMX you will need to overwrite this function in TouchGFXHAL.cpp in TouchGFX/target folder in the TouchGFXHAL::initialize() function as below. I set it to 0xC017 7000 since you should not write over the double buffer (I cant remember however if the double buffer is 100% necessary and if you could do this instead: setFrameBufferStartAddresses((void*)0xC0000000, (void*)0, (void*)0xC00BB800); )

void TouchGFXHAL::initialize()
{
    GPIO::init();
 
    // Calling parent implementation of initialize().
    //
    // To overwrite the generated implementation, omit call to parent function
    // and implemented needed functionality here.
    // Please note, HAL::initialize() must be called to initialize the framework.
 
    TouchGFXGeneratedHAL::initialize();
    setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC00BB800, (void*)0xC0177000);
 
    lockDMAToFrontPorch(false);
 
    mcuInstr.init();
    setMCUInstrumentation(&mcuInstr);
    enableMCULoadCalculation(true);
 
    setButtonController(&btnctrl);
}

/Romain

TDele.1
Associate III

Thank you for your awnser.

I've tried both your solutions and the first one (with the double buffer) still produces a wierd looking screen although the transitions are now working.

On the other hand, the second solution (without the double buffer) makes the screen look right and the transition are also working. That solution is more than enough for my application.

Tristan

perfect 👍