Increment xTickCount before call of vTaskStartScheduler()

hpc64 wrote on Monday, September 04, 2017:

Hello,

We call vTaskStartScheduler() quite late after power-up. By this, the xTickCount does not represent the number of ticks since power-up.

To change this we removed the scheduler startet condition from the SysTickHandler:

void SysTickHandler()
{
   //if ( xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED )
     xPortSysTickHandler();
 }

and added the follwing return in case the scheduler is not running:

BaseType_t xTaskIncrementTick( void )
{
        [...]
		xTickCount = xConstTickCount;

>>>  if ( xSchedulerRunning != pdTRUE )
>>>	  return pdFALSE;

		if( xConstTickCount == ( TickType_t ) 0U )
        [...]
 }

Is this solution ok or is there better, less intrusive option (despite of starting the scheduler immediately after power-up)?

Thanks a lot for any help and best regards!

rtel wrote on Monday, September 04, 2017:

I’m pretty sure this is not code that we distribute:

void SysTickHandler()
{
//if ( xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED )
xPortSysTickHandler();
}

Not sure where you got it. We don’t start the systick timer until after
the scheduler has been started, so a check to see if the scheduler had
been started on every single tick interrupt (and there are a lot of
them) would seem to be wasteful and obsolete. So in answer to part of
your question - removing the if() would seem to be fine considering it
is not there anyway in the official code.

After that, the important thing is to ensure the tick interrupt does not
attempt to unblock any tasks if the scheduler is not running.

Note many of the FreeRTOS API functions will deliberately leave
interrupts masked up to the configMAX_SYSCALL_PRIORITY value until
after the scheduler has started.

richard_damon wrote on Monday, September 04, 2017:

I generally try to get the Scheduler running quickly. I will create the Tasks/Queues/Semaphores that I can before startup and initialize basic hardware (where it doesn’t require the use of interrupts or delays), and then bring up the schedule. Operations that take time are done with the scheduler running, so they can use the same drivers as used during the “normal” operation.

The one case I could see for delaying the start of the scheduler would be if I had to read some boot information from a device that I will not need after boot. Then perhaps using a polling driver might make sense.

hpc64 wrote on Monday, September 04, 2017:

In principe I completly agree.This has also the advantage that initializations that contain long delays could be done in parallel speeding up the whole initializatoin.

It’s just that I do not want to make this change right now and just correct the tick count.

hpc64 wrote on Monday, September 04, 2017:

I am sorry, the original code was:

void SysTickHandler()
{
   if ( xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED )
      return;
   xPortSysTickHandler();
 }

When using just

void SysTickHandler()
{
   xPortSysTickHandler();
}

and without the above added return condition in xTaskIncrementTick the system gets stuck in the first call of xPortSysTickHandler().

The reason might be that as you mentioned abobve it is not ensured that the tick interrput does not attempt to unblock any tasks. How can this be done?

richard_damon wrote on Monday, September 04, 2017:

Calling xPortSysTickHandler before the scheduler is running is apt to cause problems, as it expects that it is only going to be called after the scheduler has been started (one reason FreeRTOS api calls disable the interrupts).

One solution might be to modify the FreeRTOS code to give you access to the tick counter variable and just increment it yourself before the Scheduler has started.

The other question is if it really is important the the tick counter be time since ‘turn on’ vs ‘scheduler started’. The systick isn’t designed to be an absolute time clock, but a relative clock, so where 0 is doesn’t normally matter that much. (and there have been proposals that perhaps it shouldn’t start at 0, but at some large value that will roll over in a short time to make testing that code handles the roll over easier, more important on systems with 16 bit ticks).

rtel wrote on Monday, September 04, 2017:

I wonder if it would be possible/feasible to call vTaskSuspendAll()
before the scheduler is started, then xTaskResumeAll() from the first
task to run after the scheduler has started (maybe from the Daemon task
startup hook). When the scheduler is suspended no context switches will
be attempted, but the tick count will increment.

richard_damon wrote on Monday, September 04, 2017:

You would have to make sure the Daemon task was the first to run. If being used for ISR Pend Functions it is likely highest priority, if just for Timer functions, it might not need to be. It also needs to be (I think) the only task at the priority as it is created on the call to start the scheduler and I think first created gets run first.