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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [eth/] [arm/] [ebsa285/] [v2_0/] [tests/] [test_net_realtime.h] - Blame information for rev 307

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

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H
2
#define CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H
3
/*==========================================================================
4
//
5
//        test_net_realtime.h
6
//
7
//        Auxiliary test header file
8
//        Provide a thread that runs on EBSA only, which verifies that
9
//        realtime characteristics are preserved.
10
//
11
//==========================================================================
12
//####ECOSGPLCOPYRIGHTBEGIN####
13
// -------------------------------------------
14
// This file is part of eCos, the Embedded Configurable Operating System.
15
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
16
//
17
// eCos is free software; you can redistribute it and/or modify it under
18
// the terms of the GNU General Public License as published by the Free
19
// Software Foundation; either version 2 or (at your option) any later version.
20
//
21
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
22
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License along
27
// with eCos; if not, write to the Free Software Foundation, Inc.,
28
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29
//
30
// As a special exception, if other files instantiate templates or use macros
31
// or inline functions from this file, or you compile this file and link it
32
// with other works to produce a work based on this file, this file does not
33
// by itself cause the resulting work to be covered by the GNU General Public
34
// License. However the source code for this file must still be made available
35
// in accordance with section (3) of the GNU General Public License.
36
//
37
// This exception does not invalidate any other reasons why a work based on
38
// this file might be covered by the GNU General Public License.
39
//
40
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
41
// at http://sources.redhat.com/ecos/ecos-license/
42
// -------------------------------------------
43
//####ECOSGPLCOPYRIGHTEND####
44
//==========================================================================
45
//#####DESCRIPTIONBEGIN####
46
//
47
// Author(s):     hmt
48
// Contributors:  hmt
49
// Date:          2000-05-03
50
// Description:
51
//
52
//####DESCRIPTIONEND####
53
*/
54
 
55
// This is the API to this file:
56
 
57
#define TNR_OFF() tnr_active = 0
58
#define TNR_ON()  tnr_active = 1
59
#define TNR_INIT() tnr_init()
60
#define TNR_PRINT_ACTIVITY() tnr_print_activity() 
61
 
62
// Tests should use these if they are defined to test that the realtime
63
// characteristics of the world are preserved during a test.
64
//
65
// It is accepted that printing stuff via diag_printf() (and the test
66
// infra) disables interrupts for a long time.  So invoke TNR_OFF/ON()
67
// either side of diagnostic prints, to prevent boguf firings of the
68
// realtime test.
69
 
70
// ------------------------------------------------------------------------
71
 
72
// This file rather assumes that the network is in use, and that therefore
73
// there is also a kernel, and so on....
74
 
75
#include <cyg/infra/testcase.h>         // CYG_TEST_FAIL et al
76
#include <cyg/infra/diag.h>             // diag_printf()
77
#include <cyg/kernel/kapi.h>            // Thread API
78
 
79
#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
80
#include <cyg/hal/hal_intr.h>           // Interrupt names
81
#include <cyg/hal/hal_ebsa285.h>        // Hardware definitions
82
 
83
// The EBSA has 4 hardware timers; timer 3 is the kernel's realtime clock
84
// because it is connected to a separate, indepenent 3.68MHz signal; timer
85
// 4 can be used as a watchdog.  So we have timers 1 and 2 to use.
86
// Timers 1 and 2 have an input clock of 50MHz on fclk_in.
87
// Timer 2 should be initialized for periodic interrupts per 500uS.
88
// Timer 1 should be initialized for a one-shot interrupt after 1mS (1000uS).
89
//
90
// Timer 2's ISR examines the state of timer 1; if it has expired, the test
91
// has failed.  7 out of 8 hits, timer 1 is reinitialized for the 1mS; on
92
// the 8th event, timer1 is set for 2mS.  The next timer 2 event calls its
93
// DSR, which in turn signals a semaphore which awakens a real task, which
94
// again checks and re-initializes timer1 in the same way.
95
//
96
// All this ensures that interrupts are never delayed by more than 500uS,
97
// and that signalling a real task always takes less than 1500uS.
98
//
99
// This system, once activated, will run non-intrusively along with all
100
// networking tests.
101
//
102
// Special care (aka a hack) may be needed to make it work with the
103
// diagnostic channel; that disables interrupts typically for
104
//   100[characters] * 8[bits/byte] / 38400[Baud]  [Seconds] = 20mS.
105
 
