1 //===========================================================================
5 // uITRON "C" test program for ixxx_yyy interrupt safe operators
7 //===========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //===========================================================================
41 //#####DESCRIPTIONBEGIN####
46 // Purpose: uITRON API testing
49 //####DESCRIPTIONEND####
51 //===========================================================================
53 #include <pkgconf/system.h>
54 #include <pkgconf/uitron.h> // uITRON setup CYGNUM_UITRON_SEMAS
55 // CYGPKG_UITRON et al
56 #include <cyg/infra/testcase.h> // testing infrastructure
58 #ifdef CYGPKG_UITRON // we DO want the uITRON package
60 #ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads
62 #ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls
64 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock
66 // we're OK if it's C++ or neither of those two is defined:
67 #if defined( __cplusplus ) || \
68 (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \
69 !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) )
71 // =================== TEST CONFIGURATION ===================
73 /* test configuration for enough tasks */ \
74 (CYGNUM_UITRON_TASKS >= 4) && \
75 (CYGNUM_UITRON_TASKS < 90) && \
76 (CYGNUM_UITRON_START_TASKS == 1) && \
77 ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \
78 CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \
80 /* the end of the large #if statement */ \
83 // ============================ END ============================
85 #include <cyg/hal/hal_arch.h>
86 #include <cyg/hal/hal_intr.h>
88 #include <cyg/infra/diag.h>
90 #include <cyg/compat/uitron/uit_func.h> // uITRON
91 #include <cyg/compat/uitron/uit_ifnc.h> // uITRON interrupt funcs
93 void set_interrupt_number( void );
95 unsigned int clock_interrupt = 0;
98 cyg_package_start( void )
101 CYG_TEST_INFO( "Calling cyg_uitron_start()" );
102 set_interrupt_number();
107 void task1( unsigned int arg );
108 void task2( unsigned int arg );
109 void task3( unsigned int arg );
110 void task4( unsigned int arg );
113 volatile int intercom = 0;
116 // Plan: replace (by direct intervention) the ISR and DSR of the regular
117 // timer interrupt; be sure to ack the clock intr using the appropriate hal
120 // The new ISR(s) will simply use the interrupt-safe signalling functions
121 // to control a 2nd task. Main task will check on the state thereof.
123 // We must test the ixxx_yyy() funcs with the scheduler already locked
124 // also, by direct sched calls on the KAPI. This must verify that the
125 // signal only happens when the scheduler unlocks.
127 // The 4 producer ops are:
128 // iwup_tsk ( ID tskid );
129 // isig_sem ( ID semid );
130 // iset_flg ( ID flgid, UINT setptn );
131 // isnd_msg ( ID mbxid, T_MSG *pk_msg );
133 // and return macros are:
134 // ret_wup( ID tskid );
137 // These ISRs perform the producer ops on all available objects in turn.
140 // Flags 1-4 with marching bit data; they'll all be set to 0x1ff eventually
141 // Mboxes 1-4 with an arbitrary pointer
152 #define ACK_CLOCK() CYG_MACRO_START \
153 HAL_CLOCK_RESET( CYGNUM_HAL_INTERRUPT_RTC, \
154 CYGNUM_KERNEL_COUNTERS_RTC_PERIOD ); \
155 HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_RTC ); \
158 #define CHECK_TID() CYG_MACRO_START \
161 ercd = get_tid( &my_tid ); \
162 CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); \
163 CYG_TEST_CHECK( 0 == my_tid, "tid not 0 in ISR" ); \
168 isr_wup_tsk( unsigned int vector, unsigned int data )
170 // Hit TASKS in range 2..4
176 if ( 5 == wtid ) wtid = 2;
181 isr_ret_wup( unsigned int vector, unsigned int data )
183 // Hit TASKS in range 2..4
188 if ( 6 == rwid ) rwid = 3;
193 isr_sig_sem( unsigned int vector, unsigned int data )
195 // Hit SEMAS in range 1..3
201 if ( ssid == 4 ) ssid = 1;
206 isr_set_flg( unsigned int vector, unsigned int data )
208 // Hit FLAGS in range 1..4
210 static int sfdata = 0xff;
213 iset_flg( sfid, sfdata );
215 if ( sfid == 5 ) sfid = 1;
217 // if ( sfdata == 0x20 ) sfdata = 1; // so that eventually all 0x1f set
222 isr_snd_msg( unsigned int vector, unsigned int data )
224 // Hit MBOXES in range 1..4
228 isnd_msg( smid, (T_MSG *)&smid );
230 if ( smid == 5 ) smid = 1;
235 void attach_isr( unsigned int (*isr)(unsigned int, unsigned int) );
236 void detach_isr( unsigned int (*isr)(unsigned int, unsigned int) );
238 void lock_sched( void );
239 void unlock_sched( void );
241 volatile int count = -1;
244 #define BIGDELAY 50000000
245 #define SMALLDELAY (BIGDELAY/SMALLLOOPS)
248 #define xxxLONGDELAY() \
251 for ( i = 0; i < BIGDELAY; i++ ) \
252 if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break; \
255 #define xxxDELAYLOCKSCHED() \
258 for ( j = 0; j < SMALLLOOPS; j++ ) { \
260 for ( i = 0; i < SMALLDELAY; i++ ) \
261 if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break; \
263 if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break; \
268 #define SMALLDELAYHW (5000000)
269 #define EVENTSHW ( 20)
270 #define SMALLDELAYSIM ( 100000)
271 #define EVENTSSIM ( 4)
273 #define SMALLDELAY (smalldelay)
274 #define EVENTS (events)
276 static int smalldelay = SMALLDELAYHW;
277 static int events = EVENTSHW;
279 #define LONGDELAY() do { \
281 do count++; while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS ); \
285 #define DELAYLOCKSCHED() \
291 for ( i = 0; i < SMALLDELAY; i++ ) { \
293 if ( wakeups[ 4 ] >= prewups[ 4 ] + EVENTS ) \
297 CYG_TEST_INFO(" [Still iterating, please wait....] "); \
298 } while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS ); \
308 volatile int wakeups[ 5 ] = { 0,0,0,0,0 };
309 volatile int prewups[ 5 ] = { 0,0,0,0,0 };
312 void task1( unsigned int arg )
317 CYG_TEST_INFO( "Task 1 running" );
319 if ( cyg_test_is_simulator ) {
325 // First test that dis_int() and ena_int() work for the clock interrupt
326 #ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS
327 ercd = ena_int( 123456789 ); // Hope this is large enough to error
328 CYG_TEST_CHECK( E_PAR == ercd, "ena_int bad ercd !E_PAR" );
329 ercd = dis_int( 123456789 );
330 CYG_TEST_CHECK( E_PAR == ercd, "dis_int bad ercd !E_PAR" );
333 // This may take too long on a sim...
334 // On the synthetic target this test cannot run reliably - the
335 // loop counting assumes exclusive access to the processor.
336 #ifndef CYGPKG_HAL_SYNTH
337 if ( ! cyg_test_is_simulator ) {
340 CYG_TEST_INFO( "Testing masking of clock interrupt" );
342 ercd = get_tim( &t1 );
343 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
345 // Wait for a tick. This loop acts as a synchronizer for the loop
346 // below, ensuring that it starts just after a tick.
347 for ( loops = 0; loops < 10000000; loops++ ) {
348 ercd = get_tim( &t2 );
349 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
353 // Wait for next tick. Reset loops counter so we get the
354 // approximate loop count of one clock tick.
355 for ( loops = 0; loops < 10000000; loops++ ) {
356 ercd = get_tim( &t1 );
357 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
362 // save how many loops could be executed in one tick. Multiply
363 // with 3 : we run loops in pairs below and add the time of
364 // one extra to avoid small variations to trigger failures.
365 intercom = loops * 3;
367 ercd = ena_int( clock_interrupt ); // was initialized already
368 CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" );
370 ercd = get_tim( &t1 );
371 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
374 for ( loops = intercom; loops > 0; loops-- ) {
375 ercd = get_tim( &t2 );
376 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
380 CYG_TEST_CHECK( 0 < loops, "No first tick" );
382 for ( ; loops > 0; loops-- ) {
383 ercd = get_tim( &t1 );
384 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
388 CYG_TEST_CHECK( 0 < loops, "No second tick" );
390 // The PowerPC cannot disable the timer interrupt (separately).
391 #ifndef CYGPKG_HAL_POWERPC
392 ercd = dis_int( clock_interrupt ); // was initialized already
393 CYG_TEST_CHECK( E_OK == ercd, "dis_int bad ercd" );
395 ercd = get_tim( &t1 );
396 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
398 // Wait for a tick (should not happen)
399 for ( loops = intercom; loops > 0; loops-- ) {
400 ercd = get_tim( &t2 );
401 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
405 CYG_TEST_CHECK( 0 == loops, "A tick occured - should be masked" );
406 CYG_TEST_CHECK( t1 == t2, "Times are different" );
408 // Now enable it again and ensure all is well:
409 ercd = ena_int( clock_interrupt );
410 CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" );
413 ercd = get_tim( &t1 );
414 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
417 for ( loops = intercom; loops > 0; loops-- ) {
418 ercd = get_tim( &t2 );
419 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
423 CYG_TEST_CHECK( 0 < loops, "No first tick" );
425 for ( ; loops > 0; loops-- ) {
426 ercd = get_tim( &t1 );
427 CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
431 CYG_TEST_CHECK( 0 < loops, "No second tick" );
433 CYG_TEST_PASS( "dis_int(), ena_int() OK" );
439 ercd = get_tid( &scratch );
440 CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
441 CYG_TEST_CHECK( 1 == scratch, "tid not 1" );
443 // start all other tasks (our prio is 1 by default)
444 ercd = sta_tsk( 2, 222 );
445 CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 2 bad ercd" );
446 ercd = sta_tsk( 3, 333 );
447 CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 3 bad ercd" );
448 ercd = sta_tsk( 4, 444 );
449 CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 4 bad ercd" );
450 // drop pri of other tasks all to 5
451 ercd = chg_pri( 2, 5 );
452 CYG_TEST_CHECK( E_OK == ercd, "chg_pri 2 bad ercd" );
453 ercd = chg_pri( 3, 5 );
454 CYG_TEST_CHECK( E_OK == ercd, "chg_pri 3 bad ercd" );
455 ercd = chg_pri( 4, 5 );
456 CYG_TEST_CHECK( E_OK == ercd, "chg_pri 4 bad ercd" );
460 // Drop our prio to lower; they will run in turn until asleep
461 ercd = chg_pri( 1, 6 );
462 CYG_TEST_CHECK( E_OK == ercd, "chg_pri 1 (self) bad ercd" );
468 CYG_TEST_INFO( " (toggling scheduler lock) " );
470 CYG_TEST_INFO( " (unlocked scheduler) " );
473 CYG_TEST_CHECK( 0 == wakeups[0], "init: Wakeups[0] hit" );
474 CYG_TEST_CHECK( 0 == wakeups[1], "init: Wakeups[1] hit" );
475 CYG_TEST_CHECK( prewups[2] == wakeups[2], "init: Wakeups[2] hit" );
476 CYG_TEST_CHECK( prewups[3] == wakeups[3], "init: Wakeups[3] hit" );
477 CYG_TEST_CHECK( prewups[4] == wakeups[4], "init: Wakeups[4] hit" );
479 // -------- TIMERS AND TIMESLICING DISABLED ---------
480 // install an isr that will wake them all up in turn
481 attach_isr( isr_wup_tsk );
483 detach_isr( isr_wup_tsk );
484 // -------- timers and timeslicing ENABLED ---------
486 CYG_TEST_CHECK( 0 == wakeups[0], "iwup_tsk: Wakeups[0] hit" );
487 CYG_TEST_CHECK( 0 == wakeups[1], "iwup_tsk: Wakeups[1] hit" );
488 CYG_TEST_CHECK( prewups[2] < wakeups[2], "iwup_tsk: Wakeups[2] not hit" );
489 CYG_TEST_CHECK( prewups[3] < wakeups[3], "iwup_tsk: Wakeups[3] not hit" );
490 CYG_TEST_CHECK( prewups[4] < wakeups[4], "iwup_tsk: Wakeups[4] not hit" );
491 diag_printf( "INFO:<(fg loops %10d) thread wakeups : %2d %2d %2d >\n", count,
492 wakeups[2] - prewups[2],
493 wakeups[3] - prewups[3],
494 wakeups[4] - prewups[4] );
495 prewups[2] = wakeups[2];
496 prewups[3] = wakeups[3];
497 prewups[4] = wakeups[4];
499 // -------- TIMERS AND TIMESLICING DISABLED ---------
500 // install an isr that will wake them all up in turn
501 attach_isr( isr_ret_wup );
503 detach_isr( isr_ret_wup );
504 // -------- timers and timeslicing ENABLED ---------
506 CYG_TEST_CHECK( 0 == wakeups[0], "ret_wup: Wakeups[0] hit" );
507 CYG_TEST_CHECK( 0 == wakeups[1], "ret_wup: Wakeups[1] hit" );
508 CYG_TEST_CHECK( prewups[2] < wakeups[2], "ret_wup: Wakeups[2] not hit" );
509 CYG_TEST_CHECK( prewups[3] < wakeups[3], "ret_wup: Wakeups[3] not hit" );
510 CYG_TEST_CHECK( prewups[4] < wakeups[4], "ret_wup: Wakeups[4] not hit" );
511 diag_printf( "INFO:<(fg loops %10d) thread ret_wups: %2d %2d %2d >\n", count,
512 wakeups[2] - prewups[2],
513 wakeups[3] - prewups[3],
514 wakeups[4] - prewups[4] );
515 prewups[2] = wakeups[2];
516 prewups[3] = wakeups[3];
517 prewups[4] = wakeups[4];
519 // move them on to waiting for a semaphore
522 CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(2) bad ercd" );
524 CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(3) bad ercd" );
526 CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(4) bad ercd" );
528 CYG_TEST_CHECK( 0 == wakeups[0], "wup_tsk: Wakeups[0] hit" );
529 CYG_TEST_CHECK( 0 == wakeups[1], "wup_tsk: Wakeups[1] hit" );
530 CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "wup_tsk: Wakeups[2] not hit" );
531 CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "wup_tsk: Wakeups[3] not hit" );
532 CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "wup_tsk: Wakeups[4] not hit" );
533 prewups[2] = wakeups[2];
534 prewups[3] = wakeups[3];
535 prewups[4] = wakeups[4];
537 // -------- TIMERS AND TIMESLICING DISABLED ---------
538 // install an isr that will wake them all up in turn
539 attach_isr( isr_sig_sem );
541 detach_isr( isr_sig_sem );
542 // -------- timers and timeslicing ENABLED ---------
544 CYG_TEST_CHECK( 0 == wakeups[0], "isig_sem: Wakeups[0] hit" );
545 CYG_TEST_CHECK( 0 == wakeups[1], "isig_sem: Wakeups[1] hit" );
546 CYG_TEST_CHECK( prewups[2] < wakeups[2], "isig_sem: Wakeups[2] not hit" );
547 CYG_TEST_CHECK( prewups[3] < wakeups[3], "isig_sem: Wakeups[3] not hit" );
548 CYG_TEST_CHECK( prewups[4] < wakeups[4], "isig_sem: Wakeups[4] not hit" );
549 diag_printf( "INFO:<(fg loops %10d) semaphore waits: %2d %2d %2d >\n", count,
550 wakeups[2] - prewups[2],
551 wakeups[3] - prewups[3],
552 wakeups[4] - prewups[4] );
553 prewups[2] = wakeups[2];
554 prewups[3] = wakeups[3];
555 prewups[4] = wakeups[4];
557 // move them on to waiting for a flag
560 CYG_TEST_CHECK( E_OK == ercd, "sig_sem(1) bad ercd" );
562 CYG_TEST_CHECK( E_OK == ercd, "sig_sem(2) bad ercd" );
564 CYG_TEST_CHECK( E_OK == ercd, "sig_sem(3) bad ercd" );
566 CYG_TEST_CHECK( 0 == wakeups[0], "sig_sem: Wakeups[0] hit" );
567 CYG_TEST_CHECK( 0 == wakeups[1], "sig_sem: Wakeups[1] hit" );
568 CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "sig_sem: Wakeups[2] not hit" );
569 CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "sig_sem: Wakeups[3] not hit" );
570 CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "sig_sem: Wakeups[4] not hit" );
571 prewups[2] = wakeups[2];
572 prewups[3] = wakeups[3];
573 prewups[4] = wakeups[4];
575 // -------- TIMERS AND TIMESLICING DISABLED ---------
576 // install an isr that will wake them all up in turn
577 attach_isr( isr_set_flg );
579 detach_isr( isr_set_flg );
580 // -------- timers and timeslicing ENABLED ---------
582 CYG_TEST_CHECK( 0 == wakeups[0], "iset_flg: Wakeups[0] hit" );
583 CYG_TEST_CHECK( 0 == wakeups[1], "iset_flg: Wakeups[1] hit" );
584 CYG_TEST_CHECK( prewups[2] < wakeups[2], "iset_flg: Wakeups[2] not hit" );
585 CYG_TEST_CHECK( prewups[3] < wakeups[3], "iset_flg: Wakeups[3] not hit" );
586 CYG_TEST_CHECK( prewups[4] < wakeups[4], "iset_flg: Wakeups[4] not hit" );
587 diag_printf( "INFO:<(fg loops %10d) flag waits/sets: %2d %2d %2d >\n", count,
588 wakeups[2] - prewups[2],
589 wakeups[3] - prewups[3],
590 wakeups[4] - prewups[4] );
591 prewups[2] = wakeups[2];
592 prewups[3] = wakeups[3];
593 prewups[4] = wakeups[4];
595 // move them on to waiting for a message box
597 ercd = set_flg( 2, 0xfff );
598 CYG_TEST_CHECK( E_OK == ercd, "set_flg(2) bad ercd" );
599 ercd = set_flg( 3, 0xfff );
600 CYG_TEST_CHECK( E_OK == ercd, "set_flg(3) bad ercd" );
601 ercd = set_flg( 4, 0xfff );
602 CYG_TEST_CHECK( E_OK == ercd, "set_flg(4) bad ercd" );
604 CYG_TEST_CHECK( 0 == wakeups[0], "set_flg: Wakeups[0] hit" );
605 CYG_TEST_CHECK( 0 == wakeups[1], "set_flg: Wakeups[1] hit" );
606 CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "set_flg: Wakeups[2] not hit" );
607 CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "set_flg: Wakeups[3] not hit" );
608 CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "set_flg: Wakeups[4] not hit" );
609 prewups[2] = wakeups[2];
610 prewups[3] = wakeups[3];
611 prewups[4] = wakeups[4];
613 // -------- TIMERS AND TIMESLICING DISABLED ---------
614 // install an isr that will wake them all up in turn
615 attach_isr( isr_snd_msg );
617 detach_isr( isr_snd_msg );
618 // -------- timers and timeslicing ENABLED ---------
620 CYG_TEST_CHECK( 0 == wakeups[0], "isnd_msg: Wakeups[0] hit" );
621 CYG_TEST_CHECK( 0 == wakeups[1], "isnd_msg: Wakeups[1] hit" );
622 CYG_TEST_CHECK( prewups[2] < wakeups[2], "isnd_msg: Wakeups[2] not hit" );
623 CYG_TEST_CHECK( prewups[3] < wakeups[3], "isnd_msg: Wakeups[3] not hit" );
624 CYG_TEST_CHECK( prewups[4] < wakeups[4], "isnd_msg: Wakeups[4] not hit" );
625 diag_printf( "INFO:<(fg loops %10d) message rec'pts: %2d %2d %2d >\n", count,
626 wakeups[2] - prewups[2],
627 wakeups[3] - prewups[3],
628 wakeups[4] - prewups[4] );
629 prewups[2] = wakeups[2];
630 prewups[3] = wakeups[3];
631 prewups[4] = wakeups[4];
633 // move them on to exiting, all done
635 // then we are about to exit
639 ercd = snd_msg( 2, (T_MSG *)&intercom );
640 CYG_TEST_CHECK( E_OK == ercd, "snd_msg(2) bad ercd" );
641 ercd = snd_msg( 3, (T_MSG *)&intercom );
642 CYG_TEST_CHECK( E_OK == ercd, "snd_msg(3) bad ercd" );
643 ercd = snd_msg( 4, (T_MSG *)&intercom );
644 CYG_TEST_CHECK( E_OK == ercd, "snd_msg(4) bad ercd" );
646 CYG_TEST_CHECK( 0 == wakeups[0], "snd_msg: Wakeups[0] hit" );
647 CYG_TEST_CHECK( 0 == wakeups[1], "snd_msg: Wakeups[1] hit" );
648 CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "snd_msg: Wakeups[2] not hit" );
649 CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "snd_msg: Wakeups[3] not hit" );
650 CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "snd_msg: Wakeups[4] not hit" );
651 prewups[2] = wakeups[2];
652 prewups[3] = wakeups[3];
653 prewups[4] = wakeups[4];
655 CYG_TEST_PASS( "Tested ISR invoked uITRON functions" );
657 } while ( 0 < --loops );
659 CYG_TEST_EXIT( "All done" );
671 switch ( intercom ) {
674 CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (doing nothing)" );
678 CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" );
682 ercd = wai_sem( n-1 ); // 1..3 for semas
683 CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" );
687 ercd = wai_flg( &z, n, (1<<n), TWF_CLR | TWF_ANDW );
688 CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" );
689 CYG_TEST_CHECK( z & (1<<n), "Flag bit not set" );
693 ercd = rcv_msg( &pk_msg, n );
694 CYG_TEST_CHECK( E_OK == ercd, "rcv_msg bad ercd" );
695 CYG_TEST_CHECK( pk_msg, "rcv_msg NULL msg" );
704 void task2( unsigned int arg )
707 CYG_TEST_INFO( "Task 2 running" );
708 ercd = get_tid( &scratch );
709 CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
710 CYG_TEST_CHECK( 2 == scratch, "tid not 2" );
712 CYG_TEST_FAIL( "Task 2 arg not 222" );
714 CYG_TEST_INFO( "Task 2 exiting" );
716 CYG_TEST_FAIL( "Task 2 failed to exit" );
719 void task3( unsigned int arg )
722 CYG_TEST_INFO("Task 3 running");
723 ercd = get_tid( &scratch );
724 CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
725 CYG_TEST_CHECK( 3 == scratch, "tid not 3" );
727 CYG_TEST_FAIL( "Task 3 arg not 333" );
729 CYG_TEST_INFO( "Task 3 exiting" );
731 CYG_TEST_FAIL( "Task 3 failed to exit" );
734 void task4( unsigned int arg )
737 CYG_TEST_INFO("Task 4 running");
738 ercd = get_tid( &scratch );
739 CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
740 CYG_TEST_CHECK( 4 == scratch, "tid not 4" );
742 CYG_TEST_FAIL( "Task 4 arg not 444" );
744 CYG_TEST_INFO( "Task 4 exiting" );
746 CYG_TEST_FAIL( "Task 4 failed to exit" );
749 // ------------------------------------------------------------------------
750 // Start of C++ aware portion, so to speak.
753 #include <cyg/hal/hal_intr.h>
754 #include <cyg/kernel/intr.hxx>
755 #include <cyg/kernel/clock.hxx>
756 #include <cyg/kernel/sched.hxx>
757 #include <cyg/kernel/sched.inl>
759 void set_interrupt_number( void )
761 clock_interrupt = CYGNUM_HAL_INTERRUPT_RTC;
764 // This snippet stolen from kernel/.../clock.cxx to be able to detach
765 // the RTC from its interrupt source.
766 class Cyg_RealTimeClock
770 Cyg_Interrupt interrupt;
772 static cyg_uint32 isr(cyg_vector vector, CYG_ADDRWORD data);
774 static void dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data);
780 static Cyg_Interrupt uit_intr(
781 (unsigned)CYGNUM_HAL_INTERRUPT_RTC, // Vector to attach to
783 (unsigned)0, // Data pointer
784 &isr_wup_tsk, // Interrupt Service Routine
785 &cyg_uitron_dsr // Deferred Service Routine
789 attach_isr( unsigned int (*isr)(unsigned int, unsigned int) )
793 Cyg_RealTimeClock *prtc = (Cyg_RealTimeClock *)Cyg_Clock::real_time_clock;
794 HAL_DISABLE_INTERRUPTS(old_ints);
795 HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC );
796 prtc->interrupt.detach();
797 #ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
798 // Only check that the vector was cleared when there's a specific
799 // vector for the RTC. In chain mode, other interrupt handlers
800 // may prevent the shared vector from being cleared when detaching
801 // the RTC ISR, and this assertion fails.
802 HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
803 CYG_TEST_CHECK( !inuse, "Failed to detach clock ISR" );
805 uit_intr = Cyg_Interrupt(
806 CYGNUM_HAL_INTERRUPT_RTC, // Vector to attach to
809 isr, // Interrupt Service Routine
810 cyg_uitron_dsr // Deferred Service Routine
813 HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
814 CYG_TEST_CHECK( inuse, "Failed to attach new ISR" );
816 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC );
817 HAL_RESTORE_INTERRUPTS(old_ints);
821 detach_isr( unsigned int (*isr)(unsigned int, unsigned int) )
825 Cyg_RealTimeClock *prtc = (Cyg_RealTimeClock *)Cyg_Clock::real_time_clock;
826 HAL_DISABLE_INTERRUPTS(old_ints);
827 HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC );
829 #ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
830 // See comment above in attach_isr.
831 HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
832 CYG_TEST_CHECK( !inuse, "Failed to detach my ISR" );
834 prtc->interrupt.attach();
835 HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
836 CYG_TEST_CHECK( inuse, "Failed to attach clock ISR" );
838 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC );
839 HAL_RESTORE_INTERRUPTS(old_ints);
847 Cyg_Scheduler::lock();
848 l = Cyg_Scheduler::get_sched_lock();
849 CYG_TEST_CHECK( 0 < l, "lock: Sched not locked" );
850 CYG_TEST_CHECK( 2 > l, "lock: Sched already locked" );
857 l = Cyg_Scheduler::get_sched_lock();
858 CYG_TEST_CHECK( 0 < l, "unlock: Sched not locked" );
859 CYG_TEST_CHECK( 2 > l, "unlock: Sched already locked" );
860 Cyg_Scheduler::unlock();
864 #else // not enough (or too many) uITRON objects configured in
865 #define N_A_MSG "not enough uITRON objects to run test"
866 #endif // not enough (or too many) uITRON objects configured in
867 #else // not C++ and some C++ specific options enabled
868 #define N_A_MSG "C++ specific options selected but this is C"
869 #endif // not C++ and some C++ specific options enabled
870 #else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it
871 #define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK"
872 #endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it
873 #else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it
874 #define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER"
875 #endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it
876 #else // ! CYGIMP_THREAD_PRIORITY - can't test without it
877 #define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE"
878 #endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it
879 #else // ! CYGPKG_UITRON
880 #define N_A_MSG "uITRON Compatibility layer disabled"
881 #endif // CYGPKG_UITRON
888 CYG_TEST_NA( N_A_MSG );
890 #endif // N_A_MSG defined ie. we are N/A.