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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [compat/] [uitron/] [current/] [tests/] [testintr.cxx] - Blame information for rev 856

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

Line No. Rev Author Line
1 786 skrzyp
//===========================================================================
2
//
3
//      testintr.c
4
//
5
//      uITRON "C" test program for ixxx_yyy interrupt safe operators
6
//
7
//===========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//===========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   hmt
43
// Contributors:hmt
44
// Date:        1998-08-20
45
// Purpose:     uITRON API testing
46
// Description: 
47
//
48
//####DESCRIPTIONEND####
49
//
50
//===========================================================================
51
 
52
#include <pkgconf/system.h>
53
#include <pkgconf/uitron.h>             // uITRON setup CYGNUM_UITRON_SEMAS
54
                                        // CYGPKG_UITRON et al
55
#include <cyg/infra/testcase.h>         // testing infrastructure
56
 
57
#ifdef CYGPKG_UITRON                    // we DO want the uITRON package
58
 
59
#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE      // we DO want prioritized threads
60
 
61
#ifdef CYGFUN_KERNEL_THREADS_TIMER      // we DO want timout-able calls
62
 
63
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK     // we DO want the realtime clock
64
 
65
// we're OK if it's C++ or neither of those two is defined:
66
#if defined( __cplusplus ) || \
67
    (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \
68
     !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) )
69
 
70
// =================== TEST CONFIGURATION ===================
71
#if \
72
    /* test configuration for enough tasks */                      \
73
    (CYGNUM_UITRON_TASKS >= 4)                                  && \
74
    (CYGNUM_UITRON_TASKS < 90)                                  && \
75
    (CYGNUM_UITRON_START_TASKS == 1)                            && \
76
    ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) ||               \
77
      CYGNUM_UITRON_TASKS_INITIALLY >= 4             )          && \
78
                                                                   \
79
    /* the end of the large #if statement */                       \
80
    1
81
 
82
// ============================ END ============================
83
 
84
#include <cyg/hal/hal_arch.h>
85
#include <cyg/hal/hal_intr.h>
86
 
87
#include <cyg/infra/diag.h>
88
 
89
#include <cyg/compat/uitron/uit_func.h> // uITRON
90
#include <cyg/compat/uitron/uit_ifnc.h> // uITRON interrupt funcs
91
 
92
void set_interrupt_number( void );
93
 
94
unsigned int clock_interrupt = 0;
95
 
96
externC void
97
cyg_package_start( void )
98
{
99
    CYG_TEST_INIT();
100
    CYG_TEST_INFO( "Calling cyg_uitron_start()" );
101
    set_interrupt_number();
102
    cyg_uitron_start();
103
}
104
 
105
extern "C" {
106
    void task1( unsigned int arg );
107
    void task2( unsigned int arg );
108
    void task3( unsigned int arg );
109
    void task4( unsigned int arg );
110
}
111
 
112
volatile int intercom = 0;
113
INT scratch = 0;
114
 
115
// Plan: replace (by direct intervention) the ISR and DSR of the regular
116
// timer interrupt; be sure to ack the clock intr using the appropriate hal
117
// macros.
118
// 
119
// The new ISR(s) will simply use the interrupt-safe signalling functions
120
// to control a 2nd task.  Main task will check on the state thereof.
121
//
122
// We must test the ixxx_yyy() funcs with the scheduler already locked
123
// also, by direct sched calls on the KAPI.  This must verify that the
124
// signal only happens when the scheduler unlocks.
125
// 
126
// The 4 producer ops are:
127
//     iwup_tsk ( ID tskid );
128
//     isig_sem ( ID semid );
129
//     iset_flg ( ID flgid, UINT setptn );
130
//     isnd_msg ( ID mbxid, T_MSG *pk_msg );
131
//
132
// and return macros are:
133
//     ret_wup( ID tskid );
134
//     ret_int();
135
//
136
// These ISRs perform the producer ops on all available objects in turn.
137
// Tasks 2-4
138
// Semas 1-4
139
// Flags 1-4 with marching bit data; they'll all be set to 0x1ff eventually
140
// Mboxes 1-4 with an arbitrary pointer
141
 
142
enum {
143
    NOTHING = 0,
144
    SLP,
145
    SEM,
146
    FLG,
147
    MBX,
148
    EXIT
149
};
150
 
151
#define ACK_CLOCK() CYG_MACRO_START                             \
152
    HAL_CLOCK_RESET( CYGNUM_HAL_INTERRUPT_RTC,                  \
153
                     CYGNUM_KERNEL_COUNTERS_RTC_PERIOD );       \
154
    HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_RTC );      \
155
CYG_MACRO_END
156
 