106
// Use the fclk_in divided-by 256 mode:
107
#if 0 // Default, really 1mS, 2mS, 500uS
108
#define TNR_TIMER1_PERIOD_1mS     ((50 * 1000)     >>8)
109
#define TNR_TIMER1_PERIOD_2mS     ((50 * 1000 * 2) >>8)
110
#define TNR_TIMER2_PERIOD_500uS   ((50 *  500)     >>8)
111
#else // pushing the envelope... 1/5 as much:
112
#define FACTOR 200 // 1000 is "normal"
113
#define TNR_TIMER1_PERIOD_1mS     ((50 * FACTOR)     >>8)
114
#define TNR_TIMER1_PERIOD_2mS     ((50 * FACTOR * 2) >>8)
115
#define TNR_TIMER2_PERIOD_500uS   ((50 * FACTOR / 2) >>8)
116
#endif
117
 
118
#define TNR_TIMER1_INIT   (0x88)  // Enabled, free running, fclk_in/256
119
#define TNR_TIMER2_INIT   (0xc8)  // Enabled, periodic, fclk_in/256
120
 
121
// This way, if timer1 is > TNR_TIMER1_PERIOD_2mS, then we know it has
122
// wrapped; its full range is 85 seconds, one would hope to get back in
123
// that time!
124
 
125
static volatile int tnr_active = 0;
126
static volatile int tnr_t2_counter = 0;
127
 
128
static  cyg_sem_t tnr_sema;
129
 
130
static char tnr_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
131
static cyg_thread tnr_thread_data;
132
static cyg_handle_t tnr_thread_handle;
133
 
134
static cyg_interrupt tnr_t1_intr, tnr_t2_intr;
135
static cyg_handle_t tnr_t1_inth, tnr_t2_inth;
136
 
137
struct {
138
    int timer1_isr;
139
    int timer2_isr;
140
    int timer2_isr_active;
141
    int timer2_dsr;
142
    int timer2_thd;
143
    int timer2_thd_active;
144
} tnr_activity_counts = { 0,0,0,0,0,0 };
145
 
146
 
147
static cyg_uint32 tnr_timer1_isr(cyg_vector_t vector, cyg_addrword_t data)
148
{
149
    tnr_activity_counts.timer1_isr++;
150
 
151
    if ( tnr_active )
152
        CYG_TEST_FAIL_EXIT( "test_net_realtime: Timer1 fired" );
153
 
154
    *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt (Data: don't care)
155
    HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_1 );
156
 
157
    return CYG_ISR_HANDLED;
158
}
159
 
160
static cyg_uint32 tnr_timer2_isr(cyg_vector_t vector, cyg_addrword_t data)
161
{
162
    tnr_activity_counts.timer2_isr++;
163
 
164
    *SA110_TIMER2_CLEAR = 0; // Clear any pending interrupt (Data: don't care)
165
    HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_2 );
166
 
167
    if ( tnr_active ) {
168
        tnr_activity_counts.timer2_isr_active++;
169
        if ( (*SA110_TIMER1_VALUE) > (4 * TNR_TIMER1_PERIOD_1mS) ) {
170
            // Then it has wrapped around, bad bad bad
171
            CYG_TEST_FAIL_EXIT( "tnr_timer2_isr: Timer1 wrapped" );
172
        }
173
    }
174
    tnr_t2_counter++;
175
    // We go though each of the following states in turn:
176
    switch ( tnr_t2_counter & 7 ) {
177
    case 0:
178
        // Then this is an 8th event:
179
        *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS;
180
        return CYG_ISR_HANDLED;
181
    case 1:
182
        return CYG_ISR_CALL_DSR; // See how long to call a DSR &c..
183
        // without resetting timer1: 1500uS left now
184
    default:
185
        // Reset timer1 again.  By doing this in time every time it should
186
        // never fire.
187
        *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS;
188
    }
189
    return CYG_ISR_HANDLED;
190
}
191
 
192
static void tnr_timer2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
193
{
194
    tnr_activity_counts.timer2_dsr++;
195
 
196
    if ( CYGNUM_HAL_INTERRUPT_TIMER_2 != vector )
197
        CYG_TEST_FAIL_EXIT( "tnr_timer2_dsr: Bad vector" );
198
 
199
    cyg_semaphore_post( &tnr_sema );
200
}
201
 
