The counter objects provided by the kernel provide an abstraction of the clock facility that is generally provided. Application code can associate alarms with counters, where an alarm is identified by the number of ticks until it triggers, the action to be taken on triggering, and whether or not the alarm should be repeated.
There are two different implementations of the counter objects. The first stores all alarms in a single linked list. The alternative implementation uses a table of linked lists, with the size of the table being a separate configurable option. A single list is more efficient in terms of memory usage and is generally adequate when the application only makes use of a small number of alarms. For more complicated operations it is better to have a table of lists since this reduces the amount of computation whenever the timer goes off. Assuming a table size of 8 (the default value) on average the timer code will only need to check 1/8 of the pending alarms instead of all of them.
The configuration options which select the counter implementation are CYGIMP_KERNEL_COUNTERS_MULTI_LIST (the section called Option: Implement counters using a table of lists in Chapter 17) and CYGIMP_KERNEL_COUNTERS_SINGLE_LIST (the section called Option: Implement counters using a single list in Chapter 17).
The following functions can be used to create and manipulate counters:
void cyg_counter_create(cyg_handle_t counter, cyg_counter *counter);
Creates a new counter and places it in the space pointed to by counter. A counter stores a value that is incremented by cyg_counter_tick(). Alarms may be attached to counters, and the alarms will trigger when the counter reaches a specified value.
void cyg_counter_delete(cyg_handle_t counter);
Deletes the given counter and frees the corresponding memory.
cyg_tick_count_t cyg_counter_current_value(cyg_handle_t counter);
Returns the current value of the given counter.
void cyg_counter_set_value(cyg_handle_t counter, cyg_tick_count_t new_value);
Sets the counter"s value to new_value.
void cyg_counter_tick(cyg_handle_t counter);
Advances the counter by one tick.
Clocks are counters which are associated with a stream of ticks that represent time periods. Clocks have a resolution associated with them, whereas counters do not.
The most frequently used clock is the real-time clock which serves two special purposes. First, it is necessary to support clock and alarm related functions such as cyg_thread_delay(). Second, it is needed to implement timeslicing in the mlqueue and lottery schedulers. If the application does not require either of these facilities, then it is possible to disable the real-time clock support completely. It is also possible to disable just timeslicing with the configuration option CYGSEM_KERNEL_SCHED_TIMESLICE, or just the clock and alarm functions, using the option CYGFUN_KERNEL_THREADS_TIMER. See the section called Component: Kernel schedulers in Chapter 17 for more information.
The real-time clock is available if the configuration option CYGVAR_KERNEL_COUNTERS_CLOCK (see the section called Option: Provide real-time clock in Chapter 17) is defined.
Clock resolution is stored in variables of type cyg_resolution_t (see the section called cyg_resolution_t).
void cyg_clock_create(cyg_resolution_t resolution, cyg_handle_t *handle, cyg_clock *clock);
Creates a clock object with the given resolution and places it in the space pointed to by clock. A clock is a counter driven by a regular source of ticks. For example the system real-time clock is driven by a clock interrupt.
void cyg_clock_delete(cyg_handle_t clock);
Deletes a clock object and frees the associated memory.
void cyg_clock_to_counter(cyg_handle_t clock, cyg_handle_t *counter);
Converts a clock handle to a counter handle. The counter functions can then be used with the counter handle.
void cyg_clock_set_resolution(cyg_handle_t clock, cyg_resolution_t resolution);
Changes the resolution of a given clock object.
cyg_resolution_t cyg_clock_get_resolution(cyg_handle_t clock);
Returns the resolution of clock.
Returns a handle to the system-supplied real-time clock.
Returns the real-time clock"s counter. This is equivalent to executing the code:
cyg_clock_to_counter(cyg_real_time_clock(), &h), cyg_counter_current_value(h);
typedef void cyg_alarm_t(cyg_handle_t alarm, void *data);
cyg_alarm_t is the type used for functions which are used to handle alarm events. It is used in the function cyg_alarm_create().
void cyg_alarm_create(cyg_handle_t counter, cyg_alarm_t *alarmfn, void *data, cyg_handle_t *handle, cyg_alarm *alarm);
Creates an alarm object. The alarm is attached to the counter and is created in the memory pointed to by alarm. When the alarm triggers, the handler function alarmfn is called and is passed data as a parameter. The alarm handler executes in the context of the function that incremented the counter and thus triggered the alarm.
Note: If the alarm is associated with the real-time clock, the alarm handler alarmfn will be invoked by the delayed service routine (DSR) that services the real-time clock. This means that real-time clock alarm handlers (which are possibly the most frequently used) must follow the rules of behavior for DSRs. These rules are outlined in the section called Interrupt and exception handlers in Chapter 3.
void cyg_alarm_delete(cyg_handle_t alarm);
Disables the alarm, detaches from the counter, invalidates handles, and frees memory if it was dynamically allocated by cyg_alarm_create().
void cyg_alarm_initialize(cyg_handle_t alarm, cyg_tick_count_t trigger, cyg_tick_count_t interval);
Initialize an alarm. This sets it to trigger at the tick with value trigger. When an alarm triggers, this event is dealt with by calling the alarmfn parameter which was passed when the alarm was created using cyg_alarm_create(). If interval is non-zero, then after the alarm has triggered it will set itself to trigger again after interval ticks. Otherwise, if interval is zero, the alarm is will be disabled automatically once it has triggered.
void cyg_alarm_enable(cyg_handle_t alarm);
Enables an alarm that has been disabled by calling cyg_alarm_disable().
void cyg_alarm_disable(cyg_handle_t alarm);
Disables an alarm. After an alarm is disabled it will not be triggered unless it is subsequently re-enabled by calling cyg_alarm_enable() or is reinitialized by calling cyg_alarm_initialize().
Note, though, that if a periodic alarm that has been disabled is re-enabled without reinitializing it will be in phase with the original sequence of alarms. If it is reinitialized, the new sequence of alarms will be in phase with the moment in which cyg_alarm_initialize() was called.