Tickless microsecond delay before sleep

cajjed wrote on Wednesday, November 23, 2016:

I am using a samd21g18a and using the Atmel Software Framework with freeRTOS 9.0. I have implemented tickless using an external oscillator and my own vPortSuppressTicksAndSleep function (mostly just the version used by ASF and others online). The tickless mode works great. I am trying to implement a delay before sleeping so that my usart can empty before sleeping. To do this I put a notReadyToSleep function at the beginning of vPortSuprressTicksAndSleep:

bool notReadyToSleep(void) {
    if (head != tail) return true;
    // Delay to let last print byte be written
    delayMicroseconds(60);
    return false;
}

If the function is true I don’t try and sleep. If it is false then I wait 60 microseconds and then continue. This causes serious random issues with my tick count (For example, vTaskDelay of a second will take microseconds). My Tick Rate is 1024 Hz.

To avoid the need for uartReadyToSleep function I have implemented a waitToSleepTask:

void waitToSleepTask(void *params) {
	for (;;) {
		ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
		while (notReadyToSleep()) {
			vTaskDelay(1);
		}
		// Delay to let last print byte be written
		delayMicroseconds(60);
	}
}

The task method works fine but I would rather use a function check before tickless sleep, thus avoid having such a simple task running. Is there a way to implement this in vPortSuprressTicksAndSleep? I would have thought the 60 microsecond delay would just end up in the sleep noise.

rtel wrote on Wednesday, November 23, 2016:

I’m afraid I don’t understand what your problem is. I think you are
saying that calling delayMicrosencods() is causing a problem with the
tick frequency, so I’m going to GUESS that you have implemented
delayMicroseconds() such that it uses the same clock as the tick timer.

cajjed wrote on Wednesday, November 23, 2016:

Thanks for your response and I am sensing further insight in your response.

I am using the SysTick in my delay. I read it and then just wait for the 60 microseconds to pass. I was using the Atmel Studio Framework (ASF) to configure the SysTick Counter (SysTick_Config) for this purpose (core_cm0plus.h):

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)  return (1);      /* Reload value impossible */

  SysTick->LOAD  = ticks - 1;                                  /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

Your answer makes me believe that by doing this I am cuasing issues with the FreeRTOS tick when I configure this SysTick?

I will explore, but any further enlightenment is appreciated…

rtel wrote on Wednesday, November 23, 2016:

By default, FreeRTOS needs to control the SysTick timer.

cajjed wrote on Wednesday, November 23, 2016:

Thanks,

I see that now. I had made the false assumption that SysTick was just another counter and that FreeRTOS had its own systick counter.

cajjed wrote on Wednesday, November 23, 2016:

So follow on question. In this tickless implementation it uses a timer/counter to fire the callback xPortSysTickHandler every freeRTOS tick (in my case 1/1024 sec). Since SysTick never gets enabled in vPortSetupTimerInterrupt (because I am user a timer/counter) is SysTick just a place to store tick counts?

rtel wrote on Wednesday, November 23, 2016:

Maybe without re-reading the whole thread I made a mistake in the last
answer. If you are using your own clock to generate the tick, and the
systick is not used by RTOS, then you can use the SysTick for your own
purposes - but it will likely stop if you go into a deep sleep.

cajjed wrote on Wednesday, November 23, 2016:

Thanks again for the responses, they have been very helpful. It looks like my problem is that the default SysTick_Config from ASF as shown above was setting the systick handler (SysTick_Handler) to fire when it reached the LOAD value. The problem is that the same handler is still tied to xPortSysTickHandler. So the SysTick_Handler was getting called every tick (1/1024) and then every time the SysTick reach full load (0x00FFFFFF) or in my case about every 350 ms. This extra call was thus causing all kinds of randomness. Is there a way to replace SysTick_Handler with another handler?

#define xPortSysTickHandler                     SysTick_Handler

Thanks again

rtel wrote on Thursday, November 24, 2016:

Yes - the systick handler is just an entry in the vector table and you
can replace it with whatever you like. Its is best not to edit the
vector table directly, but instead provide the definition of a function
call SysTick_Handler - which is the name of the installed handler. The
line of code in your post above is effectively doing that by using a
#define to change the name of the FreeRTOS SysTick handler, which is
called xPortSysTickHandler, to SysTick_Handler.