|
0
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // common/clock.cxx |
|
|
4 // |
|
|
5 // Clock class implementations |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): nickg |
|
|
33 // Contributors: nickg |
|
|
34 // Date: 1997-09-15 |
|
|
35 // Purpose: Clock class implementation |
|
|
36 // Description: This file contains the definitions of the counter, |
|
|
37 // clock and alarm class member functions that are common |
|
|
38 // to all clock implementations. |
|
|
39 // |
|
|
40 //####DESCRIPTIONEND#### |
|
|
41 // |
|
|
42 //========================================================================== |
|
|
43 |
|
|
44 #include <pkgconf/kernel.h> |
|
|
45 |
|
|
46 #include <cyg/kernel/ktypes.h> // base kernel types |
|
|
47 #include <cyg/infra/cyg_trac.h> // tracing macros |
|
|
48 #include <cyg/infra/cyg_ass.h> // assertion macros |
|
|
49 |
|
|
50 #include <cyg/kernel/clock.hxx> // our header |
|
|
51 |
|
|
52 #include <cyg/kernel/sched.hxx> // scheduler definitions |
|
|
53 #include <cyg/kernel/thread.hxx> // thread definitions |
|
|
54 #include <cyg/kernel/intr.hxx> // interrupt definitions |
|
|
55 |
|
|
56 #include <cyg/kernel/sched.inl> // scheduler inlines |
|
|
57 #include <cyg/kernel/clock.inl> // Clock inlines |
|
|
58 |
|
|
59 // ------------------------------------------------------------------------- |
|
|
60 // Static variables |
|
|
61 |
|
|
62 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK |
|
|
63 |
|
|
64 Cyg_Clock *Cyg_Clock::real_time_clock = NULL; // System real time clock |
|
|
65 |
|
|
66 #endif |
|
|
67 |
|
|
68 //========================================================================== |
|
|
69 // Constructor for counter object |
|
|
70 |
|
|
71 Cyg_Counter::Cyg_Counter( |
|
|
72 cyg_uint32 incr |
|
|
73 ) |
|
|
74 { |
|
|
75 CYG_REPORT_FUNCTION(); |
|
|
76 |
|
|
77 counter = 0; |
|
|
78 increment = incr; |
|
|
79 #if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) |
|
|
80 |
|
|
81 alarm_list = NULL; // Linear list of Alarms |
|
|
82 |
|
|
83 #elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST) |
|
|
84 |
|
|
85 for(cyg_ucount32 i=0; i < CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE; i++) { |
|
|
86 alarm_list[i] = NULL; |
|
|
87 } |
|
|
88 |
|
|
89 #else |
|
|
90 #error "No CYGIMP_KERNEL_COUNTERS_x_LIST config" |
|
|
91 #endif |
|
|
92 |
|
|
93 } |
|
|
94 |
|
|
95 // ------------------------------------------------------------------------- |
|
|
96 // Destructor for Counter object |
|
|
97 |
|
|
98 Cyg_Counter::~Cyg_Counter() |
|
|
99 { |
|
|
100 CYG_REPORT_FUNCTION(); |
|
|
101 |
|
|
102 |
|
|
103 } |
|
|
104 |
|
|
105 // ------------------------------------------------------------------------- |
|
|
106 // |
|
|
107 |
|
|
108 #ifdef CYGDBG_USE_ASSERTS |
|
|
109 |
|
|
110 bool Cyg_Counter::check_this( cyg_assert_class_zeal zeal) |
|
|
111 { |
|
|
112 // check that we have a non-NULL pointer first |
|
|
113 if( this == NULL ) return false; |
|
|
114 |
|
|
115 switch( zeal ) |
|
|
116 { |
|
|
117 case cyg_system_test: |
|
|
118 case cyg_extreme: |
|
|
119 case cyg_thorough: |
|
|
120 case cyg_quick: |
|
|
121 case cyg_trivial: |
|
|
122 case cyg_none: |
|
|
123 default: |
|
|
124 break; |
|
|
125 }; |
|
|
126 |
|
|
127 return true; |
|
|
128 } |
|
|
129 |
|
|
130 #endif |
|
|
131 |
|
|
132 // ------------------------------------------------------------------------- |
|
|
133 // Counter tick function |
|
|
134 |
|
|
135 void Cyg_Counter::tick( cyg_uint32 ticks ) |
|
|
136 { |
|
|
137 // CYG_REPORT_FUNCTION(); |
|
|
138 |
|
|
139 CYG_ASSERTCLASS( this, "Bad counter object" ); |
|
|
140 |
|
|
141 // Increment the counter in a loop so we process |
|
|
142 // each tick separately. This is easier than trying |
|
|
143 // to cope with a range of increments. |
|
|
144 |
|
|
145 while( ticks-- ) |
|
|
146 { |
|
|
147 Cyg_Scheduler::lock(); |
|
|
148 |
|
|
149 // increment the counter, note that it is |
|
|
150 // allowed to wrap. |
|
|
151 counter += increment; |
|
|
152 |
|
|
153 // now check for any expired alarms |
|
|
154 |
|
|
155 Cyg_Alarm **alarm_list_ptr; // pointer to list |
|
|
156 |
|
|
157 #if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) |
|
|
158 |
|
|
159 alarm_list_ptr = &alarm_list; |
|
|
160 |
|
|
161 #elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST) |
|
|
162 |
|
|
163 // With multiple lists, each one contains only the alarms |
|
|
164 // that will expire at a given tick modulo the list number. |
|
|
165 // So we only have a fraction of the alarms to check here. |
|
|
166 |
|
|
167 alarm_list_ptr = &(alarm_list[ |
|
|
168 (counter/increment) % CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] ); |
|
|
169 |
|
|
170 #else |
|
|
171 #error "No CYGIMP_KERNEL_COUNTERS_x_LIST config" |
|
|
172 #endif |
|
|
173 |
|
|
174 // Now that we have the list pointer, we can use common code for |
|
|
175 // both list oragnizations. |
|
|
176 |
|
|
177 while( *alarm_list_ptr != NULL ) |
|
|
178 { |
|
|
179 Cyg_Alarm *alarm = *alarm_list_ptr; |
|
|
180 |
|
|
181 CYG_ASSERTCLASS(alarm, "Bad alarm in counter list" ); |
|
|
182 |
|
|
183 if( alarm->trigger <= counter ) |
|
|
184 { |
|
|
185 // remove alarm from list |
|
|
186 *alarm_list_ptr = alarm->next; |
|
|
187 |
|
|
188 if( alarm->interval != 0 ) |
|
|
189 { |
|
|
190 // The alarm has a retrigger interval. |
|
|
191 // Reset the trigger time and requeue |
|
|
192 // the alarm. |
|
|
193 alarm->trigger += alarm->interval; |
|
|
194 add_alarm( alarm ); |
|
|
195 } |
|
|
196 else alarm->enabled = false; |
|
|
197 |
|
|
198 CYG_INSTRUMENT_ALARM( CALL, this, alarm ); |
|
|
199 |
|
|
200 // call alarm function |
|
|
201 alarm->alarm(alarm, alarm->data); |
|
|
202 |
|
|
203 // all done, loop |
|
|
204 } |
|
|
205 else break; |
|
|
206 } |
|
|
207 |
|
|
208 Cyg_Scheduler::unlock(); |
|
|
209 |
|
|
210 } |
|
|
211 |
|
|
212 } |
|
|
213 |
|
|
214 // ------------------------------------------------------------------------- |
|
|
215 // Add an alarm to this counter |
|
|
216 |
|
|
217 void Cyg_Counter::add_alarm( Cyg_Alarm *alarm ) |
|
|
218 { |
|
|
219 CYG_REPORT_FUNCTION(); |
|
|
220 |
|
|
221 CYG_ASSERTCLASS( this, "Bad counter object" ); |
|
|
222 CYG_ASSERTCLASS( alarm, "Bad alarm passed" ); |
|
|
223 |
|
|
224 Cyg_Scheduler::lock(); |
|
|
225 |
|
|
226 // set this now to allow an immediate handler call to manipulate |
|
|
227 // this alarm sensibly. |
|
|
228 alarm->enabled = true; |
|
|
229 |
|
|
230 // Check here for an alarm that triggers now or in the past and |
|
|
231 // call its alarm function immediately. |
|
|
232 if( alarm->trigger <= counter ) |
|
|
233 { |
|
|
234 CYG_INSTRUMENT_ALARM( CALL, this, alarm ); |
|
|
235 |
|
|
236 // call alarm function. Note that this is being |
|
|
237 // called here before the add_alarm has returned. |
|
|
238 // Note that this function may disable the alarm. |
|
|
239 |
|
|
240 alarm->alarm(alarm, alarm->data); |
|
|
241 |
|
|
242 // Note that this extra check on alarm->enabled is in case the |
|
|
243 // handler function disables this alarm! |
|
|
244 if( alarm->interval != 0 && alarm->enabled ) |
|
|
245 { |
|
|
246 // The alarm has a retrigger interval. |
|
|
247 // Reset the trigger interval and drop |
|
|
248 // through to queue it. |
|
|
249 alarm->trigger += alarm->interval; |
|
|
250 // ensure the next alarm time is in our future, and in phase |
|
|
251 // with the original time requested. |
|
|
252 alarm->synchronize(); |
|
|
253 } |
|
|
254 else |
|
|
255 { |
|
|
256 // The alarm is all done with, disable it |
|
|
257 // unlock and return. |
|
|
258 alarm->enabled = false; |
|
|
259 Cyg_Scheduler::unlock(); |
|
|
260 return; |
|
|
261 } |
|
|
262 } |
|
|
263 |
|
|
264 CYG_INSTRUMENT_ALARM( ADD, this, alarm ); |
|
|
265 |
|
|
266 { |
|
|
267 // Find the pointer to the relevant list _after_ a retrigger |
|
|
268 // alarm has been given its new trigger time. |
|
|
269 |
|
|
270 Cyg_Alarm **alarm_list_ptr; // pointer to list |
|
|
271 |
|
|
272 #if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) |
|
|
273 |
|
|
274 alarm_list_ptr = &alarm_list; |
|
|
275 |
|
|
276 #elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST) |
|
|
277 |
|
|
278 // Each alarm must go into the list that covers the tick that is |
|
|
279 // going to happen _after_ the trigger time (or at it if trigger |
|
|
280 // happens to fall on a tick. |
|
|
281 |
|
|
282 alarm_list_ptr = &(alarm_list[ |
|
|
283 ((alarm->trigger+increment-1)/increment) % |
|
|
284 CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] ); |
|
|
285 |
|
|
286 #else |
|
|
287 #error "No CYGIMP_KERNEL_COUNTERS_x_LIST config" |
|
|
288 #endif |
|
|
289 |
|
|
290 |
|
|
291 // Now that we have the list pointer, we can use common code for |
|
|
292 // both list oragnizations. |
|
|
293 |
|
|
294 while( *alarm_list_ptr != NULL ) |
|
|
295 { |
|
|
296 Cyg_Alarm *list_alarm = *alarm_list_ptr; |
|
|
297 |
|
|
298 CYG_ASSERTCLASS(list_alarm, "Bad alarm in counter list" ); |
|
|
299 |
|
|
300 // The alarms are in ascending trigger order. When we |
|
|
301 // find an alarm that is later than us, we go in front of |
|
|
302 // it. |
|
|
303 |
|
|
304 if( list_alarm->trigger > alarm->trigger ) break; |
|
|
305 else alarm_list_ptr = &list_alarm->next; |
|
|
306 } |
|
|
307 |
|
|
308 // Insert the new alarm at *alarm_list_ptr |
|
|
309 |
|
|
310 alarm->next = *alarm_list_ptr; |
|
|
311 *alarm_list_ptr = alarm; |
|
|
312 |
|
|
313 Cyg_Scheduler::unlock(); |
|
|
314 } |
|
|
315 } |
|
|
316 |
|
|
317 // ------------------------------------------------------------------------- |
|
|
318 // Remove an alarm from this counter |
|
|
319 |
|
|
320 void Cyg_Counter::rem_alarm( Cyg_Alarm *alarm ) |
|
|
321 { |
|
|
322 CYG_REPORT_FUNCTION(); |
|
|
323 |
|
|
324 CYG_ASSERTCLASS( this, "Bad counter object" ); |
|
|
325 CYG_ASSERTCLASS( alarm, "Bad alarm passed" ); |
|
|
326 |
|
|
327 Cyg_Alarm **alarm_list_ptr; // pointer to list |
|
|
328 |
|
|
329 #if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) |
|
|
330 |
|
|
331 alarm_list_ptr = &alarm_list; |
|
|
332 |
|
|
333 #elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST) |
|
|
334 |
|
|
335 alarm_list_ptr = &(alarm_list[ |
|
|
336 ((alarm->trigger+increment-1)/increment) % |
|
|
337 CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] ); |
|
|
338 |
|
|
339 #else |
|
|
340 #error "No CYGIMP_KERNEL_COUNTERS_x_LIST config" |
|
|
341 #endif |
|
|
342 |
|
|
343 // Now that we have the list pointer, we can use common code for |
|
|
344 // both list organizations. |
|
|
345 |
|
|
346 Cyg_Scheduler::lock(); |
|
|
347 |
|
|
348 CYG_INSTRUMENT_ALARM( REM, this, alarm ); |
|
|
349 |
|
|
350 while( *alarm_list_ptr != NULL ) |
|
|
351 { |
|
|
352 Cyg_Alarm *list_alarm = *alarm_list_ptr; |
|
|
353 |
|
|
354 CYG_ASSERTCLASS(list_alarm, "Bad alarm in counter list" ); |
|
|
355 |
|
|
356 if( list_alarm == alarm ) break; |
|
|
357 else alarm_list_ptr = &list_alarm->next; |
|
|
358 } |
|
|
359 |
|
|
360 // If the alarm was found, remove it from the list. |
|
|
361 if( *alarm_list_ptr != NULL ) |
|
|
362 { |
|
|
363 *alarm_list_ptr = alarm->next; |
|
|
364 alarm->enabled = false; |
|
|
365 } |
|
|
366 |
|
|
367 Cyg_Scheduler::unlock(); |
|
|
368 } |
|
|
369 |
|
|
370 //========================================================================== |
|
|
371 // Constructor for clock object |
|
|
372 |
|
|
373 Cyg_Clock::Cyg_Clock( |
|
|
374 cyg_resolution res |
|
|
375 ) |
|
|
376 { |
|
|
377 CYG_REPORT_FUNCTION(); |
|
|
378 |
|
|
379 resolution = res; |
|
|
380 } |
|
|
381 |
|
|
382 // ------------------------------------------------------------------------- |
|
|
383 // Destructor for Clock objects |
|
|
384 |
|
|
385 Cyg_Clock::~Cyg_Clock() |
|
|
386 { |
|
|
387 CYG_REPORT_FUNCTION(); |
|
|
388 |
|
|
389 } |
|
|
390 |
|
|
391 // ------------------------------------------------------------------------- |
|
|
392 // |
|
|
393 |
|
|
394 #ifdef CYGDBG_USE_ASSERTS |
|
|
395 |
|
|
396 bool Cyg_Clock::check_this( cyg_assert_class_zeal zeal) |
|
|
397 { |
|
|
398 // check that we have a non-NULL pointer first |
|
|
399 if( this == NULL ) return false; |
|
|
400 |
|
|
401 switch( zeal ) |
|
|
402 { |
|
|
403 case cyg_system_test: |
|
|
404 case cyg_extreme: |
|
|
405 case cyg_thorough: |
|
|
406 case cyg_quick: |
|
|
407 case cyg_trivial: |
|
|
408 case cyg_none: |
|
|
409 default: |
|
|
410 break; |
|
|
411 }; |
|
|
412 |
|
|
413 return true; |
|
|
414 } |
|
|
415 |
|
|
416 #endif |
|
|
417 |
|
|
418 //========================================================================== |
|
|
419 // Constructor for alarm object |
|
|
420 |
|
|
421 Cyg_Alarm::Cyg_Alarm( |
|
|
422 Cyg_Counter *c, // Attached to this counter |
|
|
423 cyg_alarm_fn *a, // Call-back function |
|
|
424 CYG_ADDRWORD d // Call-back data |
|
|
425 ) |
|
|
426 { |
|
|
427 CYG_REPORT_FUNCTION(); |
|
|
428 |
|
|
429 counter = c; |
|
|
430 alarm = a; |
|
|
431 data = d; |
|
|
432 trigger = 0; |
|
|
433 interval = 0; |
|
|
434 enabled = false; |
|
|
435 |
|
|
436 #if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) || defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST) |
|
|
437 next = NULL; |
|
|
438 #endif |
|
|
439 |
|
|
440 } |
|
|
441 |
|
|
442 Cyg_Alarm::Cyg_Alarm(){} |
|
|
443 |
|
|
444 // ------------------------------------------------------------------------- |
|
|
445 // Destructor |
|
|
446 |
|
|
447 Cyg_Alarm::~Cyg_Alarm() |
|
|
448 { |
|
|
449 CYG_REPORT_FUNCTION(); |
|
|
450 |
|
|
451 disable(); |
|
|
452 } |
|
|
453 |
|
|
454 // ------------------------------------------------------------------------- |
|
|
455 // |
|
|
456 |
|
|
457 #ifdef CYGDBG_USE_ASSERTS |
|
|
458 |
|
|
459 bool Cyg_Alarm::check_this( cyg_assert_class_zeal zeal) |
|
|
460 { |
|
|
461 // check that we have a non-NULL pointer first |
|
|
462 if( this == NULL ) return false; |
|
|
463 |
|
|
464 switch( zeal ) |
|
|
465 { |
|
|
466 case cyg_system_test: |
|
|
467 case cyg_extreme: |
|
|
468 case cyg_thorough: |
|
|
469 if( trigger != 0 && !enabled ) return false; |
|
|
470 case cyg_quick: |
|
|
471 case cyg_trivial: |
|
|
472 case cyg_none: |
|
|
473 default: |
|
|
474 break; |
|
|
475 }; |
|
|
476 |
|
|
477 return true; |
|
|
478 } |
|
|
479 |
|
|
480 #endif |
|
|
481 |
|
|
482 // ------------------------------------------------------------------------- |
|
|
483 // Initialize Alarm and enable |
|
|
484 |
|
|
485 void Cyg_Alarm::initialize( |
|
|
486 cyg_tick_count t, // Absolute trigger time |
|
|
487 cyg_tick_count i // Relative retrigger interval |
|
|
488 ) |
|
|
489 { |
|
|
490 CYG_REPORT_FUNCTION(); |
|
|
491 |
|
|
492 // If already enabled, remove from counter |
|
|
493 |
|
|
494 if( enabled ) counter->rem_alarm(this); |
|
|
495 |
|
|
496 CYG_INSTRUMENT_ALARM( INIT, this, 0 ); |
|
|
497 CYG_INSTRUMENT_ALARM( TRIGGER, |
|
|
498 ((cyg_uint32 *)&t)[0], |
|
|
499 ((cyg_uint32 *)&t)[1] ); |
|
|
500 CYG_INSTRUMENT_ALARM( INTERVAL, |
|
|
501 ((cyg_uint32 *)&i)[0], |
|
|
502 ((cyg_uint32 *)&i)[1] ); |
|
|
503 |
|
|
504 trigger = t; |
|
|
505 interval = i; |
|
|
506 |
|
|
507 counter->add_alarm(this); |
|
|
508 } |
|
|
509 |
|
|
510 // ------------------------------------------------------------------------- |
|
|
511 // Synchronize with a past alarm stream that had been disabled, |
|
|
512 // bring past times into synch, and the like. |
|
|
513 |
|
|
514 void |
|
|
515 Cyg_Alarm::synchronize( void ) |
|
|
516 { |
|
|
517 if( interval != 0 ) { |
|
|
518 // This expression sets the trigger to the next whole interval |
|
|
519 // at or after the current time. This means that alarms will |
|
|
520 // continue at the same intervals as if they had never been |
|
|
521 // disabled. The alternative would be to just set trigger to |
|
|
522 // (counter->counter + interval), but this is less satisfying |
|
|
523 // than preserving the original intervals. That behaviour can |
|
|
524 // always be obtained by using initialize() rather than |
|
|
525 // enable(), while the current behaviour would be more |
|
|
526 // difficult to achieve that way. |
|
|
527 cyg_tick_count d; |
|
|
528 d = counter->current_value() + interval - trigger; |
|
|
529 if ( d > interval ) { |
|
|
530 // then trigger was in the past, so resynchronize |
|
|
531 trigger += interval * ((d - 1) / interval ); |
|
|
532 } |
|
|
533 // otherwise, we were just set up, so no worries. |
|
|
534 } |
|
|
535 } |
|
|
536 |
|
|
537 // ------------------------------------------------------------------------- |
|
|
538 // Ensure alarm enabled |
|
|
539 |
|
|
540 void Cyg_Alarm::enable() |
|
|
541 { |
|
|
542 if( !enabled ) |
|
|
543 { |
|
|
544 // ensure the alarm time is in our future: |
|
|
545 synchronize(); |
|
|
546 enabled = true; |
|
|
547 counter->add_alarm(this); |
|
|
548 } |
|
|
549 } |
|
|
550 |
|
|
551 //========================================================================== |
|
|
552 // System clock object |
|
|
553 |
|
|
554 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK |
|
|
555 |
|
|
556 class Cyg_RealTimeClock |
|
|
557 : public Cyg_Clock |
|
|
558 { |
|
|
559 Cyg_Interrupt interrupt; |
|
|
560 |
|
|
561 static cyg_uint32 isr(cyg_vector vector, CYG_ADDRWORD data); |
|
|
562 |
|
|
563 static void dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data); |
|
|
564 |
|
|
565 Cyg_RealTimeClock(); |
|
|
566 |
|
|
567 static Cyg_RealTimeClock rtc; |
|
|
568 }; |
|
|
569 |
|
|
570 Cyg_Clock::cyg_resolution rtc_resolution = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION; |
|
|
571 |
|
|
572 //Cyg_RealTimeClock Cyg_RealTimeClock::rtc __attribute__((init_priority (1))); |
|
|
573 |
|
|
574 Cyg_RealTimeClock Cyg_RealTimeClock::rtc CYG_INIT_PRIORITY( CLOCK ); |
|
|
575 |
|
|
576 // ------------------------------------------------------------------------- |
|
|
577 |
|
|
578 Cyg_RealTimeClock::Cyg_RealTimeClock() |
|
|
579 : Cyg_Clock(rtc_resolution), |
|
|
580 interrupt(CYG_VECTOR_RTC, 1, (CYG_ADDRWORD)this, isr, dsr) |
|
|
581 { |
|
|
582 CYG_REPORT_FUNCTION(); |
|
|
583 |
|
|
584 HAL_CLOCK_INITIALIZE( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD ); |
|
|
585 |
|
|
586 interrupt.attach(); |
|
|
587 |
|
|
588 interrupt.unmask_interrupt(CYG_VECTOR_RTC); |
|
|
589 |
|
|
590 Cyg_Clock::real_time_clock = this; |
|
|
591 } |
|
|
592 |
|
|
593 // ------------------------------------------------------------------------- |
|
|
594 |
|
|
595 cyg_uint32 Cyg_RealTimeClock::isr(cyg_vector vector, CYG_ADDRWORD data) |
|
|
596 { |
|
|
597 // CYG_REPORT_FUNCTION(); |
|
|
598 |
|
|
599 CYG_INSTRUMENT_CLOCK( ISR, 0, 0); |
|
|
600 |
|
|
601 HAL_CLOCK_RESET( CYG_VECTOR_RTC, CYGNUM_KERNEL_COUNTERS_RTC_PERIOD ); |
|
|
602 |
|
|
603 Cyg_Interrupt::acknowledge_interrupt(CYG_VECTOR_RTC); |
|
|
604 |
|
|
605 return Cyg_Interrupt::CALL_DSR; |
|
|
606 } |
|
|
607 |
|
|
608 // ------------------------------------------------------------------------- |
|
|
609 |
|
|
610 void Cyg_RealTimeClock::dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data) |
|
|
611 { |
|
|
612 // CYG_REPORT_FUNCTION(); |
|
|
613 |
|
|
614 Cyg_RealTimeClock *rtc = (Cyg_RealTimeClock *)data; |
|
|
615 |
|
|
616 CYG_INSTRUMENT_CLOCK( TICK_START, |
|
|
617 rtc->current_value_lo(), |
|
|
618 rtc->current_value_hi()); |
|
|
619 |
|
|
620 rtc->tick( count ); |
|
|
621 |
|
|
622 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE |
|
|
623 #if 0 == CYG_SCHED_UNIQUE_PRIORITIES |
|
|
624 |
|
|
625 // If timeslicing is enabled, call the scheduler to |
|
|
626 // handle it. But not if we have unique priorities. |
|
|
627 |
|
|
628 Cyg_Scheduler::scheduler.timeslice(); |
|
|
629 |
|
|
630 #endif |
|
|
631 #endif |
|
|
632 |
|
|
633 CYG_INSTRUMENT_CLOCK( TICK_END, |
|
|
634 rtc->current_value_lo(), |
|
|
635 rtc->current_value_hi()); |
|
|
636 |
|
|
637 } |
|
|
638 |
|
|
639 #endif |
|
|
640 |
|
|
641 // ------------------------------------------------------------------------- |
|
|
642 // EOF common/clock.cxx |