OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [doc/] [html/] [user-guide/] [clocks-and-alarm-handlers.html] - Blame information for rev 588

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 28 unneback
<!-- 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
>

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.