/////////////////////////////////////////////////////////////////////////////////// // File : irq_handler.c // Date : 01/04/2012 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined( USE_XCU ) # error: You must define USE_XCU in the hard_config.h file #endif #if NB_TIM_CHANNELS extern volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS] ; #endif /////////////////////////////////////////////////////////////////////////////////// // This function uses the ICU or XICU component (Interrupt Controler Unit) // to get the interrupt vector entry. There is one ICU or XICU component per // cluster, and this component can support up to NB_PROCS_MAX output IRQs. // It returns the highest priority active interrupt index (smaller // indexes have the highest priority). // Any value larger than 31 means "no active interrupt", and no ISR is executed. // // There is three interrupt vectors per processor (stored in the processor's // scheduler) for the three HWI, PTI, and WTI interrupts types. // Each interrupt vector entry contains three bits fields: // - isr_id bits[15:0] : defines the type of ISR to be executed. // - channel_id bits[30:16] : defines the channel for multi-channels peripherals. // - valid bit 31 : valid interrupt vector entry // If the peripheral is replicated in clusters, the channel_id is // a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id /////////////////////////////////////////////////////////////////////////////////// void _irq_demux() { unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid / NB_PROCS_MAX; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<hwi_vector[irq_id]; else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id]; else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id]; else { _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n"); _exit(); } isr_type = (entry ) & 0x0000FFFF; channel = (entry>>16) & 0x00007FFF; #if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks char* irq_type_str[] = { "HWI", "WTI", "PTI" }; _puts("\n[IRQS DEBUG] Processor["); _putd(x); _puts(","); _putd(y); _puts(","); _putd(lpid); _puts("] enters _irq_demux() at cycle "); _putd(_get_proctime() ); _puts("\n "); _puts(irq_type_str[irq_type] ); _puts(" : irq_id = "); _putd(irq_id); _puts(" / isr_type = "); _putd(isr_type); _puts(" / channel = "); _putd(channel); _puts("\n"); #endif // ISR call if ( isr_type == ISR_TICK ) _isr_tick ( irq_type, irq_id, channel ); else if ( isr_type == ISR_WAKUP ) _isr_wakup ( irq_type, irq_id, channel ); else if ( isr_type == ISR_BDV ) _bdv_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_CMA ) _cma_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_TIMER ) _timer_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_MMC ) _mmc_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_DMA ) _dma_isr ( irq_type, irq_id, channel ); else if ( isr_type == ISR_SPI ) _spi_isr ( irq_type, irq_id, channel ); else { _printf("\n[GIET ERROR] in _irq_demux() :" " illegal ISR type on processor[%d,%d,%d] at cycle %d\n" " - irq_type = %d\n" " - irq_id = %d\n" " - isr_type = %x\n", x, y, lpid, _get_proctime(), irq_type, irq_id, isr_type ); } } else // no interrupt active { _isr_default(); } } /////////////////////////////////////////////////////////////////////////////////// // The default ISR is called when there is no active IRQ when the interrupt // handler is called. It simply displays a warning message on TTY[0]. /////////////////////////////////////////////////////////////////////////////////// void _isr_default() { unsigned int gpid = _get_procid(); unsigned int cluster_xy = gpid / NB_PROCS_MAX; unsigned int x = cluster_xy >> Y_WIDTH; unsigned int y = cluster_xy & ((1<> Y_WIDTH; unsigned int y = cluster_xy & ((1<> Y_WIDTH; unsigned int y = cluster_xy & ((1<