157
#define CHECK_TID() CYG_MACRO_START                     \
158
    int my_tid;                                         \
159
    ER ercd;                                            \
160
    ercd = get_tid( &my_tid );                          \
161
    CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); \
162
    CYG_TEST_CHECK( 0 == my_tid, "tid not 0 in ISR" );  \
163
CYG_MACRO_END
164
 
165
 
166
unsigned int
167
isr_wup_tsk( unsigned int vector, unsigned int data )
168
{
169
    // Hit TASKS in range 2..4
170
    static int wtid = 2;
171
    ACK_CLOCK();
172
    CHECK_TID();
173
    iwup_tsk( wtid );
174
    wtid++;
175
    if ( 5 == wtid ) wtid = 2;
176
    ret_int();
177
}
178
 
179
unsigned int
180
isr_ret_wup( unsigned int vector, unsigned int data )
181
{
182
    // Hit TASKS in range 2..4
183
    static int rwid = 2;
184
    ACK_CLOCK();
185
    CHECK_TID();
186
    rwid++;
187
    if ( 6 == rwid ) rwid = 3;
188
    ret_wup( rwid - 1 );
189
}
190
 
191
unsigned int
192
isr_sig_sem( unsigned int vector, unsigned int data )
193
{
194
    // Hit SEMAS in range 1..3
195
    static int ssid = 1;
196
    ACK_CLOCK();
197
    CHECK_TID();
198
    isig_sem( ssid );
199
    ssid++;
200
    if ( ssid == 4 ) ssid = 1;
201
    ret_int();
202
}
203
 
204
unsigned int
205
isr_set_flg( unsigned int vector, unsigned int data )
206
{
207
    // Hit FLAGS in range 1..4
208
    static int sfid = 1;
209
    static int sfdata = 0xff;
210
    ACK_CLOCK();
211
    CHECK_TID();
212
    iset_flg( sfid, sfdata );
213
    sfid++;
214
    if ( sfid == 5 ) sfid = 1;
215
//    sfdata <<= 1;
216
//    if ( sfdata == 0x20 ) sfdata = 1; // so that eventually all 0x1f set
217
    ret_int();
218
}
219
 
220
unsigned int
221
isr_snd_msg( unsigned int vector, unsigned int data )
222
{
223
    // Hit MBOXES in range 1..4
224
    static int smid = 1;
225
    ACK_CLOCK();
226
    CHECK_TID();
227
    isnd_msg( smid, (T_MSG *)&smid );
228
    smid++;
229
    if ( smid == 5 ) smid = 1;
230
    ret_int();
231
}
232
 
233
 
234
void attach_isr( unsigned int (*isr)(unsigned int, unsigned int) );
235
void detach_isr( unsigned int (*isr)(unsigned int, unsigned int) );
236
 
237
void lock_sched( void );
238
void unlock_sched( void );
239
 
240
volatile int count = -1;
241
 
242
/*
243
#define BIGDELAY  50000000
244
#define SMALLDELAY (BIGDELAY/SMALLLOOPS)
245
#define SMALLLOOPS 3
246
 
247
#define xxxLONGDELAY()                                     \
248
do {                                                    \
249
    int i;                                              \
250
    for ( i = 0; i < BIGDELAY; i++ )                    \
251
        if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break;  \
252
} while ( 0 )
253
 
254
#define xxxDELAYLOCKSCHED()                                        \
255
do {                                                            \
256
    int i,j;                                                    \
257
    for ( j = 0; j < SMALLLOOPS; j++ ) {                        \
258
        lock_sched();                                           \
259
        for ( i = 0; i < SMALLDELAY; i++ )                      \
260
            if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break;      \
261
        unlock_sched();                                         \
262
        if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break;          \
263
    }                                                           \
264
} while ( 0 )
265
*/
266
 
267
#define SMALLDELAYHW  (5000000)
268
#define EVENTSHW      (     20)
269
#define SMALLDELAYSIM ( 100000)
270
#define EVENTSSIM     (      4)
271
 
272
#define SMALLDELAY (smalldelay)
273
#define EVENTS     (events)
274
 
275
static int smalldelay = SMALLDELAYHW;
276
static int events     = EVENTSHW;
277
 
278
#define LONGDELAY() do {                                        \
279
    count = 0;                                                  \
280
    do count++; while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS ); \
281
} while ( 0 )
282
 
283
 
