Concepts and structure

The main focus of the architecture of this package is the clock management thread. This thread acts as a central processing point in the system to: asynchronously initialize the clocks at system startup time; update the wallclock time either if directed by the user, or if required to by configuration settings (at regular periods, or whenever time is updated); and notify registered modules when the system time has been set or updated.

This thread should be a high priority thread as it is inherently time-sensitive, and the behaviour may not be as expected if pre-empted. For example, after the time has been changed, registered modules will be notified, but a higher priority thread could pre-empt and run before the notification has taken place, with the potential for different parts of the system to have different understandings of what the current time is. Although be aware there is a chance this can happen anyway as a potential consequence of the notification process, as obviously only one module can be notified at a time, meaning there can be a lag between the time change and notification.

The API functions of this package represent time using the POSIX standard defined structure struct timespec. This offers the most flexible and high resolution representation. The type is defined in the header file <time.h> and the standard mandates its definition as follows:

struct timespec {
    time_t tv_sec;    /* Seconds */
    long   tv_nsec;   /* Nanoseconds */
}

All uses of absolute time values are expressed using time as a struct timespec with an "epoch" (reference start date) of 1970-01-01 00:00:00 UTC. All time is based in the UTC time frame - no support for timezones is provided, which is instead left to higher layers.

Overall, the system time is maintained by reading a high resolution HAL clock, and maintaining a fixed relationship between that clock value and the set time. Global variables are used within the common clock package to allow for this, and are protected from simultaneous access, thus making the package thread safe. However no functions in this package can be considered safe to call from either an ISR or a DSR. At the beginning of system operation, interlocks are used to ensure that it is not possible to retrieve the system time until the common clock package has been initialized.

Time can be adjusted by a small amount - the maximum allowable range being a parameter set in the package configuration. When this happens, the clock is not set to the new time immediately ("stepped") but instead it gradually converges towards the new time base. It will still increase monotonically. Making changes to time in this way can be much less disruptive to applications, however it is not appropriate for large changes, as it would take either take too long to converge, or spend a significant duration with the time being significantly inaccurate. Time can be adjusted both forwards and backwards.

Conversion functions are available to convert between real time and tick counts for the kernel clock object associated with the clock which is driving system time. These use the clock converter functions provided in the eCos kernel.

2017-02-09
Documentation license for this page: eCosPro License