]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/user-guide/clocks-and-alarm-handlers.html
Initial revision
[karo-tx-redboot.git] / doc / html / user-guide / clocks-and-alarm-handlers.html
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.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >More Features &#8212; Clocks and Alarm
13 Handlers</TITLE
14 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
15 <META
16 NAME="GENERATOR"
17 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
18 "><LINK
19 REL="HOME"
20 TITLE="eCos User Guide"
21 HREF="ecos-user-guide.html"><LINK
22 REL="UP"
23 TITLE="Programming With eCos"
24 HREF="user-guide-programming.html"><LINK
25 REL="PREVIOUS"
26 TITLE="A Sample Program with Two Threads"
27 HREF="sample-twothreads.html"><LINK
28 REL="NEXT"
29 TITLE="The eCos Configuration Tool"
30 HREF="the-ecos-configuration-tool.html"></HEAD
31 ><BODY
32 CLASS="CHAPTER"
33 BGCOLOR="#FFFFFF"
34 TEXT="#000000"
35 LINK="#0000FF"
36 VLINK="#840084"
37 ALINK="#0000FF"
38 ><DIV
39 CLASS="NAVHEADER"
40 ><TABLE
41 SUMMARY="Header navigation table"
42 WIDTH="100%"
43 BORDER="0"
44 CELLPADDING="0"
45 CELLSPACING="0"
46 ><TR
47 ><TH
48 COLSPAN="3"
49 ALIGN="center"
50 >eCos User Guide</TH
51 ></TR
52 ><TR
53 ><TD
54 WIDTH="10%"
55 ALIGN="left"
56 VALIGN="bottom"
57 ><A
58 HREF="sample-twothreads.html"
59 ACCESSKEY="P"
60 >Prev</A
61 ></TD
62 ><TD
63 WIDTH="80%"
64 ALIGN="center"
65 VALIGN="bottom"
66 ></TD
67 ><TD
68 WIDTH="10%"
69 ALIGN="right"
70 VALIGN="bottom"
71 ><A
72 HREF="the-ecos-configuration-tool.html"
73 ACCESSKEY="N"
74 >Next</A
75 ></TD
76 ></TR
77 ></TABLE
78 ><HR
79 ALIGN="LEFT"
80 WIDTH="100%"></DIV
81 ><DIV
82 CLASS="CHAPTER"
83 ><H1
84 ><A
85 NAME="CLOCKS-AND-ALARM-HANDLERS">Chapter 14. More Features &#8212; Clocks and Alarm
86 Handlers</H1
87 ><P
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
93 ><P
94 ><SPAN
95 CLASS="PRODUCTNAME"
96 >eCos</SPAN
97 > provides a rich timekeeping formalism, involving
98 <SPAN
99 CLASS="emphasis"
100 ><I
101 CLASS="EMPHASIS"
102 >counters</I
103 ></SPAN
104 >, <SPAN
105 CLASS="emphasis"
106 ><I
107 CLASS="EMPHASIS"
108 >clocks</I
109 ></SPAN
110 >,
111 <SPAN
112 CLASS="emphasis"
113 ><I
114 CLASS="EMPHASIS"
115 >alarms</I
116 ></SPAN
117 >, and <SPAN
118 CLASS="emphasis"
119 ><I
120 CLASS="EMPHASIS"
121 >timers</I
122 ></SPAN
123 >.  The
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
127 ><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 &#8220;goes off&#8221;.</P
132 ><DIV
133 CLASS="SECT1"
134 ><H1
135 CLASS="SECT1"
136 ><A
137 NAME="SAMPLE-ALARMS">A Sample Program with Alarms</H1
138 ><P
139 ><TT
140 CLASS="FILENAME"
141 >simple-alarm.c</TT
142 > (in
143 the examples directory) is a short program that creates a thread that
144 creates an alarm. The alarm is handled by the function
145 <TT
146 CLASS="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
151 ><DIV
152 CLASS="EXAMPLE"
153 ><A
154 NAME="AEN910"><P
155 ><B
156 >Example 14-1. A sample program that creates an alarm</B
157 ></P
158 ><TABLE
159 BORDER="5"
160 BGCOLOR="#E0E0F0"
161 WIDTH="70%"
162 ><TR
163 ><TD
164 ><PRE
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 */
168
169 #include &lt;cyg/kernel/kapi.h&#62;
170
171 #include &lt;stdio.h&#62;
172
173 #define NTHREADS 1
174 #define STACKSIZE 4096
175
176 static cyg_handle_t thread[NTHREADS];
177
178 static cyg_thread thread_obj[NTHREADS];
179 static char stack[NTHREADS][STACKSIZE];
180
181 static void alarm_prog( cyg_addrword_t data );
182
183 /* we install our own startup routine which sets up
184   threads and starts the scheduler */
185 void cyg_user_start(void)
186 {
187  cyg_thread_create(4, alarm_prog, (cyg_addrword_t) 0,
188         "alarm_thread", (void *) stack[0],
189         STACKSIZE, &amp;thread[0], &amp;thread_obj[0]);
190  cyg_thread_resume(thread[0]);
191 }
192
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;
196
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)
200 {
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;
205
206  system_clockH = cyg_real_time_clock();
207  cyg_clock_to_counter(system_clockH, &amp;test_counterH);
208  cyg_alarm_create(test_counterH, test_alarm_func,
209         (cyg_addrword_t) &amp;how_many_alarms,
210         &amp;test_alarmH, &amp;test_alarm);
211  cyg_alarm_initialize(test_alarmH, cyg_current_time()+200, 200);
212
213  /* get in a loop in which we read the current time and
214     print it out, just to have something scrolling by */
215  for (;;) {
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;
228    }
229    cyg_thread_delay(30);
230  }
231 }
232
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)
237 {
238  ++*((unsigned *) data);
239 }</PRE
240 ></TD
241 ></TR
242 ></TABLE
243 ></DIV
244 ><P
245 >When you run this program (by typing <B
246 CLASS="COMMAND"
247 >continue</B
248 > at
249 the (<SPAN
250 CLASS="emphasis"
251 ><I
252 CLASS="EMPHASIS"
253 >gdb</I
254 ></SPAN
255 >) prompt) the output should look like
256 this:</P
257 ><TABLE
258 BORDER="5"
259 BGCOLOR="#E0E0F0"
260 WIDTH="70%"
261 ><TR
262 ><TD
263 ><PRE
264 CLASS="SCREEN"
265 >Starting program: <TT
266 CLASS="REPLACEABLE"
267 ><I
268 >BASE_DIR</I
269 ></TT
270 >/examples/simple-alarm.exe
271 Time is 0
272 Time is 30
273 Time is 60
274 Time is 90
275 Time is 120
276 Time is 150
277 Time is 180
278 Time is 210
279   --- alarm calls so far: 1
280 Time is 240
281 Time is 270
282 Time is 300
283 Time is 330
284 Time is 360
285 Time is 390
286 Time is 420
287   --- alarm calls so far: 2
288 Time is 450
289 Time is 480</PRE
290 ></TD
291 ></TR
292 ></TABLE
293 ><DIV
294 CLASS="NOTE"
295 ><BLOCKQUOTE
296 CLASS="NOTE"
297 ><P
298 ><B
299 >Note: </B
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
307 ></BLOCKQUOTE
308 ></DIV
309 ><P
310 >Here are a few things you might notice about this program:</P
311 ><P
312 ></P
313 ><UL
314 ><LI
315 ><P
316 >It used the <TT
317 CLASS="FUNCTION"
318 >cyg_real_time_clock()</TT
319 > function;
320 this always returns a handle to the default system real-time  clock. </P
321 ></LI
322 ><LI
323 ><P
324 >Clocks are based on  counters, so the function <TT
325 CLASS="FUNCTION"
326 >cyg_alarm_create()</TT
327 >
328 uses a counter handle. The program used the function
329 <TT
330 CLASS="FUNCTION"
331 >cyg_clock_to_counter()</TT
332 > to strip the clock handle
333 to the underlying counter handle. </P
334 ></LI
335 ><LI
336 ><P
337 >Once the alarm is created it is 
338 initialized with <TT
339 CLASS="FUNCTION"
340 >cyg_alarm_initialize()</TT
341 >, which
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
345 ></LI
346 ><LI
347 ><P
348 >The alarm handler function
349 <TT
350 CLASS="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
355 in the <I
356 CLASS="CITETITLE"
357 ><SPAN
358 CLASS="PRODUCTNAME"
359 >eCos</SPAN
360 > Reference Manual</I
361 >, in the chapter
362 <I
363 CLASS="CITETITLE"
364 >The <SPAN
365 CLASS="PRODUCTNAME"
366 >eCos</SPAN
367 > Kernel</I
368 >.</P
369 ></LI
370 ><LI
371 ><P
372 >There is a <SPAN
373 CLASS="emphasis"
374 ><I
375 CLASS="EMPHASIS"
376 >critical region</I
377 ></SPAN
378 > in this program:
379 the variable <TT
380 CLASS="LITERAL"
381 >how_many_alarms</TT
382 > is accessed in the
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,
385 access to <TT
386 CLASS="LITERAL"
387 >how_many_alarms</TT
388 > in the principal thread
389 is protected by calls to <TT
390 CLASS="FUNCTION"
391 >cyg_scheduler_lock()</TT
392 > and
393 <TT
394 CLASS="FUNCTION"
395 >cyg_scheduler_unlock()</TT
396 >. When the scheduler is
397 locked, the alarm handler will not be invoked, so the problem is
398 averted. </P
399 ></LI
400 ></UL
401 ></DIV
402 ></DIV
403 ><DIV
404 CLASS="NAVFOOTER"
405 ><HR
406 ALIGN="LEFT"
407 WIDTH="100%"><TABLE
408 SUMMARY="Footer navigation table"
409 WIDTH="100%"
410 BORDER="0"
411 CELLPADDING="0"
412 CELLSPACING="0"
413 ><TR
414 ><TD
415 WIDTH="33%"
416 ALIGN="left"
417 VALIGN="top"
418 ><A
419 HREF="sample-twothreads.html"
420 ACCESSKEY="P"
421 >Prev</A
422 ></TD
423 ><TD
424 WIDTH="34%"
425 ALIGN="center"
426 VALIGN="top"
427 ><A
428 HREF="ecos-user-guide.html"
429 ACCESSKEY="H"
430 >Home</A
431 ></TD
432 ><TD
433 WIDTH="33%"
434 ALIGN="right"
435 VALIGN="top"
436 ><A
437 HREF="the-ecos-configuration-tool.html"
438 ACCESSKEY="N"
439 >Next</A
440 ></TD
441 ></TR
442 ><TR
443 ><TD
444 WIDTH="33%"
445 ALIGN="left"
446 VALIGN="top"
447 >A Sample Program with Two Threads</TD
448 ><TD
449 WIDTH="34%"
450 ALIGN="center"
451 VALIGN="top"
452 ><A
453 HREF="user-guide-programming.html"
454 ACCESSKEY="U"
455 >Up</A
456 ></TD
457 ><TD
458 WIDTH="33%"
459 ALIGN="right"
460 VALIGN="top"
461 >The eCos Configuration Tool</TD
462 ></TR
463 ></TABLE
464 ></DIV
465 ></BODY
466 ></HTML
467 >