284
#define DELAYLOCKSCHED()                                              \
285
do {                                                                  \
286
    count = 0;                                                        \
287
    int i;                                                            \
288
    do {                                                              \
289
        lock_sched();                                                 \
290
        for ( i = 0; i < SMALLDELAY; i++ ) {                          \
291
            count++;                                                  \
292
            if ( wakeups[ 4 ] >= prewups[ 4 ] + EVENTS )              \
293
                break;                                                \
294
        }                                                             \
295
        unlock_sched();                                               \
296
        CYG_TEST_INFO("  [Still iterating, please wait....]  ");      \
297
    } while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS );                 \
298
} while ( 0 )
299
 
300
#define DELAY()                                 \
301
if ( 1 & loops )                                \
302
    DELAYLOCKSCHED();                           \
303
else                                            \
304
    LONGDELAY();
305
 
306
 
307
volatile int wakeups[ 5 ] = { 0,0,0,0,0 };
308
volatile int prewups[ 5 ] = { 0,0,0,0,0 };
309
 
310
 
311
void task1( unsigned int arg )
312
{
313
    ER ercd;
314
    int loops;
315
 
316
    CYG_TEST_INFO( "Task 1 running" );
317
 
318
    if ( cyg_test_is_simulator ) {
319
        // take less time
320
        events     = EVENTSSIM;
321
    }
322
 
323
 
324
    // First test that dis_int() and ena_int() work for the clock interrupt
325
#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS
326
    ercd = ena_int( 123456789 ); // Hope this is large enough to error
327
    CYG_TEST_CHECK( E_PAR == ercd, "ena_int bad ercd !E_PAR" );
328
    ercd = dis_int( 123456789 );
329
    CYG_TEST_CHECK( E_PAR == ercd, "dis_int bad ercd !E_PAR" );
330
#endif
331
 
332
    // This may take too long on a sim...
333
    // On the synthetic target this test cannot run reliably - the
334
    // loop counting assumes exclusive access to the processor.
335
#ifndef CYGPKG_HAL_SYNTH    
336
    if ( ! cyg_test_is_simulator ) {
337
        SYSTIME t1, t2;
338
 
339
        CYG_TEST_INFO( "Testing masking of clock interrupt" );
340
 
341
        ercd = get_tim( &t1 );
342
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
343
 
344
        // Wait for a tick. This loop acts as a synchronizer for the loop
345
        // below, ensuring that it starts just after a tick.
346
        for ( loops = 0; loops < 10000000; loops++ ) {
347
            ercd = get_tim( &t2 );
348
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
349
            if ( t2 != t1 )
350
                break;
351
        }
352
        // Wait for next tick. Reset loops counter so we get the
353
        // approximate loop count of one clock tick.
354
        for ( loops = 0; loops < 10000000; loops++ ) {
355
            ercd = get_tim( &t1 );
356
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
357
            if ( t2 != t1 )
358
                break;
359
        }
360
 
361
        // save how many loops could be executed in one tick. Multiply
362
        // with 3 : we run loops in pairs below and add the time of
363
        // one extra to avoid small variations to trigger failures.
364
        intercom = loops * 3;
365
 
366
        ercd = ena_int( clock_interrupt ); // was initialized already
367
        CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" );
368
 
369
        ercd = get_tim( &t1 );
370
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
371
 
372
        // Wait for a tick
373
        for ( loops = intercom; loops > 0; loops-- ) {
374
            ercd = get_tim( &t2 );
375
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
376
            if ( t2 != t1 )
377
                break;
378
        }
379
        CYG_TEST_CHECK( 0 < loops, "No first tick" );
380
        // and a second one
381
        for (                 ; loops > 0; loops-- ) {
382
            ercd = get_tim( &t1 );
383
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
384
            if ( t2 != t1 )
385
                break;
386
        }
387
        CYG_TEST_CHECK( 0 < loops, "No second tick" );
388
 
389
        // The PowerPC cannot disable the timer interrupt (separately).
390
#ifndef CYGPKG_HAL_POWERPC
391
        ercd = dis_int( clock_interrupt ); // was initialized already
392
        CYG_TEST_CHECK( E_OK == ercd, "dis_int bad ercd" );
393
 
394
        ercd = get_tim( &t1 );
395
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
396
 
397
        // Wait for a tick (should not happen)
398
        for ( loops = intercom; loops > 0; loops-- ) {
399
            ercd = get_tim( &t2 );
400
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
401
            if ( t2 != t1 )
402
                break;
403
        }
404
        CYG_TEST_CHECK( 0 == loops, "A tick occured - should be masked" );
405
        CYG_TEST_CHECK( t1 == t2, "Times are different" );
406
 
407
        // Now enable it again and ensure all is well:
408
        ercd = ena_int( clock_interrupt );
409
        CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" );
410
#endif
411
 
412
        ercd = get_tim( &t1 );
413
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
414
 
415
        // Wait for a tick
416
        for ( loops = intercom; loops > 0; loops-- ) {
417
            ercd = get_tim( &t2 );
418
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
419
            if ( t2 != t1 )
420
                break;
421
        }
422
        CYG_TEST_CHECK( 0 < loops, "No first tick" );
423
        // and a second one
424
        for (                 ; loops > 0; loops-- ) {
425
            ercd = get_tim( &t1 );
426
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
427
            if ( t2 != t1 )
428
                break;
429
        }
430
        CYG_TEST_CHECK( 0 < loops, "No second tick" );
431
 
432
        CYG_TEST_PASS( "dis_int(), ena_int() OK" );
433
    }
434
#endif
435
 
436
    intercom = 0;
437
 
438
    ercd = get_tid( &scratch );
439
    CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
440
    CYG_TEST_CHECK( 1 == scratch, "tid not 1" );
441
 
442
    // start all other tasks (our prio is 1 by default)
443
    ercd = sta_tsk( 2, 222 );
444
    CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 2 bad ercd" );
445
    ercd = sta_tsk( 3, 333 );
446
    CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 3 bad ercd" );
447
    ercd = sta_tsk( 4, 444 );
448
    CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 4 bad ercd" );
449
    // drop pri of other tasks all to 5
450
    ercd = chg_pri( 2, 5 );
451
    CYG_TEST_CHECK( E_OK == ercd, "chg_pri 2 bad ercd" );
452
    ercd = chg_pri( 3, 5 );
453
    CYG_TEST_CHECK( E_OK == ercd, "chg_pri 3 bad ercd" );
454
    ercd = chg_pri( 4, 5 );
455
    CYG_TEST_CHECK( E_OK == ercd, "chg_pri 4 bad ercd" );
456
 
457
    // Test sleep/wakeup
458
    intercom = SLP;
459
    // Drop our prio to lower; they will run in turn until asleep
460
    ercd = chg_pri( 1, 6 );
461
    CYG_TEST_CHECK( E_OK == ercd, "chg_pri 1 (self) bad ercd" );
462
 
463
    loops = 4;
464
    do {
465
 
466
        if ( 1 & loops )
467
            CYG_TEST_INFO( " (toggling scheduler lock) " );
468
        else
469
            CYG_TEST_INFO( " (unlocked scheduler) " );
470
 
471
 
472
        CYG_TEST_CHECK(          0 == wakeups[0], "init: Wakeups[0] hit" );
473
        CYG_TEST_CHECK(          0 == wakeups[1], "init: Wakeups[1] hit" );
474
        CYG_TEST_CHECK( prewups[2] == wakeups[2], "init: Wakeups[2] hit" );
475
        CYG_TEST_CHECK( prewups[3] == wakeups[3], "init: Wakeups[3] hit" );
476
        CYG_TEST_CHECK( prewups[4] == wakeups[4], "init: Wakeups[4] hit" );
477
 
478
        // -------- TIMERS AND TIMESLICING DISABLED ---------
479
        // install an isr that will wake them all up in turn
480
        attach_isr( isr_wup_tsk );
481
        DELAY();
482
        detach_isr( isr_wup_tsk );
483
        // -------- timers and timeslicing ENABLED ---------
484
 
485
        CYG_TEST_CHECK(         0 == wakeups[0], "iwup_tsk: Wakeups[0] hit" );
486
        CYG_TEST_CHECK(         0 == wakeups[1], "iwup_tsk: Wakeups[1] hit" );
487
        CYG_TEST_CHECK( prewups[2] < wakeups[2], "iwup_tsk: Wakeups[2] not hit" );
488
        CYG_TEST_CHECK( prewups[3] < wakeups[3], "iwup_tsk: Wakeups[3] not hit" );
489
        CYG_TEST_CHECK( prewups[4] < wakeups[4], "iwup_tsk: Wakeups[4] not hit" );
490
        diag_printf( "INFO:<(fg loops %10d) thread wakeups : %2d %2d %2d >\n", count,
491
                     wakeups[2] - prewups[2],
492
                     wakeups[3] - prewups[3],
493
                     wakeups[4] - prewups[4] );
494
        prewups[2] = wakeups[2];
495
        prewups[3] = wakeups[3];
496
        prewups[4] = wakeups[4];
497
 
498
        // -------- TIMERS AND TIMESLICING DISABLED ---------
499
        // install an isr that will wake them all up in turn
500
        attach_isr( isr_ret_wup );
501
        DELAY();
502
        detach_isr( isr_ret_wup );
503
        // -------- timers and timeslicing ENABLED ---------
504
 
505
        CYG_TEST_CHECK(         0 == wakeups[0], "ret_wup: Wakeups[0] hit" );
506
        CYG_TEST_CHECK(         0 == wakeups[1], "ret_wup: Wakeups[1] hit" );
507
        CYG_TEST_CHECK( prewups[2] < wakeups[2], "ret_wup: Wakeups[2] not hit" );
508
        CYG_TEST_CHECK( prewups[3] < wakeups[3], "ret_wup: Wakeups[3] not hit" );
509
        CYG_TEST_CHECK( prewups[4] < wakeups[4], "ret_wup: Wakeups[4] not hit" );
510
        diag_printf( "INFO:<(fg loops %10d) thread ret_wups: %2d %2d %2d >\n", count,
511
                     wakeups[2] - prewups[2],
512
                     wakeups[3] - prewups[3],
513
                     wakeups[4] - prewups[4] );
514
        prewups[2] = wakeups[2];
515
        prewups[3] = wakeups[3];
516
        prewups[4] = wakeups[4];
517
 
518
        // move them on to waiting for a semaphore
519
        intercom = SEM;
520
        ercd = wup_tsk( 2 );
521
        CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(2) bad ercd" );
522
        ercd = wup_tsk( 3 );
523
        CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(3) bad ercd" );
524
        ercd = wup_tsk( 4 );
525
        CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(4) bad ercd" );
526
 
527
        CYG_TEST_CHECK(              0 == wakeups[0], "wup_tsk: Wakeups[0] hit" );
528
        CYG_TEST_CHECK(              0 == wakeups[1], "wup_tsk: Wakeups[1] hit" );
529
        CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "wup_tsk: Wakeups[2] not hit" );
530
        CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "wup_tsk: Wakeups[3] not hit" );
