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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [compat/] [uitron/] [v2_0/] [tests/] [testintr.cxx] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//===========================================================================
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 Red Hat, 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 version.
16
//
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
20
// for more details.
21
//
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.
25
//
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.
32
//
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.
35
//
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####
42
//
43
// Author(s):   hmt
44
// Contributors:hmt
45
// Date:        1998-08-20
46
// Purpose:     uITRON API testing
47
// Description: 
48
//
49
//####DESCRIPTIONEND####
50
//
51
//===========================================================================
52
 
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
57
 
58
#ifdef CYGPKG_UITRON                    // we DO want the uITRON package
59
 
60
#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE      // we DO want prioritized threads
61
 
62
#ifdef CYGFUN_KERNEL_THREADS_TIMER      // we DO want timout-able calls
63
 
64
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK     // we DO want the realtime clock
65
 
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) )
70
 
71
// =================== TEST CONFIGURATION ===================
72
#if \
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             )          && \
79
                                                                   \
80
    /* the end of the large #if statement */                       \
81
    1
82
 
83
// ============================ END ============================
84
 
85
#include <cyg/hal/hal_arch.h>
86
#include <cyg/hal/hal_intr.h>
87
 
88
#include <cyg/infra/diag.h>
89
 
90
#include <cyg/compat/uitron/uit_func.h> // uITRON
91
#include <cyg/compat/uitron/uit_ifnc.h> // uITRON interrupt funcs
92
 
93
void set_interrupt_number( void );
94
 
95
unsigned int clock_interrupt = 0;
96
 
97
externC void
98
cyg_package_start( void )
99
{
100
    CYG_TEST_INIT();
101
    CYG_TEST_INFO( "Calling cyg_uitron_start()" );
102
    set_interrupt_number();
103
    cyg_uitron_start();
104
}
105
 
106
extern "C" {
107
    void task1( unsigned int arg );
108
    void task2( unsigned int arg );
109
    void task3( unsigned int arg );
110
    void task4( unsigned int arg );
111
}
112
 
113
volatile int intercom = 0;
114
INT scratch = 0;
115
 
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
118
// macros.
119
// 
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.
122
//
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.
126
// 
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 );
132
//
133
// and return macros are:
134
//     ret_wup( ID tskid );
135
//     ret_int();
136
//
137
// These ISRs perform the producer ops on all available objects in turn.
138
// Tasks 2-4
139
// Semas 1-4
140
// Flags 1-4 with marching bit data; they'll all be set to 0x1ff eventually
141
// Mboxes 1-4 with an arbitrary pointer
142
 
143
enum {
144
    NOTHING = 0,
145
    SLP,
146
    SEM,
147
    FLG,
148
    MBX,
149
    EXIT
150
};
151
 
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 );      \
156
CYG_MACRO_END
157
 
158
#define CHECK_TID() CYG_MACRO_START                     \
159
    int my_tid;                                         \
160
    ER ercd;                                            \
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" );  \
164
CYG_MACRO_END
165
 
166
 
167
unsigned int
168
isr_wup_tsk( unsigned int vector, unsigned int data )
169
{
170
    // Hit TASKS in range 2..4
171
    static int wtid = 2;
172
    ACK_CLOCK();
173
    CHECK_TID();
174
    iwup_tsk( wtid );
175
    wtid++;
176
    if ( 5 == wtid ) wtid = 2;
177
    ret_int();
178
}
179
 
180
unsigned int
181
isr_ret_wup( unsigned int vector, unsigned int data )
182
{
183
    // Hit TASKS in range 2..4
184
    static int rwid = 2;
185
    ACK_CLOCK();
186
    CHECK_TID();
187
    rwid++;
188
    if ( 6 == rwid ) rwid = 3;
189
    ret_wup( rwid - 1 );
190
}
191
 
