Changeset 2835b3a5 in rtems
- Timestamp:
- 02/01/02 15:15:02 (22 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 7de58239
- Parents:
- e6dec71c
- Location:
- c/src/lib/libcpu/mips
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libcpu/mips/ChangeLog
re6dec71c r2835b3a5 1 2001-02-01 Greg Menke <gregory.menke@gsfc.nasa.gov> 2 3 * Lots of tinkering and tuning as part of improving interrupt latency 4 and improving the per-task interrupt level control and FP mask handling. 5 With these modifications interrupt latency was measured at a worst-case 6 of 100us, average below 60 us on a 12 Mhz R3000 class CPU with 50 7 RTEMS tasks in the application. 8 * mongoosev/README: Updated. 9 * mongoosev/include/mongoose-v.h: Masks modified. 10 * mongoosev/vectorisrs/vectorisrs.c: Significant overhaul to address 11 software prioritization of interrupts. If a higher priority interrupt 12 occurs while we are looking for new interrupts, we will reinitiate the 13 scan of all interrupts. 14 * shared/interrupts/vectorexceptions.c: Removed warning and deleted 15 blank lines. 16 1 17 2002-01-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de> 2 18 -
c/src/lib/libcpu/mips/mongoosev/README
re6dec71c r2835b3a5 5 5 The Synova Mongoose-V is a radiation hardened derivative of the 6 6 LSI 33K with on-CPU peripherals. 7 8 Status 9 ====== 10 11 Per-task floating point enable/disable is supported for both immediate 12 and deferred FPU context swaps. 13 14 Interrupt Levels are adapted reasonably well to the MIPS interrupt 15 model. Bit 0 of the int level is a global enable/disable, corresponding 16 to bit 0 of the processor's SR register. Bits 1 thru 6 are configured 17 as masks for the Int0 thru Int5 interrupts. The 2 software interrupt 18 bits are always enabled by default. Each task maintains its own 19 Interrupt Level setting, reconfiguring the SR register's interrupt bits 20 whenever scheduled in. The software ints, though not addressable via 21 the various Interrupt Level functions, are maintained on a per-task 22 basis, so if software manipulates them directly, things should behave as 23 expected. At the time of these udpates, the Interrupt Level was only 8 24 bits, and completely supporting the global enable, software ints and the 25 hardware ints would require 9 bits. When more than 8 bits are 26 available, there is no reason the software interrupts could not be added 27 to the Interrupt Level. 28 29 While supporting the Int0 thru Int5 bits in this way doesn't seem 30 wonderfully useful, it does increase the level of compliance with the 31 RTEMS spec. 32 33 Interrupt Level 0 corresponds to interrupts globally enabled, software 34 ints enabled and Int0 thru Int5 enabled. If values other than 0 are 35 supplied, they should be formulated to impose the desired bitmask. 36 Interrupt priority is not a strong concept on this bsp, it is provided 37 only by the order in which interrupts are checked. 38 39 If during the vectoring of an interrupt, others arrive, they will all be 40 processed in accordance with their ordering in SR & the peripheral 41 register. For example, if while we're vectoring Int4, Int3 and Int5 are 42 asserted, Int3 will be serviced before Int5. The peripheral interrupts 43 are individually vectored as a consequence of Int5 being asserted, 44 however Int5 is not itself vectored. Within the set of peripheral 45 interrupts, bit 0 is vectored first, 31 is last. 46 47 Interrupts are not nested for MIPS1 or MIPS3 processors, but are 48 processed serially as possible. On an unloaded 50 task RTEMS program, 49 runnning on a 12mhz MIPS1 processor, worst-case latencies of 100us were 50 observed, the average being down at 60us or below. 51 52 53 These features are principally a consequence of fixes and tweaks to the 54 MIPS1 and MIPS3 processor support, and should be equally effective on 55 both levels of MIPS processors for any of their bsp's. 56 57 58 59 60 -
c/src/lib/libcpu/mips/mongoosev/include/mongoose-v.h
re6dec71c r2835b3a5 99 99 100 100 #define MONGOOSEV_UART_CMD_TX_ENABLE_1 \ 101 (MONGOOSEV_UART_CMD_TX_ENABLE << MONGOOSEV_UART 0_CMD_SHIFT)101 (MONGOOSEV_UART_CMD_TX_ENABLE << MONGOOSEV_UART1_CMD_SHIFT) 102 102 #define MONGOOSEV_UART_CMD_RX_ENABLE_1 \ 103 (MONGOOSEV_UART_CMD_RX_ENABLE << MONGOOSEV_UART 0_CMD_SHIFT)103 (MONGOOSEV_UART_CMD_RX_ENABLE << MONGOOSEV_UART1_CMD_SHIFT) 104 104 #define MONGOOSEV_UART_CMD_TX_READY_1 \ 105 (MONGOOSEV_UART_CMD_TX_READY << MONGOOSEV_UART 0_CMD_SHIFT)105 (MONGOOSEV_UART_CMD_TX_READY << MONGOOSEV_UART1_CMD_SHIFT) 106 106 #define MONGOOSEV_UART_CMD_PARITY_ENABLE_1 \ 107 (MONGOOSEV_UART_CMD_PARITY_ENABLE << MONGOOSEV_UART 0_CMD_SHIFT)107 (MONGOOSEV_UART_CMD_PARITY_ENABLE << MONGOOSEV_UART1_CMD_SHIFT) 108 108 #define MONGOOSEV_UART_CMD_PARITY_DISABLE_1 \ 109 (MONGOOSEV_UART_CMD_PARITY_DISABLE << MONGOOSEV_UART 0_CMD_SHIFT)109 (MONGOOSEV_UART_CMD_PARITY_DISABLE << MONGOOSEV_UART1_CMD_SHIFT) 110 110 #define MONGOOSEV_UART_CMD_PARITY_EVEN_1 \ 111 (MONGOOSEV_UART_CMD_PARITY_EVEN << MONGOOSEV_UART 0_CMD_SHIFT)111 (MONGOOSEV_UART_CMD_PARITY_EVEN << MONGOOSEV_UART1_CMD_SHIFT) 112 112 #define MONGOOSEV_UART_CMD_PARITY_ODD_1 \ 113 (MONGOOSEV_UART_CMD_PARITY_ODD << MONGOOSEV_UART 0_CMD_SHIFT)113 (MONGOOSEV_UART_CMD_PARITY_ODD << MONGOOSEV_UART1_CMD_SHIFT) 114 114 115 115 /* UART Bits in Peripheral Status and Interrupt Cause Register */ … … 131 131 #define MONGOOSEV_UART0_IRQ_SHIFT 11 132 132 #define MONGOOSEV_UART1_IRQ_SHIFT 17 133 134 #define MONGOOSEV_UART_FRAME_ERROR_0 \ 135 (MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART0_IRQ_SHIFT) 136 #define MONGOOSEV_UART_RX_OVERRUN_ERROR_0 \ 137 (MONGOOSEV_UART_RX_OVERRUN_ERROR << MONGOOSEV_UART0_IRQ_SHIFT) 138 #define MONGOOSEV_UART_TX_EMPTY_0 \ 139 (MONGOOSEV_UART_TX_EMPTY << MONGOOSEV_UART0_IRQ_SHIFT) 140 #define MONGOOSEV_UART_TX_READY_0 \ 141 (MONGOOSEV_UART_TX_READY << MONGOOSEV_UART0_IRQ_SHIFT) 142 #define MONGOOSEV_UART_RX_READY_0 \ 143 (MONGOOSEV_UART_RX_READY << MONGOOSEV_UART0_IRQ_SHIFT) 133 144 134 145 #define MONGOOSEV_UART_FRAME_ERROR_1 \ … … 143 154 (MONGOOSEV_UART_RX_READY << MONGOOSEV_UART1_IRQ_SHIFT) 144 155 145 #define MONGOOSEV_UART_FRAME_ERROR_0 \146 (MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)147 #define MONGOOSEV_UART_RX_OVERRUN_ERROR_0 \148 (MONGOOSEV_UART_RX_OVERRUN_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)149 #define MONGOOSEV_UART_TX_EMPTY_0 \150 (MONGOOSEV_UART_TX_EMPTY << MONGOOSEV_UART1_IRQ_SHIFT)151 #define MONGOOSEV_UART_TX_READY_0 \152 (MONGOOSEV_UART_TX_READY << MONGOOSEV_UART1_IRQ_SHIFT)153 #define MONGOOSEV_UART_RX_READY_0 \154 (MONGOOSEV_UART_RX_READY << MONGOOSEV_UART1_IRQ_SHIFT)155 156 156 /* 157 157 * Bits in the Peripheral Interrupt Mask Register … … 163 163 #define MONGOOSEV_EDAC_SERR_BIT 0x80000000 164 164 #define MONGOOSEV_EDAC_MERR_BIT 0x40000000 165 /* 29 - 24 reserved */ 165 166 #define MONGOOSEV_MAVN_WRITE_ACCESS 0x00800000 166 167 #define MONGOOSEV_MAVN_READ_ACCESS 0x00400000 167 /* 29 - 24 reserved */168 168 #define MONGOOSEV_UART_1_RX_READY 0x00200000 169 169 #define MONGOOSEV_UART_1_TX_READY 0x00100000 … … 188 188 #define MONGOOSEV_EXTERN_INT_1 0x00000002 189 189 #define MONGOOSEV_EXTERN_INT_0 0x00000001 190 191 192 /* 193 ** Peripheral Command bits (non-uart, those are defined above) 194 */ 195 #define MONGOOSEV_COMMAND_ENABLE_EDAC MONGOOSEV_EDAC_SERR_BIT 196 #define MONGOOSEV_COMMAND_OVERRIDE_EDAC MONGOOSEV_EDAC_MERR_BIT 197 190 198 191 199 -
c/src/lib/libcpu/mips/mongoosev/vectorisrs/vectorisrs.c
re6dec71c r2835b3a5 20 20 21 21 22 #include <bspIo.h> /* for printk */ 23 24 25 26 int mips_default_isr( int vector ) 27 { 28 unsigned int sr, sr2; 29 unsigned int cause; 30 31 mips_get_sr( sr ); 32 mips_get_cause( cause ); 33 34 sr2 = sr & ~0xff; 35 mips_set_sr(sr2); 36 37 printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", vector, cause, sr ); 38 rtems_fatal_error_occurred(1); 39 return 0; 40 } 41 42 /* userspace routine to assert either software interrupt */ 43 44 int assertSoftwareInterrupt( unsigned32 n ) 45 { 46 if( n<2 ) 47 { 48 unsigned32 c; 49 50 mips_get_cause(c); 51 c = ((n+1) << CAUSE_IPSHIFT); 52 mips_set_cause(c); 53 54 return n; 55 } 56 else return -1; 57 } 58 59 60 61 62 63 22 64 #define CALL_ISR(_vector,_frame) \ 23 65 do { \ 24 if 66 if( _ISR_Vector_table[_vector] ) \ 25 67 (_ISR_Vector_table[_vector])(_vector,_frame); \ 26 68 else \ … … 28 70 } while (0) 29 71 30 #include <rtems/bspIo.h> /* for printk */ 31 72 73 // 74 // Instrumentation tweaks for isr timing measurement, turning them off 75 // via this #if will remove the code entirely from the RTEMS kernel. 76 // 77 78 #if 1 79 #define SET_ISR_FLAG( offset ) *((unsigned32 *)(0x8001e000+offset)) = 1; 80 #define CLR_ISR_FLAG( offset ) *((unsigned32 *)(0x8001e000+offset)) = 0; 81 #else 82 #define SET_ISR_FLAG( offset ) 83 #define CLR_ISR_FLAG( offset ) 84 #endif 85 86 87 88 89 90 91 static volatile unsigned32 _ivcause, _ivsr; 92 93 94 static unsigned32 READ_CAUSE(void) 95 { 96 mips_get_cause( _ivcause ); 97 _ivcause &= SR_IMASK; // mask off everything other than the interrupt bits 98 99 return ((_ivcause & (_ivsr & SR_IMASK)) >> CAUSE_IPSHIFT); 100 } 101 102 103 104 // 105 // This rather strangely coded routine enforces an interrupt priority 106 // scheme. As it runs thru finding whichever interrupt caused it to get 107 // here, it test for other interrupts arriving in the meantime (maybe it 108 // occured while the vector code is executing for instance). Each new 109 // interrupt will be served in order of its priority. In an effort to 110 // minimize overhead, the cause register is only fetched after an 111 // interrupt is serviced. Because of the intvect goto's, this routine 112 // will only exit when all interrupts have been serviced and no more 113 // have arrived, this improves interrupt latency at the cost of 114 // increasing scheduling jitter; though scheduling jitter should only 115 // become apparent in high interrupt load conditions. 116 // 32 117 void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) 33 118 { 34 unsigned32 sr, srmaskoff; 35 unsigned32 cause, cshifted; 36 unsigned32 bit; 37 unsigned32 pf_icr; 38 39 /* mips_get_sr( sr ); */ 40 sr = frame->regs[ R_SR ]; 41 42 mips_get_cause( cause ); 43 44 /* mask off everything other than the interrupt bits */ 45 cause &= SR_IMASK; 46 47 /* mask off the pending interrupts in the status register */ 48 srmaskoff = sr & ~cause; 49 mips_set_sr( srmaskoff ); 50 51 /* allow nesting for all non-pending interrupts */ 52 asm volatile( "rfe" ); 53 54 cshifted = (cause & (sr & SR_IMASK)) >> CAUSE_IPSHIFT; 55 56 if ( cshifted & 0x04 ) /* IP[0] ==> INT0 == TIMER1 */ 57 CALL_ISR( MONGOOSEV_IRQ_TIMER1, frame ); 58 59 if ( cshifted & 0x08 ) /* IP[1] ==> INT1 == TIMER2*/ 60 CALL_ISR( MONGOOSEV_IRQ_TIMER2, frame ); 61 62 if ( cshifted & 0x10 ) /* IP[2] ==> INT2 */ 63 CALL_ISR( MONGOOSEV_IRQ_INT2, frame ); 64 65 if ( cshifted & 0x20 ) /* IP[3] ==> INT3 == FPU interrupt */ 66 CALL_ISR( MONGOOSEV_IRQ_INT3, frame ); 67 68 if ( cshifted & 0x40 ) /* IP[4] ==> INT4, external interrupt */ 69 CALL_ISR( MONGOOSEV_IRQ_INT4, frame ); 70 71 if ( cshifted & 0x80 ) /* IP[5] ==> INT5, peripheral interrupt */ 72 { 73 pf_icr = MONGOOSEV_READ( MONGOOSEV_PERIPHERAL_FUNCTION_INTERRUPT_CAUSE_REGISTER ); 74 75 /* if !pf_icr */ 76 for ( bit=0 ; bit <= 31 ; bit++, pf_icr >>= 1 ) 77 { 78 if ( pf_icr & 1 ) 79 { 80 CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit, frame ); 81 } 82 } 83 } 84 85 86 /* all the pending interrupts were serviced, now re-enable them */ 87 mips_get_sr( sr ); 88 89 /* we allow the 2 software interrupts to nest freely, under the 90 * assumption that the program knows what its doing... 91 */ 92 93 if( cshifted & 0x3 ) 94 { 95 sr |= (SR_IBIT1 | SR_IBIT1); 96 cause &= ~(SR_IBIT1 | SR_IBIT1); 97 98 mips_set_cause(cause); 99 mips_set_sr(sr); 100 101 if ( cshifted & 0x01 ) /* SW[0] */ 102 { 103 CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_1, frame ); 104 } 105 if ( cshifted & 0x02 ) /* SW[1] */ 106 { 107 CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_2, frame ); 108 } 109 } 110 111 sr |= cause; 112 mips_set_sr( sr ); 113 } 114 115 void mips_default_isr( int vector ) 116 { 117 unsigned int sr; 118 unsigned int cause; 119 120 mips_get_sr( sr ); 121 mips_get_cause( cause ); 122 123 printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", 124 vector, cause, sr ); 125 rtems_fatal_error_occurred(1); 126 } 127 128 /* userspace routine to assert either software interrupt */ 129 130 int assertSoftwareInterrupt( unsigned32 n ) 131 { 132 if( n >= 0 && n<2 ) 133 { 134 unsigned32 c; 135 136 mips_get_cause(c); 137 c = ((n+1) << 8); 138 mips_set_cause(c); 139 140 return n; 141 } 142 else return -1; 143 } 144 119 unsigned32 cshifted; 120 121 /* mips_get_sr( sr ); */ 122 _ivsr = frame->regs[ R_SR ]; 123 124 cshifted = READ_CAUSE(); 125 126 intvect: 127 128 if( cshifted & 0x3 ) 129 { 130 // making the software interrupt the highest priority is kind of 131 // stupid, but it makes the bit testing lots easier. On the other 132 // hand, these ints are infrequently used and the testing overhead 133 // is minimal. Who knows, high-priority software ints might be 134 // handy in some situation. 135 136 /* unset both software int cause bits */ 137 mips_set_cause( _ivcause & ~(3 << CAUSE_IPSHIFT) ); 138 139 if ( cshifted & 0x01 ) /* SW[0] */ 140 { 141 CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_1, frame ); 142 } 143 if ( cshifted & 0x02 ) /* SW[1] */ 144 { 145 CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_2, frame ); 146 } 147 cshifted = READ_CAUSE(); 148 } 149 150 151 if ( cshifted & 0x04 ) /* IP[0] ==> INT0 == TIMER1 */ 152 { 153 SET_ISR_FLAG( 0x4 ); 154 CALL_ISR( MONGOOSEV_IRQ_TIMER1, frame ); 155 CLR_ISR_FLAG( 0x4 ); 156 if( (cshifted = READ_CAUSE()) & 0x3 ) goto intvect; 157 } 158 159 if ( cshifted & 0x08 ) /* IP[1] ==> INT1 == TIMER2*/ 160 { 161 SET_ISR_FLAG( 0x8 ); 162 CALL_ISR( MONGOOSEV_IRQ_TIMER2, frame ); 163 CLR_ISR_FLAG( 0x8 ); 164 if( (cshifted = READ_CAUSE()) & 0x7 ) goto intvect; 165 } 166 167 if ( cshifted & 0x10 ) /* IP[2] ==> INT2 */ 168 { 169 SET_ISR_FLAG( 0x10 ); 170 CALL_ISR( MONGOOSEV_IRQ_INT2, frame ); 171 CLR_ISR_FLAG( 0x10 ); 172 if( (cshifted = READ_CAUSE()) & 0xf ) goto intvect; 173 } 174 175 if ( cshifted & 0x20 ) /* IP[3] ==> INT3 == FPU interrupt */ 176 { 177 SET_ISR_FLAG( 0x20 ); 178 CALL_ISR( MONGOOSEV_IRQ_INT3, frame ); 179 CLR_ISR_FLAG( 0x20 ); 180 if( (cshifted = READ_CAUSE()) & 0x1f ) goto intvect; 181 } 182 183 if ( cshifted & 0x40 ) /* IP[4] ==> INT4, external interrupt */ 184 { 185 SET_ISR_FLAG( 0x40 ); 186 CALL_ISR( MONGOOSEV_IRQ_INT4, frame ); 187 CLR_ISR_FLAG( 0x40 ); 188 if( (cshifted = READ_CAUSE()) & 0x3f ) goto intvect; 189 } 190 191 if ( cshifted & 0x80 ) /* IP[5] ==> INT5, peripheral interrupt */ 192 { 193 unsigned32 bit; 194 unsigned32 pf_icr, pf_mask, pf_reset = 0; 195 unsigned32 i, m; 196 197 pf_icr = MONGOOSEV_READ( MONGOOSEV_PERIPHERAL_FUNCTION_INTERRUPT_CAUSE_REGISTER ); 198 199 /* 200 for (bit=0, pf_mask = 1; bit < 32; bit++, pf_mask <<= 1 ) 201 { 202 if ( pf_icr & pf_mask ) 203 { 204 SET_ISR_FLAG( 0x80 + (bit*4) ); 205 CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit, frame ); 206 CLR_ISR_FLAG( 0x80 + (bit*4) ); 207 pf_reset |= pf_mask; 208 if( (cshifted = READ_CAUSE()) & 0xff ) break; 209 } 210 } 211 */ 212 213 // 214 // iterate thru 32 bits in 4 chunks of 8 bits each. This lets us 215 // quickly get past unasserted interrupts instead of flogging our 216 // way thru a full 32 bits. pf_mask shifts left 8 bits at a time 217 // to serve as a interrupt cause test mask. 218 // 219 for( bit=0, pf_mask = 0xff; (bit < 32 && pf_icr); (bit+=8, pf_mask <<= 8) ) 220 { 221 if ( pf_icr & pf_mask ) 222 { 223 // one or more of the 8 bits we're testing is high 224 225 m = (1 << bit); 226 227 // iterate thru the 8 bits, servicing any of the interrupts 228 for(i=0; (i<8 && pf_icr); (i++, m <<= 1)) 229 { 230 if( pf_icr & m ) 231 { 232 SET_ISR_FLAG( 0x80 + ((bit + i) * 4) ); 233 CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit + i, frame ); 234 CLR_ISR_FLAG( 0x80 + ((bit + i) * 4) ); 235 236 // or each serviced interrupt into our interrupt clear 237 // mask 238 pf_reset |= m; 239 240 // xor off each int we service so we can immediately 241 // exit once we get the last one 242 pf_icr %= m; 243 244 // if another interrupt has arrived, jump out right 245 // away but be sure to reset all the interrupts we've 246 // already serviced 247 //if( READ_CAUSE() & 0xff ) goto pfexit; 248 } 249 } 250 } 251 } 252 pfexit: 253 MONGOOSEV_WRITE( MONGOOSEV_PERIPHERAL_STATUS_REGISTER, pf_reset ); 254 } 255 256 // 257 // this is a last ditch interrupt check, if an interrupt arrives 258 // after this step, servicing it will incur the entire interrupt 259 // overhead cost. 260 // 261 if( (cshifted = READ_CAUSE()) & 0xff ) goto intvect; 262 } 263 264 265 266 // eof -
c/src/lib/libcpu/mips/shared/interrupts/vectorexceptions.c
re6dec71c r2835b3a5 12 12 #include "iregdef.h" 13 13 #include "idtcpu.h" 14 #include < rtems/bspIo.h>14 #include <bspIo.h> 15 15 16 16 char *cause_strings[32] = … … 90 90 } 91 91 92 93 94 92 95 #define CALL_EXC(_vector,_frame) \ 93 96 do { \ … … 97 100 mips_default_exception_code_handler( _vector, _frame ); \ 98 101 } while(0) 102 103 104 99 105 100 106 /*
Note: See TracChangeset
for help on using the changeset viewer.