Skip to main content
PMath.4
Senior III
May 21, 2020
Question

STM32H743: strange interactions LTDC, USB, SDRAM, optimisation

  • May 21, 2020
  • 19 replies
  • 3014 views

I've programmed a "retro" computer using the H743.

https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=12105

Development environment is CubeIDE.

The code supports a USB keyboard and VGA output using the LTDC and a RGB565 R2R DAC. It can play MP3 and FLAC audio over the on-chip DACs and runs a Basic interpreter. Until recently I have always compiled with O2 set.

I have had a longstanding issue with very minor instability of the LTDC clocking which could cause flicker and in extreme cases temporary loss of synch in the monitor. This was almost completely solved by using a crystal oscillator rather than a crystal to clock the processor. Loss of sync was most pronounced when using ARGB4444 in 800x600 resolution with the framebuffer in SDRAM and a 60Hz frame rate, running a FPU intensive Basic program, and whilst decoding mp3 and outputting using 44100 timer interrupts per second (yes I know I should be using DMA).

I've also been having issues with cache coherency in some code when pointers to pointers were used to update SDRAM. Whilst playing with solutions to the latter problem I switched to optimisation "Ofast". This didn't affect my caching issue but the loss of synch disappeared. Unfortunately the interpreted Basic programs ran about 5% slower with the "fast" optimisation. I can live with that so I decided to stick with Ofast.

However, a side affect was that enumeration of the USB keyboard became much less robust. Enumeration on power up stopped working and enumeration on insertion only worked occasionally. Once enumerated the keyboard worked correctly.

I then started playing with optimisation changes at a source code level and found that by compiling stm32h7xx_ll_usb.c with "O2" USB functionality returned to normal.

All this takes a huge amount of time and I'm certainly not going to wade through a disassembler listing to understand the differences. however, my learnings are as follows:

SDRAM and/or LTDC works better when compilation is with Ofast

USB must have stm32h7xx_ll_usb.c compiled with "O2"

A crystal oscillator provides a better clock source than a crystal

This topic has been closed for replies.

19 replies

berendi
Principal
May 21, 2020

I've experienced some clock instability issues using the SystemClock_Config() function generated by CubeMX. Replacing the function with my own, based on the detailed documentation in the RCC chapter of the reference manual solved that. You can use my answer here as a stating point.

Code behaviour changing at different optimization levels is a sure sign of race conditions and/or missing volatile qualifiers, maybe other memory corruption issues. Even if you did everything right in the code you've written, you should not assume that any library function does it right, unless the documentation explicitly states that it is thread-safe.

Start with reviewing every single variable which is ever touched by interrupt handlers, DMA, or multi-threaded code. If there is any HAL code involved, start with fixing that, or rewrite all interrupt and DMA handling code without using HAL.

Cache coherency is usually an issue only when DMA is involved.

44 kHz timer interrupts on a 480 MHz system should be no problem, unless you are using the HAL interrupt handling mechanism.

waclawek.jan
Super User
May 21, 2020

> I've experienced some clock instability issues using the SystemClock_Config() function generated by CubeMX.

Surely the RCC (and PWR and/or other if relevant) registers' content can be checked/compared to the expected ones...

To me, if problems are specifically related to the HSE with crystal and are solved by using an external clock, I'd start with investigating ground and power supply layout and decoupling.

JW

berendi
Principal
May 21, 2020

> Surely the RCC (and PWR and/or other if relevant) registers' content can be checked/compared to the expected ones...

If I know the expected values of the registers, then I can as well write them down in the code editor as assignments to those registers. Faster than guessing where to click in CubeMX, generate and run the code, check/compare again, repeat until my guess is right.

waclawek.jan
Super User
May 21, 2020

I meant, to find out what the source of instability is.

I was under the impression that you've had one unstable setting generated by CubeMX, and then rewrote it into the stable one. I'd compare those two settings. I don't like if there's a potential for screwup and I don't know from where it may hit.

YMMV.

JW

PMath.4
PMath.4Author
Senior III
May 21, 2020

"To me, if problems are specifically related to the HSE with crystal and are solved by using an external clock, I'd start with investigating ground and power supply layout and decoupling."

True if they weren't also solved by changing the optimisation level

waclawek.jan
Super User
May 21, 2020

You didn't say that. You said, optimization broke USB and cache coherency.

Optimization can change digital noise patterns. Running computing-intensive tasks (especially if they exercise an otherwise rarely used massive logic block (the FPU)) also increases digital noise.

JW

TDK
May 21, 2020

The HAL USB library is broken in that it stalls EP0 during enumeration, which is not allowed. This causes enumeration to only occasionally work and be apparently optimization-dependent, at least in my case. I suffered through this problem and eventually found the following:

https://github.com/STMicroelectronics/STM32CubeH7/issues/22

Go in the library and comment out any lines with:

USBD_LL_StallEP(pdev, 0U);

or

USBD_LL_StallEP(pdev, 80U);

Maybe that's one of the problems, maybe not. Sounds like there are other issues going on as well.

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
May 22, 2020

@TDK​ ,

I believe you are referring to device, whereas Peter is building a computer i.e. he complains about host behaviour.

The Synopsys OTG module has many ehm quirks, and the ST-provided software is not famous for being production-grade. I've described some experience with it in https://community.st.com/s/question/0D50X00009XkZ4KSAV/usb-host (beyond two More clicks), but I don't think these concrete ones could hit due to different level of optimization and/or upon powerup.

This sort of problems is to be solved using a bus analyzer + oscilloscope, and a deep understanding of USB as a protocol, the involved OTG module, and the given software.

[edit] removed expletives throughout the post [/edit]

JW

TDK
May 22, 2020

> I believe you are referring to device, whereas Peter is building a computer i.e. he complains about host behaviour.

@Community member​ You're right, I missed that while skimming. I don't have experience with the host USB code.

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
May 22, 2020

> I don't have experience with the host USB code.

Lucky you! ;)

JW

PMath.4
PMath.4Author
Senior III
May 22, 2020

"Cache coherency is usually an issue only when DMA is involved."

Certainly should be but I am absolutely convinced there is an issue in normal code when layers of indirection are used and the RAM is managed by the FMC. This feels like a silicon bug but I haven't got the time or energy to try and produce it in a simple enough way to post a formal errata.

It often seems to be associated with longjmp.

I've also found that in many places in the code I have had to declare variables volatile when there is absolutely no reason why this should be required. The latter is probably a compiler bug rather than silicon but it all makes development more tedious

waclawek.jan
Super User
May 22, 2020

> longjmp

Do you absolutely and perfectly understand the implications of setjmp/longjmp?

If not, get rid of it. If yes, you are probably wrong.

JW

PMath.4
PMath.4Author
Senior III
May 22, 2020

I do understand setjmp/longjmp. As I say I haven't the time or energy to try and isolate the issue but it goes something like this

global variable *p points to an area in SDRAM

write to *p typically this would be something like an error message when the Basic interpreter hits a syntax problem

longjmp back to start of program just after H/W initialisation

print *p

WTF - that wasn't what I stored

to fix cleanDcache before longjmp