192
unsigned int
193
isr_sig_sem( unsigned int vector, unsigned int data )
194
{
195
    // Hit SEMAS in range 1..3
196
    static int ssid = 1;
197
    ACK_CLOCK();
198
    CHECK_TID();
199
    isig_sem( ssid );
200
    ssid++;
201
    if ( ssid == 4 ) ssid = 1;
202
    ret_int();
203
}
204
 
205
unsigned int
206
isr_set_flg( unsigned int vector, unsigned int data )
207
{
208
    // Hit FLAGS in range 1..4
209
    static int sfid = 1;
210
    static int sfdata = 0xff;
211
    ACK_CLOCK();
212
    CHECK_TID();
213
    iset_flg( sfid, sfdata );
214
    sfid++;
215
    if ( sfid == 5 ) sfid = 1;
216
//    sfdata <<= 1;
217
//    if ( sfdata == 0x20 ) sfdata = 1; // so that eventually all 0x1f set
218
    ret_int();
219
}
220
 
221
unsigned int
222
isr_snd_msg( unsigned int vector, unsigned int data )
223
{
224
    // Hit MBOXES in range 1..4
225
    static int smid = 1;
226
    ACK_CLOCK();
227
    CHECK_TID();
228
    isnd_msg( smid, (T_MSG *)&smid );
229
    smid++;
230
    if ( smid == 5 ) smid = 1;
231
    ret_int();
232
}
233
 
234
 
235
void attach_isr( unsigned int (*isr)(unsigned int, unsigned int) );
236
void detach_isr( unsigned int (*isr)(unsigned int, unsigned int) );
237
 
238
void lock_sched( void );
239
void unlock_sched( void );
240
 
241
volatile int count = -1;
242
 
243
/*
244
#define BIGDELAY  50000000
245
#define SMALLDELAY (BIGDELAY/SMALLLOOPS)
246
#define SMALLLOOPS 3
247
 
248
#define xxxLONGDELAY()                                     \
249
do {                                                    \
250
    int i;                                              \
251
    for ( i = 0; i < BIGDELAY; i++ )                    \
252
        if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break;  \
253
} while ( 0 )
254
 
255
#define xxxDELAYLOCKSCHED()                                        \
256
do {                                                            \
257
    int i,j;                                                    \
258
    for ( j = 0; j < SMALLLOOPS; j++ ) {                        \
259
        lock_sched();                                           \
260
        for ( i = 0; i < SMALLDELAY; i++ )                      \
261
            if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break;      \
262
        unlock_sched();                                         \
263
        if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break;          \
264
    }                                                           \
265
} while ( 0 )
266
*/
267
 
268
#define SMALLDELAYHW  (5000000)
269
#define EVENTSHW      (     20)
270
#define SMALLDELAYSIM ( 100000)
271
#define EVENTSSIM     (      4)
272
 
273
#define SMALLDELAY (smalldelay)
274
#define EVENTS     (events)
275
 
276
static int smalldelay = SMALLDELAYHW;
277
static int events     = EVENTSHW;
278
 
279
#define LONGDELAY() do {                                        \
280
    count = 0;                                                  \
281
    do count++; while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS ); \
282
} while ( 0 )
283
 
284
 
285
#define DELAYLOCKSCHED()                                              \
286
do {                                                                  \
287
    count = 0;                                                        \
288
    int i;                                                            \
289
    do {                                                              \
290
        lock_sched();                                                 \
291
        for ( i = 0; i < SMALLDELAY; i++ ) {                          \
292
            count++;                                                  \
293
            if ( wakeups[ 4 ] >= prewups[ 4 ] + EVENTS )              \
294
                break;                                                \
295
        }                                                             \
296
        unlock_sched();                                               \
297
        CYG_TEST_INFO("  [Still iterating, please wait....]  ");      \
298
    } while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS );                 \
299
} while ( 0 )
300
 
301
#define DELAY()                                 \
302
if ( 1 & loops )                                \
303
    DELAYLOCKSCHED();                           \
