Time Management
Nano-RK employs a novel energy-efficient time management scheme using one-shot timer interrupts instead of a polling interrupt. Traditionally, an operating system will periodically call the scheduler in order to check if a context swap should occur and to update the time of day (TOD) counter. This consumes excess energy especially during long periods of sleep. Nano-RK operates the main hardware timer in a one-shot mode wherein the next timing interrupt is triggered when either a task is scheduled to be awakened because of an event or because it becomes eligible for scheduling. This is inherently more energy-efficient than schemes that needlessly call the scheduler. Smaller OS tick granularity requires that the hardware interrupt counter be able to accumulate larger values before it overflows. In the case of extended idle intervals, this timer overflow maintenance has an associated energy penalty.
Nano-RK’s representation for time is based on the POSIX time structure timeval. This consists of two 32-bit numbers to represent the (seconds,nanoseconds) fields. The Nano-RK TOD counter field is incremented as needed, and overflows will not occur for practically foreseeable intervals of time. This allows Nano-RK to support the fine-granularity timing requirements of real-time applications while maintaining a (practically) non-overflowing notion of absolute time.
The Nano-RK timer tick is approximately 1ms. Any time events scheduled in the future are rounded to the nearest timer tick. This guarantees that time related events such as task periods and event wake-ups will experience at most 1ms of jitter with respect to their target time.
typedef struct { uint32_t secs; uint32_t nano_secs; } nrk_time_t;
Time structure used to set periods, timing reserves, future wake-ups and to access the wall clock time.
nrk_time_set
| void nrk_time_set(uint32_t secs, uint32_t nano_secs) |
| Parameters: uint32_t secs seconds since the epoch |
| Parameters: uint32_t nano_secs nano seconds since the epoch |
| Return Values: none |
This function sets the system wall clock time. Typically just at startup.
nrk_time_get
| void nrk_time_get(nrk_time_t *t) |
| Parameters: nrk_time_t *t seconds and nano seconds since the epoch returned |
| Return Values: none |
This function gets the current wall clock time from the system.
nrk_wait_until
| nrk_status_t nrk_wait_until(nrk_time_t t) |
| Parameters: nrk_time_t t time to wait |
| Return Values: NRK_OK or NRK_ERROR |
This function causes the task to suspend until an absolute time in the future. Returns 1 upon success and 0 upon failure.
nrk_spin_wait_us
| void nrk_spin_wait_us(uint16_t time) |
| Parameters: uint16_t time is the time in microseconds to spin wait |
| Return Values: none |
This function busy loops for time micro-seconds. This is not a suspend call.
nrk_wait
| nrk_status_t nrk_wait(nrk_time_t t) |
| Parameters: uint16_t time is the time in microseconds to spin wait |
| Return Values: NRK_OK or NRK_ERROR |
This function causes the task to suspend for the specified relative amount of time. Returns NRK_OK upon success and NRK_ERROR upon failure.
nrk_wait_until_ticks
| nrk_status_t nrk_wait_until_ticks(uint16_t ticks) |
| Parameters: uint16_t ticks is the time in OS ticks to wait |
| Return Values: NRK_OK or NRK_ERROR |
This function suspends the task for a specific number of OS ticks. Use this only in situations where you require exact OS tick boundaries.
nrk_time_sub
| nrk_status_t nrk_time_sub(nrk_time_t *result,nrk_time_t high, nrk_time_t low) |
| Parameters: nrk_time_t *result will hold high - low |
| Parameters: nrk_time_t high should hold the larger time value |
| Parameters: nrk_time_t low should hold the smaller time value |
| Return Values: NRK_OK or NRK_ERROR |
This is a helper function that subtracts two nrk_time_t values. result is a pointer to a structure that will contain high - low. Returns 1 upon success and 0 upon failure.
nrk_time_add
| nrk_status_t nrk_time_add(nrk_time_t *result,nrk_time_t a, nrk_time_t b) |
| Parameters: nrk_time_t *result will hold a + b |
| Parameters: nrk_time_t a holds one of the time values to be added |
| Parameters: nrk_time_t b holds one of the time values to be added |
| Return Values: NRK_OK or NRK_ERROR |
This is a helper function that adds two nrk_time_t values. result is a pointer to a structure that will contain a + b. Returns 1 upon success and 0 upon failure.
nrk_time_compact_nanos
| void nrk_time_compact_nanos(nrk_time_t *t) |
| Parameters: nrk_time_t *t holds the time structure that you wish to compact |
| Return Values: none |
This function takes an nrk_time_t structure and compacts it such that the nano_secs field is smaller than a full second. Any overflowed nanosecs are added into the secs field.
