Skip to main content
Gregory3
Associate III
May 12, 2020
Question

LTDC won't initialize with the STM32H753

  • May 12, 2020
  • 9 replies
  • 4523 views

Hello!

I'm using the Cube IDE with STM32H753 and trying to initialize the LTDC from HAL.

I already did this with success for the STM32F767.

But for the STM32H753 I have some problems with LTDC drivers.

The programm hangs up during debugging on the automatic genarated initialization routine.

The main looks like this:

int main(void)
{
 /* USER CODE BEGIN 1 */
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* USER CODE BEGIN Init */
 
 /* USER CODE END Init */
 
 /* Configure the system clock */
 SystemClock_Config();
 
 /* USER CODE BEGIN SysInit */
 
 /* USER CODE END SysInit */
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_LTDC_Init();

And the problem is the MX_LTDC_Init();

The program goes into it (inside the ltdc.c file):

void MX_LTDC_Init(void)
{
 LTDC_LayerCfgTypeDef pLayerCfg = {0};
 
 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 = 9;
 hltdc.Init.VerticalSync = 1;
 hltdc.Init.AccumulatedHBP = 29;
 hltdc.Init.AccumulatedVBP = 5;
 hltdc.Init.AccumulatedActiveW = 269;
 hltdc.Init.AccumulatedActiveH = 325;
 hltdc.Init.TotalWidth = 279;
 hltdc.Init.TotalHeigh = 329;
 hltdc.Init.Backcolor.Blue = 0;
 hltdc.Init.Backcolor.Green = 0;
 hltdc.Init.Backcolor.Red = 200;
 if (HAL_LTDC_Init(&hltdc) != HAL_OK)
 {
 Error_Handler();
 }
 pLayerCfg.WindowX0 = 0;
 pLayerCfg.WindowX1 = 240;
 pLayerCfg.WindowY0 = 0;
 pLayerCfg.WindowY1 = 320;
 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 = 0;
 pLayerCfg.ImageWidth = 220;
 pLayerCfg.ImageHeight = 320;
 pLayerCfg.Backcolor.Blue = 0;
 pLayerCfg.Backcolor.Green = 0;
 pLayerCfg.Backcolor.Red = 250;
 if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
 {
 Error_Handler();
 }
 
}

And then hangs on the HAL_LTDC_Init line.

Going further into that it looks like the problem is with the line 58:

HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc)
{
 uint32_t tmp, tmp1;
 
 /* Check the LTDC peripheral state */
 if (hltdc == NULL)
 {
 return HAL_ERROR;
 }
 
 /* Check function parameters */
 assert_param(IS_LTDC_ALL_INSTANCE(hltdc->Instance));
 assert_param(IS_LTDC_HSYNC(hltdc->Init.HorizontalSync));
 assert_param(IS_LTDC_VSYNC(hltdc->Init.VerticalSync));
 assert_param(IS_LTDC_AHBP(hltdc->Init.AccumulatedHBP));
 assert_param(IS_LTDC_AVBP(hltdc->Init.AccumulatedVBP));
 assert_param(IS_LTDC_AAH(hltdc->Init.AccumulatedActiveH));
 assert_param(IS_LTDC_AAW(hltdc->Init.AccumulatedActiveW));
 assert_param(IS_LTDC_TOTALH(hltdc->Init.TotalHeigh));
 assert_param(IS_LTDC_TOTALW(hltdc->Init.TotalWidth));
 assert_param(IS_LTDC_HSPOL(hltdc->Init.HSPolarity));
 assert_param(IS_LTDC_VSPOL(hltdc->Init.VSPolarity));
 assert_param(IS_LTDC_DEPOL(hltdc->Init.DEPolarity));
 assert_param(IS_LTDC_PCPOL(hltdc->Init.PCPolarity));
 
#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
 if (hltdc->State == HAL_LTDC_STATE_RESET)
 {
 /* Allocate lock resource and initialize it */
 hltdc->Lock = HAL_UNLOCKED;
 
 /* Reset the LTDC callback to the legacy weak callbacks */
 hltdc->LineEventCallback = HAL_LTDC_LineEventCallback; /* Legacy weak LineEventCallback */
 hltdc->ReloadEventCallback = HAL_LTDC_ReloadEventCallback; /* Legacy weak ReloadEventCallback */
 hltdc->ErrorCallback = HAL_LTDC_ErrorCallback; /* Legacy weak ErrorCallback */
 
 if (hltdc->MspInitCallback == NULL)
 {
 hltdc->MspInitCallback = HAL_LTDC_MspInit;
 }
 /* Init the low level hardware */
 hltdc->MspInitCallback(hltdc);
 }
#else
 if (hltdc->State == HAL_LTDC_STATE_RESET)
 {
 /* Allocate lock resource and initialize it */
 hltdc->Lock = HAL_UNLOCKED;
 /* Init the low level hardware */
 HAL_LTDC_MspInit(hltdc);
 }
#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
 
 /* Change LTDC peripheral state */
 hltdc->State = HAL_LTDC_STATE_BUSY;
 
 /* Configure the HS, VS, DE and PC polarity */
 hltdc->Instance->GCR &= ~(LTDC_GCR_HSPOL | LTDC_GCR_VSPOL | LTDC_GCR_DEPOL | LTDC_GCR_PCPOL);
 hltdc->Instance->GCR |= (uint32_t)(hltdc->Init.HSPolarity | hltdc->Init.VSPolarity | \
 hltdc->Init.DEPolarity | hltdc->Init.PCPolarity);

The debugger says this:

0693W000000XIZZQA4.png

0693W000000XIbBQAW.png

So it looks like the Instance is initialized with zeros. But why?

Like I wrote , the code is automatic generated, so I don't delete anythig or write anything into the Init functions.

How can I deep deeper to see what could be the problem?

The application shall just display a simple one color picture first.

Thank you and regards,

Gregor

This topic has been closed for replies.

9 replies

Tesla DeLorean
Guru
May 12, 2020

>>So it looks like the Instance is initialized with zeros. But why?

Got the right AHB, APB, PLL and peripheral clocks initialized/enabled properly?

Check that the startup code is properly initializing the statics.

Check you don't have different WEAK functions competing to get bound by the linker.

Disassemble code determine what code gets into the final image, and what's getting executed.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Gregory3
Gregory3Author
Associate III
May 12, 2020

Hi!

Thank you for the reply!

So, to get to each point from your answer.

1. My clock initializations seems to be ok. Here is the screen shot:

0693W000000XJmKQAW.png

The source is the 25MHz input clock. The LTDC is getting 8.33 MHz, but this shouldn't be a problem I think.

This constellation works with a blinking LED :)