531
        CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "wup_tsk: Wakeups[4] not hit" );
532
        prewups[2] = wakeups[2];
533
        prewups[3] = wakeups[3];
534
        prewups[4] = wakeups[4];
535
 
536
        // -------- TIMERS AND TIMESLICING DISABLED ---------
537
        // install an isr that will wake them all up in turn
538
        attach_isr( isr_sig_sem );
539
        DELAY();
540
        detach_isr( isr_sig_sem );
541
        // -------- timers and timeslicing ENABLED ---------
542
 
543
        CYG_TEST_CHECK(         0 == wakeups[0], "isig_sem: Wakeups[0] hit" );
544
        CYG_TEST_CHECK(         0 == wakeups[1], "isig_sem: Wakeups[1] hit" );
545
        CYG_TEST_CHECK( prewups[2] < wakeups[2], "isig_sem: Wakeups[2] not hit" );
546
        CYG_TEST_CHECK( prewups[3] < wakeups[3], "isig_sem: Wakeups[3] not hit" );
547
        CYG_TEST_CHECK( prewups[4] < wakeups[4], "isig_sem: Wakeups[4] not hit" );
548
        diag_printf( "INFO:<(fg loops %10d) semaphore waits: %2d %2d %2d >\n", count,
549
                     wakeups[2] - prewups[2],
550
                     wakeups[3] - prewups[3],
551
                     wakeups[4] - prewups[4] );