304
else                                            \
305
    LONGDELAY();
306
 
307
 
308
volatile int wakeups[ 5 ] = { 0,0,0,0,0 };
309
volatile int prewups[ 5 ] = { 0,0,0,0,0 };
310
 
311
 
312
void task1( unsigned int arg )
313
{
314
    ER ercd;
315
    int loops;
316
 
317
    CYG_TEST_INFO( "Task 1 running" );
318
 
319
    if ( cyg_test_is_simulator ) {
320
        // take less time
321
        events     = EVENTSSIM;
322
    }
323
 
324
 
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" );
331
#endif
332
 
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 ) {
338
        SYSTIME t1, t2;
339
 
340
        CYG_TEST_INFO( "Testing masking of clock interrupt" );
341
 
342
        ercd = get_tim( &t1 );
343
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
344
 
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" );
350
            if ( t2 != t1 )
351
                break;
352
        }
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" );
358
            if ( t2 != t1 )
359
                break;
360
        }
361
 
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;
366
 
367
        ercd = ena_int( clock_interrupt ); // was initialized already
368
        CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" );
369
 
370
        ercd = get_tim( &t1 );
371
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
372
 
373
        // Wait for a tick
374
        for ( loops = intercom; loops > 0; loops-- ) {
375
            ercd = get_tim( &t2 );
376
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
377
            if ( t2 != t1 )
378
                break;
379
        }
380
        CYG_TEST_CHECK( 0 < loops, "No first tick" );
381
        // and a second one
382
        for (                 ; loops > 0; loops-- ) {
383
            ercd = get_tim( &t1 );
384
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
385
            if ( t2 != t1 )
386
                break;
387
        }
388
        CYG_TEST_CHECK( 0 < loops, "No second tick" );
389
 
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" );
394
 
395
        ercd = get_tim( &t1 );
396
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
397
 
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" );
402
            if ( t2 != t1 )
403
                break;
404
        }
405
        CYG_TEST_CHECK( 0 == loops, "A tick occured - should be masked" );
406
        CYG_TEST_CHECK( t1 == t2, "Times are different" );
407
 
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" );
411
#endif
412
 
413
        ercd = get_tim( &t1 );
414
        CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
415
 
416
        // Wait for a tick
417
        for ( loops = intercom; loops > 0; loops-- ) {
418
            ercd = get_tim( &t2 );
419
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
420
            if ( t2 != t1 )
421
                break;
422
        }
423
        CYG_TEST_CHECK( 0 < loops, "No first tick" );
424
        // and a second one
425
        for (                 ; loops > 0; loops-- ) {
426
            ercd = get_tim( &t1 );
427
            CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" );
428
            if ( t2 != t1 )
429
                break;
430
        }
431
        CYG_TEST_CHECK( 0 < loops, "No second tick" );
432
 
433
        CYG_TEST_PASS( "dis_int(), ena_int() OK" );
434
    }
435
#endif
436
 
437
    intercom = 0;
438
 
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" );
442
 
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" );
457
 
458
    // Test sleep/wakeup
459
    intercom = SLP;
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" );
463
 
464
    loops = 4;
465
    do {
466
 
467
        if ( 1 & loops )
468
            CYG_TEST_INFO( " (toggling scheduler lock) " );
469
        else
470
            CYG_TEST_INFO( " (unlocked scheduler) " );
471
 
472
 
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" );
478
 
479
        // -------- TIMERS AND TIMESLICING DISABLED ---------
480
        // install an isr that will wake them all up in turn
481
        attach_isr( isr_wup_tsk );
482
        DELAY();
483
        detach_isr( isr_wup_tsk );
484
        // -------- timers and timeslicing ENABLED ---------
485
 
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];
498
 
499
        // -------- TIMERS AND TIMESLICING DISABLED ---------
500
        // install an isr that will wake them all up in turn
501
        attach_isr( isr_ret_wup );
502
        DELAY();