I also get a warning on the RCC because I'm using the 4wire JTAG as a debugg:

0693W000000XJnDQAW.png

2. I don't know how to check the statics? But I have discovered, that in the mentioned code:

HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc)
{
 uint32_t tmp, tmp1;
 
 /* Check the LTDC peripheral state */
 if (hltdc == NULL)
 {
 return HAL_ERROR;
 }
 
 /* Check function parameters */
 assert_param(IS_LTDC_ALL_INSTANCE(hltdc->Instance));
 assert_param(IS_LTDC_HSYNC(hltdc->Init.HorizontalSync));
 assert_param(IS_LTDC_VSYNC(hltdc->Init.VerticalSync));
 assert_param(IS_LTDC_AHBP(hltdc->Init.AccumulatedHBP));
 assert_param(IS_LTDC_AVBP(hltdc->Init.AccumulatedVBP));
 assert_param(IS_LTDC_AAH(hltdc->Init.AccumulatedActiveH));
 assert_param(IS_LTDC_AAW(hltdc->Init.AccumulatedActiveW));
 assert_param(IS_LTDC_TOTALH(hltdc->Init.TotalHeigh));
 assert_param(IS_LTDC_TOTALW(hltdc->Init.TotalWidth));
 assert_param(IS_LTDC_HSPOL(hltdc->Init.HSPolarity));
 assert_param(IS_LTDC_VSPOL(hltdc->Init.VSPolarity));
 assert_param(IS_LTDC_DEPOL(hltdc->Init.DEPolarity));
 assert_param(IS_LTDC_PCPOL(hltdc->Init.PCPolarity));
 
#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
 if (hltdc->State == HAL_LTDC_STATE_RESET)
 {
 /* Allocate lock resource and initialize it */
 hltdc->Lock = HAL_UNLOCKED;
 
 /* Reset the LTDC callback to the legacy weak callbacks */
 hltdc->LineEventCallback = HAL_LTDC_LineEventCallback; /* Legacy weak LineEventCallback */
 hltdc->ReloadEventCallback = HAL_LTDC_ReloadEventCallback; /* Legacy weak ReloadEventCallback */
 hltdc->ErrorCallback = HAL_LTDC_ErrorCallback; /* Legacy weak ErrorCallback */
 
 if (hltdc->MspInitCallback == NULL)
 {
 hltdc->MspInitCallback = HAL_LTDC_MspInit;
 }
 /* Init the low level hardware */
 hltdc->MspInitCallback(hltdc);
 }
#else
 if (hltdc->State == HAL_LTDC_STATE_RESET)
 {
 /* Allocate lock resource and initialize it */
 hltdc->Lock = HAL_UNLOCKED;
 /* Init the low level hardware */
 HAL_LTDC_MspInit(hltdc);
 }
#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
 
 /* Change LTDC peripheral state */
 hltdc->State = HAL_LTDC_STATE_BUSY;
 
 /* Configure the HS, VS, DE and PC polarity */
 hltdc->Instance->GCR &= ~(LTDC_GCR_HSPOL | LTDC_GCR_VSPOL | LTDC_GCR_DEPOL | LTDC_GCR_PCPOL);
 hltdc->Instance->GCR |= (uint32_t)(hltdc->Init.HSPolarity | hltdc->Init.VSPolarity | \
 hltdc->Init.DEPolarity | hltdc->Init.PCPolarity);

The line 42 is responsible for resetting the initialized values:

/* Init the low level hardware */

hltdc->MspInitCallback(hltdc);

If I debugg one line before that, then I get the following (correct for my display) values:

0693W000000XJp9QAG.png

So I think that the initialization is ok, right?

But when the code gets into the mentioned line 42, then something happens... -> see point 3.

3. Inside of the driver "stm32h7xx_hal_ltdc.c" there is a weak declaration of the mentioned function in the line 42:

__weak void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc)
{
 /* Prevent unused argument(s) compilation warning */
 UNUSED(hltdc);
 
 /* NOTE : This function should not be modified, when the callback is needed,
 the HAL_LTDC_MspDeInit could be implemented in the user file
 */
}