552
        prewups[2] = wakeups[2];
553
        prewups[3] = wakeups[3];
554
        prewups[4] = wakeups[4];
555
 
556
        // move them on to waiting for a flag
557
        intercom = FLG;
558
        ercd = sig_sem( 1 );
559
        CYG_TEST_CHECK( E_OK == ercd, "sig_sem(1) bad ercd" );
560
        ercd = sig_sem( 2 );
561
        CYG_TEST_CHECK( E_OK == ercd, "sig_sem(2) bad ercd" );
562
        ercd = sig_sem( 3 );
563
        CYG_TEST_CHECK( E_OK == ercd, "sig_sem(3) bad ercd" );
564
 
565
        CYG_TEST_CHECK(              0 == wakeups[0], "sig_sem: Wakeups[0] hit" );
566
        CYG_TEST_CHECK(              0 == wakeups[1], "sig_sem: Wakeups[1] hit" );
567
        CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "sig_sem: Wakeups[2] not hit" );
568
        CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "sig_sem: Wakeups[3] not hit" );
569
        CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "sig_sem: Wakeups[4] not hit" );
570
        prewups[2] = wakeups[2];
571
        prewups[3] = wakeups[3];
572
        prewups[4] = wakeups[4];
573
 
574
        // -------- TIMERS AND TIMESLICING DISABLED ---------
575
        // install an isr that will wake them all up in turn
576
        attach_isr( isr_set_flg );
577
        DELAY();
578
        detach_isr( isr_set_flg );
579
        // -------- timers and timeslicing ENABLED ---------
580
 
