Skip to main content
Visitor II
August 23, 2024
Question

STM32U575 incorrect timing

  • August 23, 2024
  • 4 replies
  • 930 views

I am testing the functions of STM32U575 and found the following issue.

I simply wrote this in main():

 

while(1){
 for(i=0;i<160;i++);
 HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_11);
}

 

where i is defined as uint32_t.

HCLK is set to 160MHz by using PLLCLK with source=16MHz HSE, M=1, N=10, and R=1. Therefore the Cortex System timer is also 160MHz.

But I found the PC11 pin toggles at a cycle of about 17.2us with ICACHE on and about 45us with ICACHE off, instead of about 1us expected. DCACHE is always on.

I tried changing the Cortex System timer frequency but found it has completely no effect on the toggling frequency.

I have also enabled TIM2 and generated a PWM which performs correctly, showing that HSE is working correctly.

Why did this issue occur and how to solve it?

Thanks in advance.

    This topic has been closed for replies.

    4 replies

    Graduate II
    August 23, 2024

    If you're going for high-frequency waveform generation, software control of GPIO is a bad way to do it.

    With any optimizations turned on, the compiler would likely remove the for loop as having no side-effects. At the very least, you should look at the disassembly to see what code is being generated.

    If compiler optimizations are off, don't expect your code to perform well.

    GPIO drive strength can be controlled via registers. Their reset value puts them at the weakest value possible. Depending on what the pin's load looks like, that can mean slow rise/fall times. But I would expect 1Mhz to be doable for a reasonable load, even with the default setting.

    As a general debugging approach, start at 1Hz, then gradually increase the toggle rate to find the range where code and reality begin to diverge. Investigate from there.

    ST Employee
    August 23, 2024

    I just toggled a GPIO on my U575 NUCLEO with GPIO Speed set to Very High

    calling HAL_GPIO_TOGGLE = ~ 4 MHZ

    calling GPIOF->ODR ^= GPIO_PIN_13 = ~ 16 MHZ

    Screenshot from 2024-08-23 01-01-08.png

    Screenshot from 2024-08-23 01-02-43.png

     

    Things to consider:

    - Trigger voltage : 3.3V in my case

    - HAL overhead.

    - For loop overheard of comparing and incrementing that variable. In both cases my pin toggled faster in a while(1) loop than in a for loop, obviously you need a for loop to break out but the point is that there is overhead, even if its fractional it will make a difference.

     

    I would also suggest reading the electrical characteristics for the IO ports for your chip in the Datasheet (not the RM)

     

    Screenshot from 2024-08-23 00-14-41.png

    Eventually there will be a section on output frequency based on, like the previous answer said, load capacitance

    Screenshot from 2024-08-23 00-15-36.png

     

    Super User
    August 23, 2024

    If you look at the disassembly of this code (i.e. the assembly instructions that the compiler generates) you'll see the loop takes more than 1 instruction. Also, each instruction in the loop can take multiple ticks.

    The misunderstanding is that this should take 1us (i.e. 160 ticks) per toggle even in the best of scenarios.

    Even then, these are not simple 8 bit microcontrollers. Instruction cycle counts are not fixed, lots of other variables at play here.

    Graduate II
    August 23, 2024

    >>instead of about 1us expected

    That's a pretty naive analysis. You should be looking at the machine code the MCU is running, and what the compiler did with the high-level code. Look at a disassembly.

    Perhaps write GPIO->ODR or GPIO->BSRR directly for highest efficiency.

    With optimization code like that can frequently be removed as it "does nothing"

    The GPIO speed will be limited by the APB/AHB buses it lives on.

    Whilst base through-put of the ARM MCU's can often be one-cycle, it's also pipe-lined. How deep that pipe is depends on the model.

    If you want 1 MHz output, you'd use a TIM, not manually toggle, and count machine cycles.