cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5G7 - LTDC bricks when peripheral clock enabled?

dmarks-ls
Associate III

All,

I have somehow concocted a CubeMX configuration (attached) that causes the CPU to latch up when the LTDC clock is enabled during HAL initialization.  Here's what I'm seeing/doing:

  1. Debugger loads flash, breakpoints at HAL_Init() in main().
  2. Set a breakpoint on the first line of HAL_LTDC_MspInit() inside Core/Src/stm32u5xxx_hal_msp.c.
  3. Run program.  main() calls MX_LTDC_Init(), which calls HAL_LTDC_Init(), which calls HAL_LTDC_MspInit(), stopping at the breakpoint.
  4. Open the Variables view, expand hltdc, then expand hltdc->Instance.  Observe that the LTDC peripheral registers are viewable in the debugger.
  5. Step up to and then over the call to the macro __HAL_RCC_LTDC_CLK_ENABLE().  Observe that the LTDC peripheral register values go blank, and the debugger has lost communication with the MCU.

Here's the "before":

Before the crashBefore the crash

And here's the "after":

After the crashAfter the crash

My question is... why is this happening?  It does this on both the U5G9 DK2 board and our custom board.  I have a valid(?) 32.4 MHz clock going to the LTDC.  It's sourced from PLL2R, which in turn is sourced from HSE (16 MHz).  I created a quickie test project which just initializes the clocks and the UARTs, and I can get correct UART output from our board while running the CPU and peripheral buses on an HSE-derived PLLCLK (PLL1R), which should be proof that our 16 MHz crystal is good.  I see the same behavior if I switch to using HSI (16 MHz) instead of HSE for PLL1 and PLL2.

A peripheral causing an internal fault when being accessed is, in my experience, an indicator of the peripheral not being clocked.  But the peripheral registers are already readable until __HAL_RCC_LTDC_CLK_ENABLE() is called, at which point the CPU and debugger both die.

Now, here's the important bit... if you close the Variables view, such that the debugger is not accessing the LTDC peripheral memory, and you step over __HAL_RCC_LTDC_CLK_ENABLE(), the program continues to function.  I am able to step over (F6) the rest of HAL_LTDC_MspInit() and return to HAL_LTDC_Init().  But once that function starts to access the LTDC registers to configure the peripheral, it dies.  Again, here's the before:

Before program crashBefore program crash

And here's the after, trying to step over line 277:

After program crashAfter program crash

So it still dies even if you don't have the debugger Variables view open; it's the act of trying to read LTDC peripheral registers (after __HAL_RCC_LTDC_CLK_ENABLE() has been called) that kills the processor and debugger.  I used the attached IOC file to generate a new STM32 CubeMX project, and the generated project exhibits this failure, so you should be able to use this IOC file to try to reproduce my failure.  I'm running the latest IDE (v1.18.1, Windows) with the latest CubeMX packages.

Any idea what I'm doing wrong?

Dana M.

1 REPLY 1
dmarks-ls
Associate III

FWIW, I created a new project where I'm going to start with nothing but the bare minimum to allow me to initialize the LTDC without complaints:

  • Enable ICACHE.
  • Enable SMPS under PWR/Low Power.
  • Enable high-speed crystal under RCC (using 16 MHz).
  • Configure PLL1R for 160 MHz (/4, *80, /2), apply to system clocks.
  • Enable LTDC (RGB888 output) with one RGB565 layer.  Timings are (H) 48/40/800/112 (1000 clocks) and (V) 1/31/480/28 (540 clocks), yielding 1000 * 540 * 60 = 32.4 MHz pixel clock.
  • Configure PLL2R for 32.4 MHz (/4, *81, /10), apply to LTDC.

For giggles, I also enabled USART1 on PA9/10 and added code just before the main loop:

  /* Need to #include <string.h> up top. */
  const char *str = "Hi mom.\r\n";
  HAL_UART_Transmit_IT(&huart1, (const uint8_t*) str, strlen(str));

And with this configuration, it works.  Tracing through, I find... wait, what the heck?  Here's the MSP init code from this minimal example I just created:

Clock init code generatedClock init code generated

See all that clock initialization code there with PLL divisors and such?  Here's the MSP init code from the "broken" IOC in my original post:

Clock init code not generatedClock init code not generated

There's no clock initialization code being generated there.  Why?  That's got to be the issue.  What is it about my original IOC file that causes no PLL2R clock initialization code to be generated in HAL_LTDC_MspInit()?

EDIT: If I graft the clock initialization code from the minimal example into my original project (using the user code begin/end block), LTDC initializes correctly, and the system runs.  So... the issue seems to be the omission of the clock init code.  If you can find out why it's doing that using the IOC file in my original post, I think that solves the issue.

Dana M.