581
        CYG_TEST_CHECK(         0 == wakeups[0], "iset_flg: Wakeups[0] hit" );
582
        CYG_TEST_CHECK(         0 == wakeups[1], "iset_flg: Wakeups[1] hit" );
583
        CYG_TEST_CHECK( prewups[2] < wakeups[2], "iset_flg: Wakeups[2] not hit" );
584
        CYG_TEST_CHECK( prewups[3] < wakeups[3], "iset_flg: Wakeups[3] not hit" );
585
        CYG_TEST_CHECK( prewups[4] < wakeups[4], "iset_flg: Wakeups[4] not hit" );
586
        diag_printf( "INFO:<(fg loops %10d) flag waits/sets: %2d %2d %2d >\n", count,
587
                     wakeups[2] - prewups[2],
588
                     wakeups[3] - prewups[3],
589
                     wakeups[4] - prewups[4] );
590
        prewups[2] = wakeups[2];
591
        prewups[3] = wakeups[3];
592
        prewups[4] = wakeups[4];
593
 
594
        // move them on to waiting for a message box
595
        intercom = MBX;
596
        ercd = set_flg( 2, 0xfff );
597
        CYG_TEST_CHECK( E_OK == ercd, "set_flg(2) bad ercd" );
598
        ercd = set_flg( 3, 0xfff );
599
        CYG_TEST_CHECK( E_OK == ercd, "set_flg(3) bad ercd" );
600
        ercd = set_flg( 4, 0xfff );
601
        CYG_TEST_CHECK( E_OK == ercd, "set_flg(4) bad ercd" );
602
 
603
        CYG_TEST_CHECK(              0 == wakeups[0], "set_flg: Wakeups[0] hit" );
604
        CYG_TEST_CHECK(              0 == wakeups[1], "set_flg: Wakeups[1] hit" );
605
        CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "set_flg: Wakeups[2] not hit" );
606
        CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "set_flg: Wakeups[3] not hit" );
607
        CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "set_flg: Wakeups[4] not hit" );
608
        prewups[2] = wakeups[2];
609
        prewups[3] = wakeups[3];
610
        prewups[4] = wakeups[4];
611
 
612
        // -------- TIMERS AND TIMESLICING DISABLED ---------
613
        // install an isr that will wake them all up in turn
614
        attach_isr( isr_snd_msg );
615
        DELAY();
616
        detach_isr( isr_snd_msg );
617
        // -------- timers and timeslicing ENABLED ---------
618
 
619
        CYG_TEST_CHECK(         0 == wakeups[0], "isnd_msg: Wakeups[0] hit" );
620
        CYG_TEST_CHECK(         0 == wakeups[1], "isnd_msg: Wakeups[1] hit" );
621
        CYG_TEST_CHECK( prewups[2] < wakeups[2], "isnd_msg: Wakeups[2] not hit" );
622
        CYG_TEST_CHECK( prewups[3] < wakeups[3], "isnd_msg: Wakeups[3] not hit" );
623
        CYG_TEST_CHECK( prewups[4] < wakeups[4], "isnd_msg: Wakeups[4] not hit" );
624
        diag_printf( "INFO:<(fg loops %10d) message rec'pts: %2d %2d %2d >\n", count,
625
                     wakeups[2] - prewups[2],
626
                     wakeups[3] - prewups[3],
627
                     wakeups[4] - prewups[4] );
628
        prewups[2] = wakeups[2];
629
        prewups[3] = wakeups[3];
630
        prewups[4] = wakeups[4];
631
 
632
        // move them on to exiting, all done
633
        if ( 1 == loops )
634
            // then we are about to exit
635
            intercom = EXIT;
636
        else
637
            intercom = SLP;
638
        ercd = snd_msg( 2, (T_MSG *)&intercom );
639
        CYG_TEST_CHECK( E_OK == ercd, "snd_msg(2) bad ercd" );
640
        ercd = snd_msg( 3, (T_MSG *)&intercom );
641
        CYG_TEST_CHECK( E_OK == ercd, "snd_msg(3) bad ercd" );
642
        ercd = snd_msg( 4, (T_MSG *)&intercom );
643
        CYG_TEST_CHECK( E_OK == ercd, "snd_msg(4) bad ercd" );
644
 
645
        CYG_TEST_CHECK(              0 == wakeups[0], "snd_msg: Wakeups[0] hit" );
646
        CYG_TEST_CHECK(              0 == wakeups[1], "snd_msg: Wakeups[1] hit" );
647
        CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "snd_msg: Wakeups[2] not hit" );
648
        CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "snd_msg: Wakeups[3] not hit" );
649
        CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "snd_msg: Wakeups[4] not hit" );
650
        prewups[2] = wakeups[2];
