/** * @file * @ingroup RTEMSBSPsSPARCLEON2 * @brief LEON Spurious Trap Handler */ /* * LEON Spurious Trap Handler * * This is just enough of a trap handler to let us know what * the likely source of the trap was. * * Developed as part of the port of RTEMS to the LEON implementation * of the SPARC by On-Line Applications Research Corporation (OAR) * under contract to the European Space Agency (ESA). * * COPYRIGHT (c) 1995. European Space Agency. * * This terms of the RTEMS license apply to this file. */ #include #include #include void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) { uint32_t trap; uint32_t real_trap; const CPU_Interrupt_frame *isf; trap = frame->trap; real_trap = SPARC_REAL_TRAP_NUMBER(trap); isf = frame->isf; printk( "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n", real_trap, isf->tpc ); switch (real_trap) { /* * First the ones defined by the basic architecture */ case 0x00: printk( "reset\n" ); break; case 0x01: printk( "instruction access exception\n" ); break; case 0x02: printk( "illegal instruction\n" ); break; case 0x03: printk( "privileged instruction\n" ); break; case 0x04: printk( "fp disabled\n" ); break; case 0x07: printk( "memory address not aligned\n" ); break; case 0x08: printk( "fp exception\n" ); break; case 0x09: printk("data access exception at 0x%08x\n", LEON_REG.Failed_Address ); break; case 0x0A: printk( "tag overflow\n" ); break; /* * Then the ones defined by the LEON in particular */ case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ): printk( "LEON_INTERRUPT_UART_2_RX_TX\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ): printk( "LEON_INTERRUPT_UART_1_RX_TX\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ): printk( "LEON_INTERRUPT_EXTERNAL_0\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ): printk( "LEON_INTERRUPT_EXTERNAL_1\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ): printk( "LEON_INTERRUPT_EXTERNAL_2\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ): printk( "LEON_INTERRUPT_EXTERNAL_3\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ): printk( "LEON_INTERRUPT_TIMER1\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ): printk( "LEON_INTERRUPT_TIMER2\n" ); break; default: break; } } static rtems_isr bsp_spurious_handler( rtems_vector_number trap, CPU_Interrupt_frame *isf ) { CPU_Exception_frame frame = { .trap = trap, .isf = isf }; #if !defined(SPARC_USE_LAZY_FP_SWITCH) if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) { _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT ); } #endif rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) &frame ); } /* * bsp_spurious_initialize * * Install the spurious handler for most traps. Note that set_vector() * will unmask the corresponding asynchronous interrupt, so the initial * interrupt mask is restored after the handlers are installed. */ void bsp_spurious_initialize() { uint32_t trap; uint32_t level; uint32_t mask; level = sparc_disable_interrupts(); mask = LEON_REG.Interrupt_Mask; for ( trap=0 ; trap<256 ; trap++ ) { /* * Skip window overflow, underflow, and flush as well as software * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable. * Also avoid trap 0x70 - 0x7f which cannot happen and where some of the * space is used to pass parameters to the program. */ if (( trap == 5 || trap == 6 ) || #if defined(SPARC_USE_LAZY_FP_SWITCH) ( trap == 4 ) || #endif (( trap >= 0x11 ) && ( trap <= 0x1f )) || (( trap >= 0x70 ) && ( trap <= 0x83 )) || ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) || #if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) || #endif ( trap == 0x80 + SPARC_SWTRAP_IRQEN )) continue; set_vector( (rtems_isr_entry) bsp_spurious_handler, SPARC_SYNCHRONOUS_TRAP( trap ), 1 ); } LEON_REG.Interrupt_Mask = mask; sparc_enable_interrupts(level); }