503
        detach_isr( isr_ret_wup );
504
        // -------- timers and timeslicing ENABLED ---------
505
 
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];
518
 
519
        // move them on to waiting for a semaphore
520
        intercom = SEM;
521
        ercd = wup_tsk( 2 );
522
        CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(2) bad ercd" );
523
        ercd = wup_tsk( 3 );
524
        CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(3) bad ercd" );
525
        ercd = wup_tsk( 4 );
526
        CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(4) bad ercd" );
527
 
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];
536
 
537
        // -------- TIMERS AND TIMESLICING DISABLED ---------
538
        // install an isr that will wake them all up in turn
539
        attach_isr( isr_sig_sem );
540
        DELAY();
541
        detach_isr( isr_sig_sem );
542
        // -------- timers and timeslicing ENABLED ---------
543
 
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];
556
 
557
        // move them on to waiting for a flag
558
        intercom = FLG;
559
        ercd = sig_sem( 1 );
560
        CYG_TEST_CHECK( E_OK == ercd, "sig_sem(1) bad ercd" );
561
        ercd = sig_sem( 2 );
562
        CYG_TEST_CHECK( E_OK == ercd, "sig_sem(2) bad ercd" );
563
        ercd = sig_sem( 3 );
564
        CYG_TEST_CHECK( E_OK == ercd, "sig_sem(3) bad ercd" );
565
 
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];
574
 
575
        // -------- TIMERS AND TIMESLICING DISABLED ---------
576
        // install an isr that will wake them all up in turn
577
        attach_isr( isr_set_flg );
578
        DELAY();
579
        detach_isr( isr_set_flg );
580
        // -------- timers and timeslicing ENABLED ---------
581
 
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];
594
 
595
        // move them on to waiting for a message box
596
        intercom = MBX;
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" );
603
 
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];
612
 
613
        // -------- TIMERS AND TIMESLICING DISABLED ---------
614
        // install an isr that will wake them all up in turn
615
        attach_isr( isr_snd_msg );
616
        DELAY();
617
        detach_isr( isr_snd_msg );
618
        // -------- timers and timeslicing ENABLED ---------
619
 
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];
632
 
633
        // move them on to exiting, all done
634
        if ( 1 == loops )
635
            // then we are about to exit
636
            intercom = EXIT;
637
        else
638
            intercom = SLP;
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" );
645
 
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];
654
 
655
        CYG_TEST_PASS( "Tested ISR invoked uITRON functions" );
656
 
657
    } while ( 0 < --loops );
658
 
659
    CYG_TEST_EXIT( "All done" );
660
    ext_tsk();
661
}
662
 
663
 
664
void body( int n )
665
{
666
    unsigned int z;
667
    ER ercd;
668
    T_MSG *pk_msg;
669
 
670
    do {
671
        switch ( intercom ) {
672
        case NOTHING:
673
            ercd = slp_tsk();
674
            CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (doing nothing)" );
675
            continue;
676
        case SLP:
677
            ercd = slp_tsk();
678
            CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" );
679
            wakeups[ n ]++;
680
            break;
681
        case SEM:
682
            ercd = wai_sem( n-1 ); // 1..3 for semas
683
            CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" );
684
            wakeups[ n ]++;
685
            break;
686
        case FLG:
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" );
690
            wakeups[ n ]++;
691
            break;
692
        case MBX:
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" );
696
            wakeups[ n ]++;
697
            break;
698
        case EXIT:
699
            return;
700
        }
701
    } while ( 1 );
702
}
703
 
704
void task2( unsigned int arg )
705
{
706
    ER ercd;
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" );
711
    if ( 222 != arg )
712
        CYG_TEST_FAIL( "Task 2 arg not 222" );
713
    body(2);
714
    CYG_TEST_INFO( "Task 2 exiting" );
715
    ext_tsk();
716
    CYG_TEST_FAIL( "Task 2 failed to exit" );
717
}
718
 
