INtime software defines a value called "system time" which counts seconds and microseconds since the system epoch (January 1, 1978). This value is driven from the system hardware timer which is also used to synchronize threads in the kernel.
Time values are expressed in two structures:
TIMEVALUE is a structure which consists of a count of seconds and microseconds
SYSTEMTIME is a structure which specifies a date and time using individual members for year, month, day, weekday, hour minute second and microsecond.
INtime software provides time management calls that allow threads to create alarms and to sleep for a specified amount of time.
An alarm is an object which is signaled when a pre-determined time interval has expired. The alarm event mode may be single-shot or repeatable.
The kernel's RT clock is a counter that the kernel uses to keep track of the number of low-level ticks (kernel clock) that have occurred. When the kernel is initialized, the count is set to 0 (zero). The period of the low-level ticks is configurable via the INtime for Windows Configuration or the INtime Distributed RTOS Configuration and you can read the current configuration using CopyRtSystemInfo.
High-level RT system calls have a fixed wait-time granularity of 10 milliseconds (High-level ticks). The value specified for the time period is truncated to the nearest multiple 10-millisecond value. For example a value specified as 9 will be truncated to 0; a value of 11 will be truncated to 10.
Low-level (kernel) system calls have a configurable wait-time granularity that can be selected from the following options:
Kernel tick
10 milliseconds 5 milliseconds 2 milliseconds 1 millisecond 500 microseconds (default) 250 microseconds 200 microseconds 125 microseconds 100 microseconds 50 microseconds
Other clock intervals may be configured manually. Contact TenAsys Support if you would like information about this feature and its implications.
Selecting the low-level ticks (kernel) is an important setting for the system performance. Every time the low-level ticks occur, an interrupt is generated, the scheduler is called and some housekeeping is performed. It is best to reduce this load as much as possible. The shortest timing period in the application determines the best setting. If e.g. the application needs to respond on a 500 microseconds interval on a fieldbus, this is the preferred kernel tick setting. Choosing a shorter time, does not make the system faster or better reacting. Most threads are called outside the low-level ticks anyway, as semaphores or mailboxes just suspend one thread and signal another thread, which awakes as soon as possible based on priority (without waiting for the next low-level tick to arrive).
System time is the number of elapsed seconds and microseconds since the INtime epoch. System time is managed by a microseconds counter driven by the system timer hardware. It may be read and set in different formats. Setting the system time changes only the software counter, not the timer hardware.
Read the system time using either GetRtSystemTime or GetRtSystemTimeAsTimeValue. Set the time using SetRtSystemTime or SetRtSystemTimeAsTimeValue.
The rate at which the counter is incremented may be adjusted (for example to synchronize the system time with an external clock source) using the SetRtSystemTimeAdjustment call.
INtime for Windows is configured by default to synchronize the kernel system time with the Windows system time. A Windows service (INtime Clock Synchronization Service) manages this synchronization. The interval at which the system time is synchronized is configurable in the Kernel parameters and the default is every 300 seconds.
At kernel start-up, the INtime time of day (TOD) is set to match the Windows TOD. Thereafter, at each configured TOD update interval the INtime TOD is adjusted gradually to match the Windows TOD. You can also call the SyncLocalRtClock() function to start the adjustment process before the TOD update interval. A configured adjustment value is added to (or subtracted from) the INtime TOD at each system timer tick until the entire adjustment is made. If there is a large difference between the two clocks, it can take a while until they match.
There are options for the Advanced configuration tab of the INtime configuration tool to control how the time is adjusted. If you wish to change the default values you may need to add the section before adding the values.
Section: [ADJTIME]
BIGTHRESH
TICKADJ
BIGADJ
Section: [CLKSYNC]
ATTHRESH
Note that there is not much sanity checking done on the values provided for these parameters, so it is possible to configure values that may have unexpected/catastrophic results. For example, making BIGADJ > the system timer tick period (e.g., larger than 500 microseconds) can have the result that the INtime TOD moves backward between consecutive calls to read the time.
INtime Distributed RTOS systems initially synchronize with the system's RTC (battery clock) at startup, and do not perform any further synchronization by default. There is an optional SNTP client which may be configured to synchronize with an external server.
If you wish to perform your own synchronization then you must disable the Clock Synchronization Service and use the SetRtSystemTimeAdjustment call to make any adjustments.
The kernel lets you create alarm events to simulate timer interrupts. The system signals the alarm event object at which a thread you have written waits.
Two kinds of alarm events exist:
Create an alarm with the CreateRtAlarm system call and delete it with the DeleteRtAlarm system call. To create an alarm specify:
Use WaitForRtAlarm within a thread to signal the thread whenever the alarm's time expires.
After a thread calls the DeleteRtAlarm system call, the alarm object will no longer be signaled. Alarms can be deleted at any time. This means that deleting an alarm does not have to be synchronized with the expiration of the alarm.
The ResetRtAlarm system call resets an alarm, returning it to its initial state. Both single shot and repetitive alarms can be reset. Regardless of whether the alarm's time limit has expired, resetting an alarm returns it to its creation state and starts it running as if it were just created. Resetting a single shot alarm after it has gone off is equivalent to creating the alarm again.
The kernel enables threads to sleep for a specified time, using the RtSleep or RtSleepEx system call. The amount of time the thread will be in the asleep state can vary from no time to forever. If the specified time is NO_WAIT
, the thread will not sleep. A time limit of NO_WAIT
gives the processor to another thread of equal priority, if one exists.
WAIT_FOREVER
means the thread will never wake up. When a thread sleeps forever, it is effectively deleted, but its memory is not released. If a thread has completed its assigned functions, then delete it or suspend it rather than doing a sleep forever.
INtime provides a timestamp counter facility which is accessible from all nodes, and also Windows via NTX. The best possible source is automatically configured in order to provide a counter which is coordinated between the different nodes (the sources run at exactly the same frequency) and also if possible synchronized (in other words returns the same value from each node at a given instant). Where possible the source used is the system HPET, but if this is not available the CPU Time Stamp Counter (TSC) is used.
The system call GetRtTimestampInfo returns both the period of the configured counter, and flags indicating whether the source is coordinated and synchronized. The call GetRtTimestampCounter returns the value of the selected counter.
Sometimes it is desirable to synchronize the INtime system timer with an external timer source. Cases might include synchronization with a timestamp in an Ethernet packet in order to synchronize the application's cycle time to the source precisely.
Note: this is not the same as synchronizing the INtime wall clock (system time) with an external source. In that case the time of day provided by the system is kept in sync with an external source, irrespective of the local system timer rate. This type of synchronization can be achieved with the existing interfaces, such as SetRtSystemTimeAdjustment, or adjtime in the C library.
Two APIs are provided for this function. GetRtSystemTimerValues provides details of the current system clock configuration including the period of the base interrupt signal, and the reload value which is used to program the hardware clock. This last value is in arbitrary units and is provided to enable the programmer to determine the size of any increment to make to the clock. AdjustRtSystemTimer provides an increment to be applied to the reload value of the system timer.
The PC system CMOS clock (or "RTC") hardware is accessible from an application running on INtime Distributed RTOS. It is not accessible from an application running on INtime for Windows since in that case Windows is in control of the CMOS clock hardware.
The two APIs are provided to read or write the clock hardware. GetRtHardwareClock may be read for use when synchronizing the system timer, for example. SetRtHardwareClock is intended for use during the installation and initial configuration of a system only.
This section lists common operations related to time and alarms, and the kernel system calls that do the operations:
To . . . | Use this system call . . . |
---|---|
Return the current system time in a SYSTEMTIME structure | GetRtSystemTime |
Set the system time from a SYSTEMTIME structure | SetRtSystemTime |
Return the current system time in a TIMEVALUE structure | GetRtSystemTimeAsTimeValue |
Set the system time from a TIMEVALUE structure | SetRtSystemTimeAsTimeValue |
Return the current time adjustment value | GetRtSystemTimeAdjustment |
Set the system time adjustment | SetRtSystemTimeAdjustment |
Converts a SYSTEMTIME value to a TIMEVALUE value | SystemTimeToTimeValue |
Convert a TIMEVALUE value to a SYSTEMTIME value | TimeValueToSystemTime |
Compare two TIMEVALUE values | CompareRtTimeValue |
Return a TIMEVALUE of the number of microseconds elapsed since the system was started | GetRtRunTime |
Create an alarm | CreateRtAlarm |
Delete an alarm | DeleteRtAlarm |
Reset an alarm | ResetRtAlarm |
Wait on an alarm | WaitForRtAlarm |
Get elapsed time as number of system timer ticks. | knGetKernelTime |
Reset the time as number of system timer ticks. | knSetKernelTime |
Put a thread to sleep | RtSleep, RtSleepEx |
Get the timestamp counter information | GetRtTimestampInfo, ntxGetRtTimestampInfo |
Get the timestamp counter value | GetRtTimestampCounter, ntxGetRtTimestampCounter |
Get CPU timestamp counter and frequency | QueryRtPerformanceCounter, QueryRtPerformanceFrequency |
Read the system CMOS clock ("RTC") | GetRtHardwareClock |
Set the system CMOS clock ("RTC") | SetRtHardwareClock |
Read the system hardware timer details | GetRtSystemTimerValues |
Make an adjustment to the system hardware timer | AdjustRtSystemTimer |
Synchronize the time of day clock to an external source. | SyncLocalRtClock |