It seems that this function is called (by the satndard in the driver) and resets all the values !

Actually it shall be the function in the (also automatic genarted ltdc.c file, which shall initialize the low level hardware:

void HAL_LTDC_MspInit(LTDC_HandleTypeDef* ltdcHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(ltdcHandle->Instance==LTDC)
 {
 /* USER CODE BEGIN LTDC_MspInit 0 */
 
 /* USER CODE END LTDC_MspInit 0 */
 /* LTDC clock enable */
 __HAL_RCC_LTDC_CLK_ENABLE();
 
 __HAL_RCC_GPIOK_CLK_ENABLE();
 __HAL_RCC_GPIOJ_CLK_ENABLE();
 __HAL_RCC_GPIOI_CLK_ENABLE();
 /**LTDC GPIO Configuration 
 PK5 ------> LTDC_B6
 PK4 ------> LTDC_B5
 PJ15 ------> LTDC_B3
 PK6 ------> LTDC_B7
 PK3 ------> LTDC_B4
 PK7 ------> LTDC_DE
 PJ14 ------> LTDC_B2
 PI12 ------> LTDC_HSYNC
 PI13 ------> LTDC_VSYNC
 PI14 ------> LTDC_CLK
 PK2 ------> LTDC_G7
 PK0 ------> LTDC_G5
 PK1 ------> LTDC_G6
 PJ11 ------> LTDC_G4
 PJ10 ------> LTDC_G3
 PJ9 ------> LTDC_G2
 PJ6 ------> LTDC_R7
 PJ1 ------> LTDC_R2
 PJ5 ------> LTDC_R6
 PJ2 ------> LTDC_R3
 PJ3 ------> LTDC_R4
 PJ4 ------> LTDC_R5 
 */
 GPIO_InitStruct.Pin = TFT_B6_Pin|TFT_B5_Pin|TFT_B7_Pin|TFT_B4_Pin 
 |TFT_EN_Pin|TFT_G7_Pin|TFT_G5_Pin|TFT_G6_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
 HAL_GPIO_Init(GPIOK, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = TFT_B3_Pin|TFT_B2_Pin|TFT_G4_Pin|TFT_G3_Pin 
 |TFT_G2_Pin|TFT_R7_Pin|TFT_R2_Pin|TFT_R6_Pin 
 |TFT_R3_Pin|TFT_R4_Pin|TFT_R5_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
 HAL_GPIO_Init(GPIOJ, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = TFT_HSYNC_Pin|TFT_VSYNC_Pin|TFT_CLK_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
 HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
 
 /* LTDC interrupt Init */
 HAL_NVIC_SetPriority(LTDC_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(LTDC_IRQn);
 HAL_NVIC_SetPriority(LTDC_ER_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(LTDC_ER_IRQn);
 /* USER CODE BEGIN LTDC_MspInit 1 */
 
 /* USER CODE END LTDC_MspInit 1 */
 }
}

So now I'm confused. Did I did something wrong with the driver? I haven't change a signle line of it...

4. I don't really know how, but could this be also the reason for the point 3?

Regards,

Gregor

Tesla DeLorean
Guru
May 12, 2020

Look at the hardware itself, not the CubeMX views, the code running on the device ultimately dictates what happens.

The statics are copied by code in, or called from, startup_stm32h7xx.s

Got an adequate stack size for local/auto variables in use?

And empty subroutine is not clearing your structure.

Walk the code that's being executed. Check if there is some memcpy(), memset(), or subroutine prologue code damaging the instance/structure.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Gregory3
Gregory3Author
Associate III
May 16, 2020

Is there anything special about the STM32H753 that I need to consider?

Why the same board with the STM32F767 works perfectly (user code is 100% identical)?

Thank you for any hints...

Stathis
Associate
July 9, 2020

Hi Gregory,

Did you find the solution on this ?

I have exactly the same problem.

Thanks in advance

Stathis

Gregory3
Gregory3Author
Associate III
July 9, 2020

Hi!

No nobody could help me with this one...

STM also donsen't seems to bother about this.

Regards,

Gregor

Stathis
Associate
July 10, 2020

Thanks for your fast reply.

I will try to solve it.

berendi
Principal
July 10, 2020

I ran into this issue too, and ended up rewriting SystemClock_Config() and LTDC initialization without HAL, setting the RCC and LTDC registers according to the reference manual.

CubeMX generated code locked the MCU up at the first time, provided unstable clocks at the second time.

Stathis
Associate
July 10, 2020

I will be obligated if you could share your initialization code of RCC and LTDC.

Thanks in advance

Stathis

GTini.1
Visitor II
August 10, 2020

Hi all, I have the same problem with STM32H743BI in my embedded board.

I replaced the old STM32F429 with this high performance MCU but the MX_LTDC_Init() crashes when it try to write the ltdc registers.

I found a note in the errata manual. There is a bug in some hardware revision (I have the “V�? rev).

The device stalls if you write the LTDC registers before the activation of the pixel clock, but the HAL drivers seems enable the pll3_r_ck before write the registers.

Anyway four or six eyes are better then 2...

Please let me know if someone find a solution, I am in a stall condition, thanks

Gianluca

GTini.1
Visitor II
August 19, 2020

I solved this issue in my embedded board.

The problem, in my case, seems to be caused by a CubeMX bug.

The VCO Range of the PLL3 (the one used to generate the pixel clock of the LTDC module) cannot be selected in MEDIUM mode but only WIDE.

If one of the PLL outputs (P, Q, R) have a frequency higher than 192MHz there are no problems, otherwise the microcontroller will stall during the initialisation phase of the LTDC module because the pixel clock is not active.

It is possible to solve the problem in two ways, the first one is to set one of the three outputs, if not used (P, Q or R) with a clock at 200MHz for example, the other solution is to manually modify the PeriphClkInitStruct.PLL3 parameter. PLL3VCOSEL from RCC_PLL3VCOWIDE to RCC_PLL3VCOMEDIUM.

In this case, however, every time a change is made to the project on CubeMX, the parameter returns to the wrong value.

Gianluca