651
        prewups[3] = wakeups[3];
652
        prewups[4] = wakeups[4];
653
 
654
        CYG_TEST_PASS( "Tested ISR invoked uITRON functions" );
655
 
656
    } while ( 0 < --loops );
657
 
658
    CYG_TEST_EXIT( "All done" );
659
    ext_tsk();
660
}
661
 
662
 
663
void body( int n )
664
{
665
    unsigned int z;
666
    ER ercd;
667
    T_MSG *pk_msg;
668
 
669
    do {
670
        switch ( intercom ) {
671
        case NOTHING:
672
            ercd = slp_tsk();
673
            CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (doing nothing)" );
674
            continue;
675
        case SLP:
676
            ercd = slp_tsk();
677
            CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" );
678
            wakeups[ n ]++;
679
            break;
680
        case SEM:
681
            ercd = wai_sem( n-1 ); // 1..3 for semas
682
            CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" );
683
            wakeups[ n ]++;
684
            break;
685
        case FLG:
686
            ercd = wai_flg( &z, n, (1<<n), TWF_CLR | TWF_ANDW );
687
            CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" );
688
            CYG_TEST_CHECK( z & (1<<n), "Flag bit not set" );
689
            wakeups[ n ]++;
690
            break;
691
        case MBX:
692
            ercd = rcv_msg( &pk_msg, n );
693
            CYG_TEST_CHECK( E_OK == ercd, "rcv_msg bad ercd" );
694
            CYG_TEST_CHECK( pk_msg, "rcv_msg NULL msg" );
695
            wakeups[ n ]++;
696
            break;
697
        case EXIT:
698
            return;
699
        }
700
    } while ( 1 );
701
}
702
 
703
void task2( unsigned int arg )
704
{
705
    ER ercd;
706
    CYG_TEST_INFO( "Task 2 running" );
707
    ercd = get_tid( &scratch );
708
    CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
709
    CYG_TEST_CHECK( 2 == scratch, "tid not 2" );
710
    if ( 222 != arg )
711
        CYG_TEST_FAIL( "Task 2 arg not 222" );
712
    body(2);
713
    CYG_TEST_INFO( "Task 2 exiting" );
714
    ext_tsk();
715
    CYG_TEST_FAIL( "Task 2 failed to exit" );
716
}
717
 
718
void task3( unsigned int arg )
719
{
720
    ER ercd;
721
    CYG_TEST_INFO("Task 3 running");
722
    ercd = get_tid( &scratch );
723
    CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
724
    CYG_TEST_CHECK( 3 == scratch, "tid not 3" );
725
    if ( 333 != arg )
726
        CYG_TEST_FAIL( "Task 3 arg not 333" );
727
    body(3);
728
    CYG_TEST_INFO( "Task 3 exiting" );
729
    ext_tsk();
730
    CYG_TEST_FAIL( "Task 3 failed to exit" );
731
}
732
 
733
void task4( unsigned int arg )
734
{
735
    ER ercd;
736
    CYG_TEST_INFO("Task 4 running");
737
    ercd = get_tid( &scratch );
738
    CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" );
739
    CYG_TEST_CHECK( 4 == scratch, "tid not 4" );
740
    if ( 444 != arg )
741
        CYG_TEST_FAIL( "Task 4 arg not 444" );
742
    body(4);
743
    CYG_TEST_INFO( "Task 4 exiting" );
744
    ext_tsk();
745
    CYG_TEST_FAIL( "Task 4 failed to exit" );
746
}
747
 
748
// ------------------------------------------------------------------------
749
// Start of C++ aware portion, so to speak.
750
//
751
 
752
#include <cyg/hal/hal_intr.h>
753
#include <cyg/kernel/intr.hxx>
754
#include <cyg/kernel/clock.hxx>
755
#include <cyg/kernel/sched.hxx>
756
#include <cyg/kernel/sched.inl>
757
 
758
void set_interrupt_number( void )
759
{
760
    clock_interrupt = CYGNUM_HAL_INTERRUPT_RTC;
761
}
762
 
763
// This snippet stolen from kernel/.../clock.cxx to be able to detach
764
// the RTC from its interrupt source.
765
class Cyg_RealTimeClock
766
    : public Cyg_Clock
767
{
768
public:
769
    Cyg_Interrupt       interrupt;
770
 
771
    static cyg_uint32 isr(cyg_vector vector, CYG_ADDRWORD data);
772
 
773
    static void dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data);
774
 
775
    Cyg_RealTimeClock();
776
};
777
 
778
 