202
static void tnr_timer2_service_thread( cyg_addrword_t param )
203
{
204
    while (1) {
205
        cyg_semaphore_wait( &tnr_sema );
206
        tnr_activity_counts.timer2_thd++;
207
        if ( tnr_active ) {
208
            tnr_activity_counts.timer2_thd_active++;
209
            if ( (*SA110_TIMER1_VALUE) > (4 * TNR_TIMER1_PERIOD_1mS) ) {
210
                // Then it has wrapped around, bad bad bad
211
                CYG_TEST_FAIL_EXIT( "tnr_timer2_service_thread: Timer1 wrapped" );
212
            }
213
        }
214
        // Reset timer1 again.  By doing this in time every time it should
215
        // never fire.
216
        *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS;
217
    }
218
}
219
 
220
 
221
static void tnr_init( void )
222
{
223
    // init the semaphore
224
    cyg_semaphore_init( &tnr_sema, 0 );
225
 
226
    // create and start the thread
227
    cyg_thread_create(2,                  // Priority - just a number
228
                      tnr_timer2_service_thread,
229
                      0,                  // entry parameter
230
                      "Test Net Realtime tnr_timer2_service_thread",
231
                     &tnr_stack[0],       // Stack
232
                      sizeof(tnr_stack),  // Size
233
                      &tnr_thread_handle, // Handle
234
                      &tnr_thread_data    // Thread data structure
235
        );
236
    cyg_thread_resume( tnr_thread_handle );
237
 
238
    // set up and attach the interrupts et al...
239
    cyg_interrupt_create(
240
        CYGNUM_HAL_INTERRUPT_TIMER_2,   /* Vector to attach to       */
241
        0,                              /* Queue priority            */
242
        0,                              /* Data pointer              */
243
        tnr_timer2_isr,                 /* Interrupt Service Routine */
244
        tnr_timer2_dsr,                 /* Deferred Service Routine  */
245
        &tnr_t2_inth,                   /* returned handle           */
246
        &tnr_t2_intr                    /* put interrupt here        */
247
        );
248
 
249
    cyg_interrupt_create(
250
        CYGNUM_HAL_INTERRUPT_TIMER_1,   /* Vector to attach to       */
251
        0,                              /* Queue priority            */
252
        0,                              /* Data pointer              */
253
        tnr_timer1_isr,                 /* Interrupt Service Routine */
254
        tnr_timer2_dsr, /* re-use! */   /* Deferred Service Routine  */
255
        &tnr_t1_inth,                   /* returned handle           */
256
        &tnr_t1_intr                    /* put interrupt here        */
257
        );
258
 
259
    cyg_interrupt_attach( tnr_t1_inth );
260
    cyg_interrupt_attach( tnr_t2_inth );
261
 
262
    *SA110_TIMER1_CONTROL = 0;          // Disable while we are setting up
263
    *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS;
264
    *SA110_TIMER1_CLEAR = 0;            // Clear any pending interrupt
265
    *SA110_TIMER1_CONTROL = TNR_TIMER1_INIT;
266
    *SA110_TIMER1_CLEAR = 0;            // Clear any pending interrupt again
267
 
268
    *SA110_TIMER2_CONTROL = 0;          // Disable while we are setting up
269
    *SA110_TIMER2_LOAD = TNR_TIMER2_PERIOD_500uS;
270
    *SA110_TIMER2_CLEAR = 0;            // Clear any pending interrupt
271
    *SA110_TIMER2_CONTROL = TNR_TIMER2_INIT;
272
    *SA110_TIMER2_CLEAR = 0;            // Clear any pending interrupt again
273
 
274
    cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_2 );
275
    cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_1 );
276
}
277
 
278
static void tnr_print_activity( void )
279
{
280
    int tmp = tnr_active;
281
    tnr_active = 0;
282
    diag_printf( "Test-net-realtime: interrupt activity log:\n" );
283
    diag_printf( "    timer1_isr %10d\n", tnr_activity_counts.timer1_isr );
284
    diag_printf( "    timer2_isr %10d\n", tnr_activity_counts.timer2_isr );
285
    diag_printf( "      (active) %10d\n", tnr_activity_counts.timer2_isr_active );
286
    diag_printf( "    timer2_dsr %10d\n", tnr_activity_counts.timer2_dsr );
287
    diag_printf( "    timer2_thd %10d\n", tnr_activity_counts.timer2_thd );
288
    diag_printf( "      (active) %10d\n", tnr_activity_counts.timer2_thd_active );
289
    tnr_active = tmp;
290
}
291
 
292
#endif /* ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H */
293
 
294
/* EOF test_net_realtime.h */

powered by: WebSVN 2.1.0

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