Mercurial > ecos
annotate packages/hal/sparclite/sleb/current/tests/slebintr.c @ 208:e0c0827131d1 ecos
Merge from eCos master repository on 2002-05-20-20:11:54-BST
| author | jlarmour |
|---|---|
| date | Mon, 20 May 2002 22:19:26 +0000 |
| parents | bf00f99aec69 |
| children | d2c90368aeef |
| rev | line source |
|---|---|
| 2 | 1 /*================================================================= |
| 2 // | |
| 3 // slebintr.c | |
| 4 // | |
| 5 // SPARClite HAL interrupt manipulation test | |
| 6 // | |
| 7 //========================================================================== | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
8 //####ECOSGPLCOPYRIGHTBEGIN#### |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
9 // ------------------------------------------- |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
10 // This file is part of eCos, the Embedded Configurable Operating System. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
12 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
13 // eCos is free software; you can redistribute it and/or modify it under |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
14 // the terms of the GNU General Public License as published by the Free |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
15 // Software Foundation; either version 2 or (at your option) any later version. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
16 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
20 // for more details. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
21 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
22 // You should have received a copy of the GNU General Public License along |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
23 // with eCos; if not, write to the Free Software Foundation, Inc., |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
25 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
26 // As a special exception, if other files instantiate templates or use macros |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
27 // or inline functions from this file, or you compile this file and link it |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
28 // with other works to produce a work based on this file, this file does not |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
29 // by itself cause the resulting work to be covered by the GNU General Public |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
30 // License. However the source code for this file must still be made available |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
31 // in accordance with section (3) of the GNU General Public License. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
32 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
33 // This exception does not invalidate any other reasons why a work based on |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
34 // this file might be covered by the GNU General Public License. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
35 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
37 // at http://sources.redhat.com/ecos/ecos-license |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
38 // ------------------------------------------- |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
66
diff
changeset
|
39 //####ECOSGPLCOPYRIGHTEND#### |
| 2 | 40 //========================================================================== |
| 41 //#####DESCRIPTIONBEGIN#### | |
| 42 // | |
| 43 // Author(s): dsm | |
| 44 // Contributors: dsm, nickg | |
| 45 // Date: 1998-06-18 | |
| 46 //####DESCRIPTIONEND#### | |
| 47 */ | |
| 48 | |
| 49 #include <pkgconf/system.h> | |
| 50 | |
| 51 #include <pkgconf/hal.h> | |
| 52 | |
| 53 #include <cyg/infra/cyg_type.h> | |
| 54 | |
| 55 #include <cyg/infra/cyg_ass.h> | |
| 56 | |
| 57 #include <cyg/infra/testcase.h> | |
| 58 | |
| 59 #include <cyg/hal/hal_arch.h> | |
| 60 #include <cyg/hal/hal_intr.h> | |
| 61 #include <cyg/hal/hal_diag.h> | |
| 62 #include <cyg/hal/hal_clock.h> | |
| 63 | |
| 64 #include <pkgconf/infra.h> | |
| 65 | |
| 66 #include <cyg/infra/diag.h> | |
| 67 | |
| 68 #define DELAY(x) \ | |
| 69 CYG_MACRO_START int i; for (i = 0; i < x; i++); CYG_MACRO_END | |
| 70 | |
| 71 #define DLA 100 | |
| 72 | |
| 73 static int l, u, m, j; | |
| 74 | |
| 75 int levels[ 16 ]; | |
| 76 int ups[ 16 ]; | |
| 77 int masks[ 16 ]; | |
| 78 int reqs[ 16 ]; | |
| 79 | |
| 80 #define XDIGIT( q ) (q + ((q < 10) ? '0' : ('A'-10) )) | |
| 81 | |
| 82 #define SETSTR( x, y, str ) CYG_MACRO_START \ | |
| 83 str[0] = XDIGIT( x ); \ | |
| 84 str[1] = XDIGIT( y ); \ | |
| 85 CYG_MACRO_END | |
| 86 | |
| 87 static char lstr[] = "xy Bad level"; | |
| 88 static char mstr[] = "xy Bad mask"; | |
| 89 static char ustr[] = "xy Bad up"; | |
| 90 | |
| 91 | |
| 92 static void checkallbut( int z ) | |
| 93 { | |
| 94 int i; | |
| 95 for ( i = 1; i < 16; i++ ) { | |
| 96 int level, up, hipri, mask, req; | |
| 97 if ( z == i ) | |
| 98 continue; | |
| 99 | |
| 100 SETSTR( i, z, lstr ); | |
| 101 SETSTR( i, z, mstr ); | |
| 102 SETSTR( i, z, ustr ); | |
| 103 | |
| 104 HAL_INTERRUPT_QUERY_INFO( i, level, up, hipri, mask, req); | |
| 105 l = level; | |
| 106 u = up; | |
| 107 m = mask; | |
| 108 j = i; | |
| 109 | |
| 110 #if 0 // for manual testing really... | |
| 111 if ( level != levels[i] ) | |
| 112 CYG_TEST_INFO( lstr ); | |
| 113 if ( up != ups[i] ) | |
| 114 CYG_TEST_INFO( ustr ); | |
| 115 if ( mask != masks[i] ) | |
| 116 CYG_TEST_INFO( mstr ); | |
| 117 if ( (level != levels[i] ) | |
| 118 | ( up != ups[i] ) | |
| 119 | ( mask != masks[i] ) ) { | |
| 120 CYG_TEST_INFO( "Re-reading" ); | |
| 121 HAL_INTERRUPT_QUERY_INFO( i, level, up, hipri, mask, req); | |
| 122 } | |
| 123 #endif | |
| 124 CYG_TEST_CHECK( level == levels[i], lstr ); | |
| 125 CYG_TEST_CHECK( up == ups[i], ustr ); | |
| 126 CYG_TEST_CHECK( mask == masks[i], mstr ); | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 // input is the active phase of the chosen interrupt. It is assumed that | |
| 131 // the source is normally level-sensititve rather than edge-sensitive. | |
| 132 static void interferewith( int which, int input ) | |
| 133 { | |
| 134 int level, up, hipri, mask, req; | |
| 135 | |
| 136 // Interfere with interrupt 'which' | |
| 137 HAL_INTERRUPT_CONFIGURE( which, 1, input ); // should be no change | |
| 138 | |
| 139 checkallbut( 0 ); // so don't exclude any of them | |
| 140 | |
| 141 HAL_INTERRUPT_CONFIGURE( which, 1, !input ); // make it other-sensitive | |
| 142 DELAY( DLA ); | |
| 143 HAL_INTERRUPT_ACKNOWLEDGE( which ); | |
| 144 DELAY( DLA ); | |
| 145 HAL_INTERRUPT_QUERY_INFO( which, level, up, hipri, mask, req); | |
| 146 CYG_TEST_CHECK( 0 != level , "Int not level-sensitive (-ve level)" ); | |
| 147 if ( input ) | |
| 148 CYG_TEST_CHECK( 0 == up, "Int high level (-ve level)" ); | |
| 149 else | |
| 150 CYG_TEST_CHECK( 0 != up, "Int low level (-ve level)" ); | |
| 151 CYG_TEST_CHECK( 0 != mask , "Int unmasked (-ve level)" ); | |
| 152 CYG_TEST_CHECK( 0 != req , "Int not requesting (-ve level)" ); | |
| 153 checkallbut( which ); // don't check #which, we're messing with it | |
| 154 | |
| 155 HAL_INTERRUPT_CONFIGURE( which, 0, input ); // edge, default sense | |
| 156 DELAY( DLA ); | |
| 157 HAL_INTERRUPT_ACKNOWLEDGE( which ); | |
| 158 DELAY( DLA ); | |
| 159 HAL_INTERRUPT_QUERY_INFO( which, level, up, hipri, mask, req); | |
| 160 CYG_TEST_CHECK( 0 == level , "Int not edge-sensitive (+ve edge)" ); | |
| 161 if ( input ) | |
| 162 CYG_TEST_CHECK( 0 != up, "Int low edge (+ve edge)" ); | |
| 163 else | |
| 164 CYG_TEST_CHECK( 0 == up, "Int high edge (+ve edge)" ); | |
| 165 CYG_TEST_CHECK( 0 != mask , "Int unmasked (+ve edge)" ); | |
| 166 CYG_TEST_CHECK( 0 == req , "Int requesting (+ve edge)" ); | |
| 167 checkallbut( which ); // don't check #which, we're messing with it | |
| 168 | |
| 169 HAL_INTERRUPT_CONFIGURE( which, 0, !input ); // edge, opposite sense | |
| 170 DELAY( DLA ); | |
| 171 HAL_INTERRUPT_ACKNOWLEDGE( which ); | |
| 172 DELAY( DLA ); | |
| 173 HAL_INTERRUPT_QUERY_INFO( which, level, up, hipri, mask, req); | |
| 174 CYG_TEST_CHECK( 0 == level , "Int not edge-sensitive (-ve edge)" ); | |
| 175 if ( input ) | |
| 176 CYG_TEST_CHECK( 0 == up, "Int high edge (-ve edge)" ); | |
| 177 else | |
| 178 CYG_TEST_CHECK( 0 != up, "Int low edge (-ve edge)" ); | |
| 179 CYG_TEST_CHECK( 0 != mask , "Int unmasked (-ve edge)" ); | |
| 180 CYG_TEST_CHECK( 0 == req , "Int requesting (-ve edge)" ); | |
| 181 checkallbut( which ); // don't check #which, we're messing with it | |
| 182 | |
| 183 HAL_INTERRUPT_CONFIGURE( which, 1, input ); // back to original value | |
| 184 DELAY( DLA ); | |
| 185 HAL_INTERRUPT_ACKNOWLEDGE( which ); | |
| 186 DELAY( DLA ); | |
| 187 checkallbut( 0 ); // so don't exclude any of them | |
| 188 } | |
| 189 | |
| 190 // ------------------------------------------------------------------------ | |
| 191 | |
| 192 #ifndef CYGPKG_KERNEL | |
| 193 // then the clock is not initialized! | |
| 194 #undef HAL_CLOCK_READ | |
| 195 // so provide a dumb counter, so we do the test a number of times anyway. | |
| 196 static int pseudotime = 0; | |
| 197 #define HAL_CLOCK_READ( _pval_ ) *(_pval_) = \ | |
| 198 ((pseudotime > 10) ? (pseudotime = 0) : ++pseudotime) | |
| 199 #endif | |
| 200 | |
| 201 static int start( void ) | |
| 202 { | |
| 203 // We'll mess about with these interrupt sources: | |
| 204 // 13 : EX_IRQ13 from expansion board, active HIGH | |
| 205 // 12 : EX_IRQ12 from expansion board, active LOW | |
| 206 // 4 : EX_IRQ4 from expansion board, active LOW | |
| 207 // 3 : EX_IRQ3 from expansion board, active HIGH | |
| 208 | |
| 209 int i, hipri; | |
| 210 for ( i = 1; i < 16; i++ ) { | |
| 211 HAL_INTERRUPT_QUERY_INFO( i, levels[i], ups[i], | |
| 212 hipri, masks[i], reqs[i]); | |
| 213 } | |
| 214 CYG_TEST_CHECK( 0 != masks[13], "Int 13 unmasked initially" ); | |
| 215 CYG_TEST_CHECK( 0 != masks[12], "Int 12 unmasked initially" ); | |
| 216 CYG_TEST_CHECK( 0 != masks[ 4], "Int 4 unmasked initially" ); | |
| 217 CYG_TEST_CHECK( 0 != masks[ 3], "Int 3 unmasked initially" ); | |
| 218 CYG_TEST_CHECK( 0 == reqs[13], "Int 13 requests initially" ); | |
| 219 CYG_TEST_CHECK( 0 == reqs[12], "Int 12 requests initially" ); | |
| 220 CYG_TEST_CHECK( 0 == reqs[ 4], "Int 4 requests initially" ); | |
| 221 CYG_TEST_CHECK( 0 == reqs[ 3], "Int 3 requests initially" ); | |
| 222 CYG_TEST_CHECK( 0 != levels[13], "Int 13 edgetrig initially" ); | |
| 223 CYG_TEST_CHECK( 0 != levels[12], "Int 12 edgetrig initially" ); | |
| 224 CYG_TEST_CHECK( 0 != levels[ 4], "Int 4 edgetrig initially" ); | |
| 225 CYG_TEST_CHECK( 0 != levels[ 3], "Int 3 edgetrig initially" ); | |
| 226 CYG_TEST_CHECK( 0 != ups[13], "Int 13 not up initially" ); | |
| 227 CYG_TEST_CHECK( 0 == ups[12], "Int 12 is up initially" ); | |
| 228 CYG_TEST_CHECK( 0 == ups[ 4], "Int 4 is up initially" ); | |
| 229 CYG_TEST_CHECK( 0 != ups[ 3], "Int 3 not up initially" ); | |
| 230 | |
| 231 checkallbut( 0 ); // don't exclude any of them | |
| 232 | |
| 233 // I want to run this loop for 100 centiSeconds, so that 100 clock | |
| 234 // interrupts have occurred whilst interfering with the other interrupt | |
| 235 // state, to provoke possible problems with interactions there. On a | |
| 236 // 100MHz 86832 with default configuration, this usually gives 1200 | |
| 237 // loops in total, 12 per centiSecond. But with config variance and | |
| 238 // caching behaviour, it's quite possible for this loop to take much | |
| 239 // longer, if it takes over 1/2 a centiSecond, aliasing effects could | |
| 240 // cause the timing to fail completely, causing test timeouts. Hence | |
| 241 // the additional loop limit of 20 times round the inner loop, aiming | |
| 242 // for a maximum elapsed time of 20 S maximum, plus extra chances to | |
| 243 // break out part way through the loop if a tick has passed. | |
| 244 | |
| 245 hipri = 0; | |
| 246 CYG_TEST_INFO( "About to configure interrupts" ); | |
| 247 for ( i = 0; i < 100; i++ ) { | |
| 248 int t1, t2, j; | |
| 249 HAL_CLOCK_READ( &t1 ); | |
| 250 // Do this while/until there is a clock tick | |
| 251 // ie. some interrupt activity: | |
| 252 for ( j = 0; j < 20; j++ ) { | |
| 253 t2 = t1; | |
| 254 hipri++; | |
| 255 interferewith( 13, 1 ); | |
| 256 interferewith( 3, 1 ); | |
| 257 interferewith( 4, 0 ); | |
| 258 HAL_CLOCK_READ( &t1 ); | |
| 259 if ( t1 < t2 ) | |
| 260 break; // clock has wrapped | |
| 261 t2 = t1; | |
| 262 interferewith( 12, 0 ); | |
| 263 interferewith( 3, 1 ); | |
| 264 interferewith( 3, 1 ); | |
| 265 HAL_CLOCK_READ( &t1 ); | |
| 266 if ( t1 < t2 ) | |
| 267 break; // clock has wrapped | |
| 268 t2 = t1; | |
| 269 interferewith( 4, 0 ); | |
| 270 interferewith( 13, 1 ); | |
| 271 interferewith( 12, 0 ); | |
| 272 interferewith( 12, 0 ); | |
| 273 HAL_CLOCK_READ( &t1 ); | |
| 274 if ( t1 < t2 ) | |
| 275 break; // clock has wrapped | |
| 276 } | |
| 277 } | |
| 278 CYG_TEST_PASS( "Configured interrupts 3,4,12 & 13 a great deal" ); | |
| 279 return hipri; | |
| 280 } | |
| 281 | |
| 282 // ------------------------------------------------------------------------- | |
| 283 | |
| 284 externC void | |
| 285 #ifdef CYGPKG_KERNEL | |
| 286 cyg_user_start( void ) | |
| 287 #else | |
| 288 cyg_start( void ) | |
| 289 #endif | |
| 290 { | |
| 291 int loops; | |
| 292 CYG_TEST_INIT(); | |
| 293 CYG_TEST_INFO( "cyg_user_start()" ); | |
| 294 HAL_ENABLE_INTERRUPTS(); | |
| 295 loops = start(); | |
| 296 // Typically about 1200 loops execute on the 33MHz 86832; | |
| 297 // I hoped to put in a check that we hadn't wasted time in | |
| 298 // spurious interrupts, but kernel instrumentation, for example, | |
| 299 // is more than enough to slow the world down... so keep this | |
| 300 // very weak test in, as a placeholder. | |
| 301 CYG_TEST_CHECK( 100 <= loops, "Not enough tests executed" ); | |
| 302 CYG_TEST_EXIT( "All done" ); | |
| 303 } | |
| 304 | |
| 305 // ------------------------------------------------------------------------- | |
| 306 | |
| 307 /* EOF slebintr.c */ |
