1 <!-- Copyright (C) 2003 Red Hat, Inc. -->
2 <!-- This material may be distributed only subject to the terms -->
3 <!-- and conditions set forth in the Open Publication License, v1.0 -->
4 <!-- or later (the latest version is presently available at -->
5 <!-- http://www.opencontent.org/openpub/). -->
6 <!-- Distribution of the work or derivative of the work in any -->
7 <!-- standard (paper) book form is prohibited unless prior -->
8 <!-- permission is obtained from the copyright holder. -->
12 >More Features — Clocks and Alarm
14 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
17 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
20 TITLE="eCos User Guide"
21 HREF="ecos-user-guide.html"><LINK
23 TITLE="Programming With eCos"
24 HREF="user-guide-programming.html"><LINK
26 TITLE="A Sample Program with Two Threads"
27 HREF="sample-twothreads.html"><LINK
29 TITLE="The eCos Configuration Tool"
30 HREF="the-ecos-configuration-tool.html"></HEAD
41 SUMMARY="Header navigation table"
58 HREF="sample-twothreads.html"
72 HREF="the-ecos-configuration-tool.html"
85 NAME="CLOCKS-AND-ALARM-HANDLERS">Chapter 14. More Features — Clocks and Alarm
88 >If a program wanted to execute a task at a given time, or
89 periodically, it could do it in an inefficient way by sitting in a
90 loop and checking the real-time clock to see if the proper amount of
91 time has elapsed. But operating systems usually provide system calls
92 which allow the program to be informed at the desired time.</P
97 > provides a rich timekeeping formalism, involving
124 precise definition, relationship, and motivation of these features is
125 beyond the scope of this tutorial, but these examples illustrate how
126 to set up basic periodic tasks.</P
128 >Alarms are events that happen at
129 a given time, either once or periodically. A thread associates an
130 alarm handling function with the alarm, so that the function will
131 be invoked every time the alarm “goes off”.</P
137 NAME="SAMPLE-ALARMS">A Sample Program with Alarms</H1
143 the examples directory) is a short program that creates a thread that
144 creates an alarm. The alarm is handled by the function
147 >test_alarm_func()</TT
148 >, which sets a global
149 variable. When the main thread of execution sees that the variable has
150 changed, it prints a message.</P
156 >Example 14-1. A sample program that creates an alarm</B
165 CLASS="PROGRAMLISTING"
166 >/* this is a very simple program meant to demonstrate
167 a basic use of time, alarms and alarm-handling functions in eCos */
169 #include <cyg/kernel/kapi.h>
171 #include <stdio.h>
174 #define STACKSIZE 4096
176 static cyg_handle_t thread[NTHREADS];
178 static cyg_thread thread_obj[NTHREADS];
179 static char stack[NTHREADS][STACKSIZE];
181 static void alarm_prog( cyg_addrword_t data );
183 /* we install our own startup routine which sets up
184 threads and starts the scheduler */
185 void cyg_user_start(void)
187 cyg_thread_create(4, alarm_prog, (cyg_addrword_t) 0,
188 "alarm_thread", (void *) stack[0],
189 STACKSIZE, &thread[0], &thread_obj[0]);
190 cyg_thread_resume(thread[0]);
193 /* we need to declare the alarm handling function (which is
194 defined below), so that we can pass it to cyg_alarm_initialize() */
195 cyg_alarm_t test_alarm_func;
197 /* alarm_prog() is a thread which sets up an alarm which is then
198 handled by test_alarm_func() */
199 static void alarm_prog(cyg_addrword_t data)
201 cyg_handle_t test_counterH, system_clockH, test_alarmH;
202 cyg_tick_count_t ticks;
203 cyg_alarm test_alarm;
204 unsigned how_many_alarms = 0, prev_alarms = 0, tmp_how_many;
206 system_clockH = cyg_real_time_clock();
207 cyg_clock_to_counter(system_clockH, &test_counterH);
208 cyg_alarm_create(test_counterH, test_alarm_func,
209 (cyg_addrword_t) &how_many_alarms,
210 &test_alarmH, &test_alarm);
211 cyg_alarm_initialize(test_alarmH, cyg_current_time()+200, 200);
213 /* get in a loop in which we read the current time and
214 print it out, just to have something scrolling by */
216 ticks = cyg_current_time();
217 printf("Time is %llu\n", ticks);
218 /* note that we must lock access to how_many_alarms, since the
219 alarm handler might change it. this involves using the
220 annoying temporary variable tmp_how_many so that I can keep the
221 critical region short */
222 cyg_scheduler_lock();
223 tmp_how_many = how_many_alarms;
224 cyg_scheduler_unlock();
225 if (prev_alarms != tmp_how_many) {
226 printf(" --- alarm calls so far: %u\n", tmp_how_many);
227 prev_alarms = tmp_how_many;
229 cyg_thread_delay(30);
233 /* test_alarm_func() is invoked as an alarm handler, so
234 it should be quick and simple. in this case it increments
235 the data that is passed to it. */
236 void test_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data)
238 ++*((unsigned *) data);
245 >When you run this program (by typing <B
255 >) prompt) the output should look like
265 >Starting program: <TT
270 >/examples/simple-alarm.exe
279 --- alarm calls so far: 1
287 --- alarm calls so far: 2
300 >When running in a simulator the delays
301 might be quite long. On a hardware board (where the clock speed is 100
302 ticks/second) the delays should average to about 0.3 seconds (and 2
303 seconds between alarms). In simulation, the delay will depend on the
304 speed of the host processor and will almost always be much slower than
305 the actual board. You might want to reduce the delay parameter when
306 running in simulation.</P
310 >Here are a few things you might notice about this program:</P
318 >cyg_real_time_clock()</TT
320 this always returns a handle to the default system real-time clock. </P
324 >Clocks are based on counters, so the function <TT
326 >cyg_alarm_create()</TT
328 uses a counter handle. The program used the function
331 >cyg_clock_to_counter()</TT
332 > to strip the clock handle
333 to the underlying counter handle. </P
337 >Once the alarm is created it is
340 >cyg_alarm_initialize()</TT
342 sets the time at which the alarm should go off, as well as the period
343 for repeating alarms. It is set to go off at the current time and
344 then to repeat every 200 ticks. </P
348 >The alarm handler function
351 >test_alarm_func()</TT
352 > conforms to the guidelines for
353 writing alarm handlers and other delayed service routines: it does not invoke any
354 functions which might lock the scheduler. This is discussed in detail
360 > Reference Manual</I
383 main thread of control and is also modified in the alarm handler. To
384 prevent a possible (though unlikely) race condition on this variable,
388 > in the principal thread
389 is protected by calls to <TT
391 >cyg_scheduler_lock()</TT
395 >cyg_scheduler_unlock()</TT
396 >. When the scheduler is
397 locked, the alarm handler will not be invoked, so the problem is
408 SUMMARY="Footer navigation table"
419 HREF="sample-twothreads.html"
428 HREF="ecos-user-guide.html"
437 HREF="the-ecos-configuration-tool.html"
447 >A Sample Program with Two Threads</TD
453 HREF="user-guide-programming.html"
461 >The eCos Configuration Tool</TD