779
static Cyg_Interrupt uit_intr(
780
        (unsigned)CYGNUM_HAL_INTERRUPT_RTC, // Vector to attach to
781
        0,                              // Queue priority
782
        (unsigned)0,                    // Data pointer
783
        &isr_wup_tsk,                   // Interrupt Service Routine
784
        &cyg_uitron_dsr                 // Deferred Service Routine
785
);
786
 
787
void
788
attach_isr( unsigned int (*isr)(unsigned int, unsigned int) )
789
{
790
    int inuse;
791
    int old_ints;
792
    Cyg_RealTimeClock *prtc = (Cyg_RealTimeClock *)Cyg_Clock::real_time_clock;
793
    HAL_DISABLE_INTERRUPTS(old_ints);
794
    HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC );
795
    prtc->interrupt.detach();
796
#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
797
    // Only check that the vector was cleared when there's a specific
798
    // vector for the RTC.  In chain mode, other interrupt handlers
799
    // may prevent the shared vector from being cleared when detaching
800
    // the RTC ISR, and this assertion fails.
801
    HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
802
    CYG_TEST_CHECK( !inuse, "Failed to detach clock ISR" );
803
#endif
804
    uit_intr = Cyg_Interrupt(
805
        CYGNUM_HAL_INTERRUPT_RTC,       // Vector to attach to
806
        1,                              // Queue priority
807
        0,                              // Data pointer
808
        isr,                            // Interrupt Service Routine
809
        cyg_uitron_dsr                  // Deferred Service Routine
810
        );
811
    uit_intr.attach();
812
    HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
813
    CYG_TEST_CHECK( inuse, "Failed to attach new ISR" );
814
    ACK_CLOCK();
815
    HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC );
816
    HAL_RESTORE_INTERRUPTS(old_ints);
817
}
818
 
819
void
820
detach_isr( unsigned int (*isr)(unsigned int, unsigned int) )
821
{
822
    int inuse;
823
    int old_ints;
824
    Cyg_RealTimeClock *prtc = (Cyg_RealTimeClock *)Cyg_Clock::real_time_clock;
825
    HAL_DISABLE_INTERRUPTS(old_ints);
826
    HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC );
827
    uit_intr.detach();
828
#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
829
    // See comment above in attach_isr.
830
    HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
831
    CYG_TEST_CHECK( !inuse, "Failed to detach my ISR" );
832
#endif
833
    prtc->interrupt.attach();
834
    HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
835
    CYG_TEST_CHECK( inuse, "Failed to attach clock ISR" );
836
    ACK_CLOCK();
837
    HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC );
838
    HAL_RESTORE_INTERRUPTS(old_ints);
839
}
840
 
841
 
842
void
843
lock_sched( void )
844
{
845
    cyg_uint32 l;
846
    Cyg_Scheduler::lock();
847
    l = Cyg_Scheduler::get_sched_lock();
848
    CYG_TEST_CHECK( 0 < l, "lock: Sched not locked" );
849
    CYG_TEST_CHECK( 2 > l, "lock: Sched already locked" );
850
}
851
 
852
void
853
unlock_sched( void )
854
{
855
    cyg_uint32 l;
856
    l = Cyg_Scheduler::get_sched_lock();
857
    CYG_TEST_CHECK( 0 < l, "unlock: Sched not locked" );
858
    CYG_TEST_CHECK( 2 > l, "unlock: Sched already locked" );
859
    Cyg_Scheduler::unlock();
860
}
861
 
862
 
863
#else // not enough (or too many) uITRON objects configured in
864
#define N_A_MSG "not enough uITRON objects to run test"
865
#endif // not enough (or too many) uITRON objects configured in
866
#else  // not C++ and some C++ specific options enabled
867
#define N_A_MSG "C++ specific options selected but this is C"
868
#endif  // not C++ and some C++ specific options enabled
869
#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK   - can't test without it
870
#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK"
871
#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK  - can't test without it
872
#else  // ! CYGFUN_KERNEL_THREADS_TIMER   - can't test without it
873
#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER"
874
#endif // ! CYGFUN_KERNEL_THREADS_TIMER   - can't test without it
875
#else  // ! CYGIMP_THREAD_PRIORITY        - can't test without it
876
#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE"
877
#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE   - can't test without it
878
#else  // ! CYGPKG_UITRON
879
#define N_A_MSG "uITRON Compatibility layer disabled"
880
#endif // CYGPKG_UITRON
881
 
882
#ifdef N_A_MSG
883
externC void
884
cyg_start( void )
885
{
886
    CYG_TEST_INIT();
887
    CYG_TEST_NA( N_A_MSG );
888
}
889
#endif // N_A_MSG defined ie. we are N/A.
890
 
891
// EOF testintr.c

powered by: WebSVN 2.1.0

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