Trying to figure out some numbers around tickless idle

I am working on a Cortex M0+ (STM32G07) and experiment with tickless idle.
I did this:
in tasks.c , static portTASK_FUNCTION (prvIdleTask, pvParameters) in the #if (configUSE_TICKLESS_IDLE != 0) section, right at the beginning I added these lines that output the value returned by prvGetExpectedIdleTime :

      xExpectedIdleTime = prvGetExpectedIdleTime (); // this is originally in tasks.c
      if (xExpectedIdleTime > 100)
        uint32_t Wert = xExpectedIdleTime;
        char Str [10];
        char * Ptr = Str;
        while ((USART2->ISR & USART_ISR_TXE_TXFNF) == 0) { }
          *Ptr++ = 0x30 + (char)(Wert % 10);
          Wert /= 10;
        while (Wert > 0);
          USART2->TDR = *Ptr;
          //        USART2->TDR        = xExpectedIdleTime & 0xFF;
          while ((USART2->ISR & USART_ISR_TXE_TXFNF) == 0) { }
        while (Ptr != Str);
        USART2->TDR = '\n';

In a longer period of no task ready to run I see the values output counting down with a difference between each two values given by the maximum time that can be set with the 24-bit sys-timer. But I found that the first value is not correct, it is much to high.

Any explanations?
Thanky for any hint

Hi Martin,

What value are you getting at the beginning of a long period of no tasks ready? What value would you expect and why?

Hi Jeff,
I have seen two cases.
In one I know that it tries to enter power down right after a vTaskDelay of 5 sec. In that case I always get 2500 returned from prvGetExpectedIdleTime which is correct because I have 2msec tick period.
In the other case it may try to enter power down from various situations. In fact it will always try to enter power down whenever it comes to run idle task. In these cases I see values of about 3000. The next value, which occurs after one full sys timer down count of the whole 24 bit range is much smaller. But the difference should be 131 which is 2^24 / 64 MHz / 2msec. I see this 131 in all following outputs until 0 is reached.
Now the high starting value may lead to erroneous entries in low power mode. My final goal is to use this value to determine which kind of low power mode to enter.
One strange observation I made is that these false first values change with every new first enrty into idle task in a way that they get smaler by about 500 until zero, than start again at about 3000.
Here is an example from my mind, I can’t do measurement at the moment
first case:
2500 => 5 sec in ticks of 2msec
2369 => difference is 131
=> no output for values <= 100, see listing in my first post
second case
3256 => erroneous value
468 => this seems to be correct
337 => from here on difference is 131
=> here this idle period is over
2723 => next erroneous value, subsequent ones will always be about 500 less
473 => this seems to be correct
342 => from here on difference is 131
=> here this idle period is over
Yesterday I also noticed this comment in tasks.c: it is right before the place I inserted my code

  /* It is not desirable to suspend then resume the scheduler on
                 * each iteration of the idle task.  Therefore, a preliminary
                 * test of the expected idle time is performed without the
                 * scheduler suspended.  The result here is not necessarily
                 * valid. */

What precisely does that mean? In which cases must I expect unvalid values?

Thanks for any help


That comment is important, and it may explain your observations. If the scheduler is running, then the expected idle time could change at any time. That would happen if another task preempts the idle task and changes the expected idle time.

Just prior to suppressing the tick, the idle task disables the scheduler and verifies that there is enough idle time expected to justify suppressing the tick. At this time the expected idle time will not change and the tick-suppression logic can move ahead based on that expected idle time.

Your test code reports the values taken before the idle task disables the scheduler. Those values are subject to change as noted above. The amount of expected idle time changed from before disabling the scheduler to after. Both values are correct at the time they are measured.

Given the ultimate goal you described, you might take a look at configPRE_SLEEP_PROCESSING(). That is a good place for the application to evaluate which type of sleep to use and, optionally, to conduct that sleep.

Hi Jeff,
thanks for the clarification, I understand better now.