cwhile-loopmicrocontroller

Why does using nested loops cause the program to freeze?


I was trying to run the WDT on a specific microcontroller (it's still under development, and I accidentally got it as a test sample) and encountered an issue where, to start the WDT, there needs to be a delay between initialization and the WDT starting. There are no standard functions for this, so I wrote simple nested loops.

What I expect from it is the following:

And it actually works like that!

However, I decided to change i = 2, expecting no significant changes
(after the first while(i--), j remains 0, which I understood during experiments),
and the delay time should change by some number of clock cycles, which should be unnoticed by me, and I should still observe the blinking of both LEDs.

But the green LED does not turn off, and the red LED does not turn on.

Can you tell me what might be the problem? Is it related to the C language, the compiler, or specific to the microcontroller?

Here is the code:

int main()
{
    volatile uint32_t i=1;
    volatile uint32_t j=1000000;;

    setup();
    GREEN_LED_OFF();
    RED_LED_OFF();
    WDT_Init();
    GREEN_LED_ON();
    while(i--)
    {
        while(j--)
        {

        }
    }
    GREEN_LED_OFF();
    HAL_WDT_Start(&hwdt, 100);
    while(1)
    {
        RED_LED_ON();
    }
}

Solution

  • When you change i to 2 after the first loop j is not 0 but UINT32_MAX as j is being decremented after the test, which is 4'294'967'295. If you have 80MHz clock and your loop is executed in 10clock cycles (volatile and -O3) then it will take 42'949'672'950 clock cycles to go through your loop.

    It will take about 536 seconds if your code is executed from SRAM with 0 wait states. If you execute from FLASH it will take longer.

    If you do not enable optimizations then this loop will run much longer

    Demo:

    int main(void)
    {
        volatile unsigned i = 1;
        volatile unsigned j = 1000000;
    
        while(i--)
        {
            while(j--)
            {
    
            }
            printf("j = %u\n", j);
        }
    }
    

    https://godbolt.org/z/8P8f83ssf

    if you change to while(--j) then decrementing will happen before test and j will be 0 after the test