Mercurial > flash_v2
comparison packages/devs/eth/arm/ebsa285/current/tests/test_net_realtime.h @ 88:afdeb44241de ecos-sw-2000-05-12
Merge from eCos master repository on 2000-05-12-07:47:04-BST
| author | jlarmour |
|---|---|
| date | Fri, 12 May 2000 17:53:32 +0000 |
| parents | |
| children | 70190fa0fe10 |
comparison
equal
deleted
inserted
replaced
| 87:008177d90c43 | 88:afdeb44241de |
|---|---|
| 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 | |
| 4 /*========================================================================== | |
| 5 // | |
| 6 // test_net_realtime.h | |
| 7 // | |
| 8 // Auxiliary test header file | |
| 9 // Provide a thread that runs on EBSA only, which verifies that | |
| 10 // realtime characteristics are preserved. | |
| 11 // | |
| 12 //========================================================================== | |
| 13 //####COPYRIGHTBEGIN#### | |
| 14 // | |
| 15 // ------------------------------------------- | |
| 16 // The contents of this file are subject to the Red Hat eCos Public License | |
| 17 // Version 1.1 (the "License"); you may not use this file except in | |
| 18 // compliance with the License. You may obtain a copy of the License at | |
| 19 // http://www.redhat.com/ | |
| 20 // | |
| 21 // Software distributed under the License is distributed on an "AS IS" | |
| 22 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 23 // License for the specific language governing rights and limitations under | |
| 24 // the License. | |
| 25 // | |
| 26 // The Original Code is eCos - Embedded Configurable Operating System, | |
| 27 // released September 30, 1998. | |
| 28 // | |
| 29 // The Initial Developer of the Original Code is Red Hat. | |
| 30 // Portions created by Red Hat are | |
| 31 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. | |
| 32 // All Rights Reserved. | |
| 33 // ------------------------------------------- | |
| 34 // | |
| 35 //####COPYRIGHTEND#### | |
| 36 //========================================================================== | |
| 37 //#####DESCRIPTIONBEGIN#### | |
| 38 // | |
| 39 // Author(s): hmt | |
| 40 // Contributors: hmt | |
| 41 // Date: 2000-05-03 | |
| 42 // Description: | |
| 43 // | |
| 44 //####DESCRIPTIONEND#### | |
| 45 */ | |
| 46 | |
| 47 // This file rather assumes that the network is in use, and that therefore | |
| 48 // there is also a kernel, and so on.... | |
| 49 | |
| 50 #include <cyg/kernel/kapi.h> // Thread API | |
| 51 | |
| 52 #include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL | |
| 53 #include <cyg/hal/hal_intr.h> // Interrupt names | |
| 54 #include <cyg/hal/hal_ebsa285.h> // Hardware definitions | |
| 55 | |
| 56 // The EBSA has 4 hardware timers; timer 3 is the kernel's realtime clock | |
| 57 // because it is connected to a separate, indepenent 3.68MHz signal; timer | |
| 58 // 4 can be used as a watchdog. So we have timers 1 and 2 to use. | |
| 59 // Timers 1 and 2 have an input clock of 50MHz on fclk_in. | |
| 60 // Timer 2 should be initialized for periodic interrupts per 500uS. | |
| 61 // Timer 1 should be initialized for a one-shot interrupt after 1mS (1000uS). | |
| 62 // | |
| 63 // Timer 2's ISR examines the state of timer 1; if it has expired, the test | |
| 64 // has failed. 7 out of 8 hits, timer 1 is reinitialized for the 1mS; on | |
| 65 // the 8th event, timer1 is set for 2mS. The next timer 2 event calls its | |
| 66 // DSR, which in turn signals a semaphore which awakens a real task, which | |
| 67 // again checks and re-initializes timer1 in the same way. | |
| 68 // | |
| 69 // All this ensures that interrupts are never delayed by more than 500uS, | |
| 70 // and that signalling a real task always takes less than 1500uS. | |
| 71 // | |
| 72 // This system, once activated, will run non-intrusively along with all | |
| 73 // networking tests. | |
| 74 // | |
| 75 // Special care (aka a hack) may be needed to make it work with the | |
| 76 // diagnostic channel; that disables interrupts typically for | |
| 77 // 100[characters] * 8[bits/byte] / 38400[Baud] [Seconds] = 20mS. | |
| 78 | |
| 79 // Use the fclk_in divided-by 256 mode: | |
| 80 #define TNR_TIMER1_PERIOD_1mS ((50 * 1000) >>8) | |
| 81 #define TNR_TIMER1_PERIOD_2mS ((50 * 1000 * 2) >>8) | |
| 82 #define TNR_TIMER2_PERIOD_500uS ((50 * 500) >>8) | |
| 83 | |
| 84 #define TNR_TIMER1_INIT (0x88) // Enabled, free running, fclk_in/256 | |
| 85 #define TNR_TIMER2_INIT (0xc8) // Enabled, periodic, fclk_in/256 | |
| 86 | |
| 87 // This way, if timer1 is > TNR_TIMER1_PERIOD_2mS, then we know it has | |
| 88 // wrapped; its full range is 85 seconds, one would hope to get back in | |
| 89 // that time! | |
| 90 | |
| 91 static volatile int tnr_active = 0; | |
| 92 static volatile int tnr_t2_counter = 0; | |
| 93 | |
| 94 static cyg_sem_t tnr_sema; | |
| 95 | |
| 96 static char tnr_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; | |
| 97 static cyg_thread tnr_thread_data; | |
| 98 static cyg_handle_t tnr_thread_handle; | |
| 99 | |
| 100 static cyg_interrupt tnr_t1_intr, tnr_t2_intr; | |
| 101 static cyg_handle_t tnr_t1_inth, tnr_t2_inth; | |
| 102 | |
| 103 | |
| 104 | |
| 105 static cyg_uint32 tnr_timer1_isr(cyg_vector_t vector, cyg_addrword_t data) | |
| 106 { | |
| 107 if ( tnr_active ) | |
| 108 CYG_TEST_FAIL( "test_net_realtime: Timer1 fired" ); | |
| 109 | |
| 110 *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt (Data: don't care) | |
| 111 HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_1 ); | |
| 112 | |
| 113 return CYG_ISR_HANDLED; | |
| 114 } | |
| 115 | |
| 116 static cyg_uint32 tnr_timer2_isr(cyg_vector_t vector, cyg_addrword_t data) | |
| 117 { | |
| 118 *SA110_TIMER2_CLEAR = 0; // Clear any pending interrupt (Data: don't care) | |
| 119 HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_TIMER_2 ); | |
| 120 | |
| 121 if ( tnr_active ) { | |
| 122 if ( (*SA110_TIMER1_VALUE) > (4 * TNR_TIMER1_PERIOD_1mS) ) { | |
| 123 // Then it has wrapped around, bad bad bad | |
| 124 CYG_TEST_FAIL( "tnr_timer2_isr: Timer1 wrapped" ); | |
| 125 } | |
| 126 } | |
| 127 tnr_t2_counter++; | |
| 128 // We go though each of the following states in turn: | |
| 129 switch ( tnr_t2_counter & 7 ) { | |
| 130 case 0: | |
| 131 // Then this is an 8th event: | |
| 132 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS; | |
| 133 return CYG_ISR_HANDLED; | |
| 134 case 1: | |
| 135 return CYG_ISR_CALL_DSR; // See how long to call a DSR &c.. | |
| 136 // without resetting timer1: 1500uS left now | |
| 137 default: | |
| 138 // Reset timer1 again. By doing this in time every time it should | |
| 139 // never fire. | |
| 140 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS; | |
| 141 } | |
| 142 return CYG_ISR_HANDLED; | |
| 143 } | |
| 144 | |
| 145 static void tnr_timer2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) | |
| 146 { | |
| 147 if ( CYGNUM_HAL_INTERRUPT_TIMER_2 != vector ) | |
| 148 CYG_TEST_FAIL( "tnr_timer2_dsr: Bad vector" ); | |
| 149 | |
| 150 cyg_semaphore_post( &tnr_sema ); | |
| 151 } | |
| 152 | |
| 153 static void tnr_timer2_service_thread( cyg_addrword_t param ) | |
| 154 { | |
| 155 while (1) { | |
| 156 cyg_semaphore_wait( &tnr_sema ); | |
| 157 if ( tnr_active ) { | |
| 158 if ( (*SA110_TIMER1_VALUE) > (4 * TNR_TIMER1_PERIOD_1mS) ) { | |
| 159 // Then it has wrapped around, bad bad bad | |
| 160 CYG_TEST_FAIL( "tnr_timer2_service_thread: Timer1 wrapped" ); | |
| 161 } | |
| 162 } | |
| 163 // Reset timer1 again. By doing this in time every time it should | |
| 164 // never fire. | |
| 165 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_1mS; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 | |
| 170 static void tnr_init( void ) | |
| 171 { | |
| 172 // init the semaphore | |
| 173 cyg_semaphore_init( &tnr_sema, 0 ); | |
| 174 | |
| 175 // create and start the thread | |
| 176 cyg_thread_create(2, // Priority - just a number | |
| 177 tnr_timer2_service_thread, | |
| 178 0, // entry parameter | |
| 179 "Test Net Realtime tnr_timer2_service_thread", | |
| 180 &tnr_stack[0], // Stack | |
| 181 sizeof(tnr_stack), // Size | |
| 182 &tnr_thread_handle, // Handle | |
| 183 &tnr_thread_data // Thread data structure | |
| 184 ); | |
| 185 cyg_thread_resume( tnr_thread_handle ); | |
| 186 | |
| 187 // set up and attach the interrupts et al... | |
| 188 cyg_interrupt_create( | |
| 189 CYGNUM_HAL_INTERRUPT_TIMER_2, /* Vector to attach to */ | |
| 190 0, /* Queue priority */ | |
| 191 0, /* Data pointer */ | |
| 192 tnr_timer2_isr, /* Interrupt Service Routine */ | |
| 193 tnr_timer2_dsr, /* Deferred Service Routine */ | |
| 194 &tnr_t2_inth, /* returned handle */ | |
| 195 &tnr_t2_intr /* put interrupt here */ | |
| 196 ); | |
| 197 | |
| 198 cyg_interrupt_create( | |
| 199 CYGNUM_HAL_INTERRUPT_TIMER_1, /* Vector to attach to */ | |
| 200 0, /* Queue priority */ | |
| 201 0, /* Data pointer */ | |
| 202 tnr_timer1_isr, /* Interrupt Service Routine */ | |
| 203 tnr_timer2_dsr, /* re-use! */ /* Deferred Service Routine */ | |
| 204 &tnr_t1_inth, /* returned handle */ | |
| 205 &tnr_t1_intr /* put interrupt here */ | |
| 206 ); | |
| 207 | |
| 208 cyg_interrupt_attach( tnr_t1_inth ); | |
| 209 cyg_interrupt_attach( tnr_t2_inth ); | |
| 210 | |
| 211 *SA110_TIMER1_CONTROL = 0; // Disable while we are setting up | |
| 212 *SA110_TIMER1_LOAD = TNR_TIMER1_PERIOD_2mS; | |
| 213 *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt | |
| 214 *SA110_TIMER1_CONTROL = TNR_TIMER1_INIT; | |
| 215 *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt again | |
| 216 | |
| 217 *SA110_TIMER2_CONTROL = 0; // Disable while we are setting up | |
| 218 *SA110_TIMER2_LOAD = TNR_TIMER2_PERIOD_500uS; | |
| 219 *SA110_TIMER2_CLEAR = 0; // Clear any pending interrupt | |
| 220 *SA110_TIMER2_CONTROL = TNR_TIMER2_INIT; | |
| 221 *SA110_TIMER2_CLEAR = 0; // Clear any pending interrupt again | |
| 222 | |
| 223 cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_2 ); | |
| 224 cyg_interrupt_unmask( CYGNUM_HAL_INTERRUPT_TIMER_1 ); | |
| 225 } | |
| 226 | |
| 227 #endif /* ifndef CYGONCE_DEVS_ETH_ARM_EBSA285_TESTS_TEST_NET_REALTIME_H */ | |
| 228 | |
| 229 /* EOF test_net_realtime.h */ |
