1 #ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H
2 #define CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H
3 /*==========================================================================
7 // Auxiliary test header file
8 // Provide a thread that runs on EBSA only, which verifies that
9 // realtime characteristics are preserved.
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.
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.
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
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.
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.
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.
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####
52 //####DESCRIPTIONEND####
55 // This is the API to this file:
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()
62 // Tests should use these if they are defined to test that the realtime
63 // characteristics of the world are preserved during a test.
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
70 // ------------------------------------------------------------------------
72 // This file rather assumes that the network is in use, and that therefore
73 // there is also a kernel, and so on....
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
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
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).
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.
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.
99 // This system, once activated, will run non-intrusively along with all
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.
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)
118 #define TNR_TIMER1_INIT (0x88) // Enabled, free running, fclk_in/256
119 #define TNR_TIMER2_INIT (0xc8) // Enabled, periodic, fclk_in/256
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
125 static volatile int tnr_active = 0;
126 static volatile int tnr_t2_counter = 0;
128 static cyg_sem_t tnr_sema;
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;
134 static cyg_interrupt tnr_t1_intr, tnr_t2_intr;
135 static cyg_handle_t tnr_t1_inth, tnr_t2_inth;
140 int timer2_isr_active;
143 int timer2_thd_active;
144 } tnr_activity_counts = { 0,0,0,0,0,0 };
147 static cyg_uint32 tnr_timer1_isr(cyg_vector_t vector, cyg_addrword_t data)
149 tnr_activity_counts.timer1_isr++;
152 CYG_TEST_FAIL_EXIT( "test_net_realtime: Timer1 fired" );
154 *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt (Data: don't care)
155 HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_1 );
157 return CYG_ISR_HANDLED;
160 static cyg_uint32 tnr_timer2_isr(cyg_vector_t vector, cyg_addrword_t data)
162 tnr_activity_counts.timer2_isr++;
164 *SA110_TIMER2_CLEAR = 0; // Clear any pending interrupt (Data: don't care)
165 HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_2 );
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" );
175 // We go though each of the following states in turn:
176 switch ( tnr_t2_counter & 7 ) {
178 // Then this is an 8th event:
179 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS;
180 return CYG_ISR_HANDLED;
182 return CYG_ISR_CALL_DSR; // See how long to call a DSR &c..
183 // without resetting timer1: 1500uS left now
185 // Reset timer1 again. By doing this in time every time it should
187 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS;
189 return CYG_ISR_HANDLED;
192 static void tnr_timer2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
194 tnr_activity_counts.timer2_dsr++;
196 if ( CYGNUM_HAL_INTERRUPT_TIMER_2 != vector )
197 CYG_TEST_FAIL_EXIT( "tnr_timer2_dsr: Bad vector" );
199 cyg_semaphore_post( &tnr_sema );
202 static void tnr_timer2_service_thread( cyg_addrword_t param )
205 cyg_semaphore_wait( &tnr_sema );
206 tnr_activity_counts.timer2_thd++;
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" );
214 // Reset timer1 again. By doing this in time every time it should
216 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS;
221 static void tnr_init( void )
223 // init the semaphore
224 cyg_semaphore_init( &tnr_sema, 0 );
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
236 cyg_thread_resume( tnr_thread_handle );
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 */
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 */
259 cyg_interrupt_attach( tnr_t1_inth );
260 cyg_interrupt_attach( tnr_t2_inth );
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
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
274 cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_2 );
275 cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_1 );
278 static void tnr_print_activity( void )
280 int tmp = tnr_active;
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 );
292 #endif /* ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H */
294 /* EOF test_net_realtime.h */