Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Short Time Delays

System Timer Interrupt

This Wiki page addresses some counter-intuitive properties of using very short time delays. This Wiki page assumes that timing is generated by a system timer "tick" interrupt. In Tickless Mode there is no system timer interrupt. Much of the discussion here would also apply in the Tickless mode, however, the terminology used here assumes system timer interrupts.

Timer Resolution

When we talk about short delays, we are talking about delays that are on the same order of magnitude as the system timer interrupt interval. That interval is controlled the configuration setting CONFIG_USEC_PER_TICK. The default value of CONFIG_USEC_PER_TICK is 10,000 microseconds. That equivalent to a timer interrupt frequency of 100Hz:

...

There are many different OS interfaces that implement timed delays (or function that have timeout values such as sem_timedwait()). These all behave in basically the same way. For simplicity of discussion let's focus on on usleep(). usleep() is a standard but deprecated interface that simply delays for a specified number of microseconds (it is deprecated in favor of clock_nanosleep()).

Requirements/Assumptions of usleep()

The prototype for usleep() is:

...

http://nuttx.org/Images/short-delay.pngImage RemovedImage Added

For the most part, when delays are large – hundreds or thousands of microseconds – this error is not significant. It becomes noticeable only if you are using usleep() for delays very close to the the timer resolution when the error can be relatively significant.

...

This will return immediately with no delay. That satisfies all requirements and assumptions of the interface.

Using usleep() to implement periodic delays

The third assumption is necessary because usleep() has no knowledge of the current system timer phase. But it also makes usleep() a very bad choice for implementing periodic behavior if the usleep() delay is close to the system timer resolution. For example, consider a loop such as the following (again assuming that CONFIG_USEC_PER_TICK is set to 10,000 microseconds:

...

A final note: The above periodic delay loop can be made to work well, on the other hand, if the delay provided to usleep() is significantly larger that the system timer resolution.

What can you do?

What can you do to improve the resolution for such high frequency processing loop? First, you might consider increasing the system timer interrupt rate. You would do this by reducing the value of CONFIG_USEC_PER_TICK. For example a value of 1000 for CONFIG_USEC_PER_TICK would create a timer interrupt rate of 1KHz and a minimum loop delay of perhaps 2 milliseconds.

...

Another option is to abandon the system timer altogether and use a dedicated timer peripheral to perform your timed operations with high precision. But if you really want to use the system timer than another thing you should consider would be to implement a Timer Hook.

Timer Hook

A Timer Hook is a user provided function that is called from the OS on each timer interrupt. If you enable CONFIG_SYSTEMTICK_HOOK=y in your configuration, then the OS timer interrupt handler will call out to a user-provided function, board_timerhook(), on each timer interrupt. The full prototype of this function is provided in included/nuttx/board.h as:

...