719
void task3( unsigned int arg )
720
{
721
    ER ercd;
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" );
726
    if ( 333 != arg )
727
        CYG_TEST_FAIL( "Task 3 arg not 333" );
728
    body(3);
729
    CYG_TEST_INFO( "Task 3 exiting" );
730
    ext_tsk();
731
    CYG_TEST_FAIL( "Task 3 failed to exit" );
732
}
733
 
734
void task4( unsigned int arg )
735
{
736
    ER ercd;
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" );
741
    if ( 444 != arg )
742
        CYG_TEST_FAIL( "Task 4 arg not 444" );
743
    body(4);
744
    CYG_TEST_INFO( "Task 4 exiting" );
745
    ext_tsk();
746
    CYG_TEST_FAIL( "Task 4 failed to exit" );
747
}
748
 
749
// ------------------------------------------------------------------------
750
// Start of C++ aware portion, so to speak.
751
//
752
 
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>
758
 
759
void set_interrupt_number( void )
760
{
761
    clock_interrupt = CYGNUM_HAL_INTERRUPT_RTC;
762
}
763
 
764
// This snippet stolen from kernel/.../clock.cxx to be able to detach
765
// the RTC from its interrupt source.
766
class Cyg_RealTimeClock
767
    : public Cyg_Clock
768
{
769
public:
770
    Cyg_Interrupt       interrupt;
771
 
772
    static cyg_uint32 isr(cyg_vector vector, CYG_ADDRWORD data);
773
 
774
    static void dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data);
775
 
776
    Cyg_RealTimeClock();
777
};
778
 
779
 
780
static Cyg_Interrupt uit_intr(
781
        (unsigned)CYGNUM_HAL_INTERRUPT_RTC, // Vector to attach to
782
        0,                              // Queue priority
783
        (unsigned)0,                    // Data pointer
784
        &isr_wup_tsk,                   // Interrupt Service Routine
785
        &cyg_uitron_dsr                 // Deferred Service Routine
786
);
787
 
788
void
789
attach_isr( unsigned int (*isr)(unsigned int, unsigned int) )
790
{
791
    int inuse;
792
    int old_ints;
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" );
804
#endif
805
    uit_intr = Cyg_Interrupt(
806
        CYGNUM_HAL_INTERRUPT_RTC,       // Vector to attach to
807
        1,                              // Queue priority
808
        0,                              // Data pointer
809
        isr,                            // Interrupt Service Routine
810
        cyg_uitron_dsr                  // Deferred Service Routine
811
        );
812
    uit_intr.attach();
813
    HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
814
    CYG_TEST_CHECK( inuse, "Failed to attach new ISR" );
815
    ACK_CLOCK();
816
    HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC );
817
    HAL_RESTORE_INTERRUPTS(old_ints);
818
}
819
 
820
void
821
detach_isr( unsigned int (*isr)(unsigned int, unsigned int) )
822
{
823
    int inuse;
824
    int old_ints;
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 );
828
    uit_intr.detach();
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" );
833
#endif
834
    prtc->interrupt.attach();
835
    HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse );
836
    CYG_TEST_CHECK( inuse, "Failed to attach clock ISR" );
837
    ACK_CLOCK();
838
    HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC );
839
    HAL_RESTORE_INTERRUPTS(old_ints);
840
}
841
 
842
 
843
void
844
lock_sched( void )
845
{
846
    cyg_uint32 l;
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" );
851
}
852
 
853
void
854
unlock_sched( void )
855
{
856
    cyg_uint32 l;
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();
861
}
862
 
863
 
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
882
 
883
#ifdef N_A_MSG
884
externC void
885
cyg_start( void )
886
{
887
    CYG_TEST_INIT();
888
    CYG_TEST_NA( N_A_MSG );
889
}
890
#endif // N_A_MSG defined ie. we are N/A.
891
 
892
// EOF testintr.c

powered by: WebSVN 2.1.0

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