source: soft/giet_vm/giet_kernel/irq_handler.c @ 383

Last change on this file since 383 was 346, checked in by alain, 10 years ago

Fixing a bug in the _sys_handler function (giet.s file).
The SR value was not safely restored.

  • Property svn:executable set to *
File size: 9.3 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : irq_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
9#include <irq_handler.h>
10#include <sys_handler.h>
11#include <ctx_handler.h>
12#include <tim_driver.h>
13#include <icu_driver.h>
14#include <xcu_driver.h>
15#include <tty_driver.h>
[294]16#include <nic_driver.h>
17#include <cma_driver.h>
[297]18#include <mmc_driver.h>
[294]19#include <bdv_driver.h>
[258]20#include <dma_driver.h>
[322]21#include <spi_driver.h>
[281]22#include <mapping_info.h>
[258]23#include <utils.h>
24
[322]25#if !defined( USE_XCU )
26# error: You must define USE_XCU in the hard_config.h file
[258]27#endif
28
29#if NB_TIM_CHANNELS
[263]30extern volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS] ;
[258]31#endif
32
33///////////////////////////////////////////////////////////////////////////////////
34// This function uses the ICU or XICU component (Interrupt Controler Unit)
35// to get the interrupt vector entry. There is one ICU or XICU component per
36// cluster, and this component can support up to NB_PROCS_MAX output IRQs.
37// It returns the highest priority active interrupt index (smaller
38// indexes have the highest priority).
39// Any value larger than 31 means "no active interrupt", and no ISR is executed.
40//
[294]41// There is three interrupt vectors per processor (stored in the processor's
42// scheduler) for the three HWI, PTI, and WTI interrupts types.
43// Each interrupt vector entry contains three bits fields:
44// - isr_id     bits[15:0]  : defines the type of ISR to be executed.
[258]45// - channel_id bits[30:16] : defines the channel for multi-channels peripherals.
46// - valid      bit 31      : valid interrupt vector entry
[294]47// If the peripheral is replicated in clusters, the channel_id is
[258]48// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
49///////////////////////////////////////////////////////////////////////////////////
50void _irq_demux() 
51{
[294]52    unsigned int gpid           = _get_procid();
53    unsigned int cluster_xy     = gpid / NB_PROCS_MAX;
54    unsigned int x              = cluster_xy >> Y_WIDTH;
55    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
56    unsigned int lpid           = gpid % NB_PROCS_MAX;
[258]57    unsigned int irq_id;
[294]58    unsigned int irq_type;
[258]59
60    // get the highest priority active IRQ index
[294]61    unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR;
[258]62
[322]63#if USE_XCU
[294]64    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
[258]65#else
[294]66    irq_type = IRQ_TYPE_HWI;
67    _icu_get_index( cluster_xy, icu_out_index, &irq_id );
[258]68#endif
69
70    if (irq_id < 32) 
71    {
[294]72        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
[346]73        unsigned int        entry = 0;
[294]74        unsigned int        isr_type;
75        unsigned int        channel;
[258]76
[294]77        if      (irq_type == IRQ_TYPE_HWI) entry = psched->hwi_vector[irq_id];
78        else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id];
79        else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id];
80        else
[258]81        {
[294]82            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
83            _exit();
[258]84        }
[294]85
86        isr_type   = (entry    ) & 0x0000FFFF;
87        channel    = (entry>>16) & 0x00007FFF;
88
89#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
[310]90char* irq_type_str[] = { "HWI", "WTI", "PTI" }; 
[294]91_puts("\n[IRQS DEBUG] Processor[");
92_putd(x);
93_puts(",");
94_putd(y);
95_puts(",");
96_putd(lpid);
97_puts("] enters _irq_demux() at cycle ");
98_putd(_get_proctime() );
99_puts("\n  ");
100_puts(irq_type_str[irq_type] );
101_puts(" : irq_id = ");
102_putd(irq_id);
103_puts(" / isr_type = ");
104_putd(isr_type);
105_puts(" / channel = ");
106_putd(channel);
107_puts("\n");
108#endif
109
110        // ISR call
111        if      ( isr_type == ISR_TICK   ) _isr_tick   ( irq_type, irq_id, channel );
112        else if ( isr_type == ISR_WAKUP  ) _isr_wakup  ( irq_type, irq_id, channel );
113        else if ( isr_type == ISR_BDV    ) _bdv_isr    ( irq_type, irq_id, channel );
114        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
115        else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel );
116        else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel );
117        else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel );
118        else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel );
119        else if ( isr_type == ISR_TIMER  ) _timer_isr  ( irq_type, irq_id, channel );
[297]120        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
[322]121        else if ( isr_type == ISR_DMA    ) _dma_isr    ( irq_type, irq_id, channel );
122        else if ( isr_type == ISR_SPI    ) _spi_isr    ( irq_type, irq_id, channel );
[294]123        else
[258]124        {
[310]125            _printf("\n[GIET ERROR] in _irq_demux() :"
126                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
127                    " - irq_type = %d\n"
128                    " - irq_id   = %d\n"
129                    " - isr_type = %x\n",
130                    x, y, lpid, _get_proctime(), irq_type, irq_id, isr_type );
[258]131        }
132    }
[294]133    else   // no interrupt active
134    {
135        _isr_default();
136    } 
[258]137}
138
139///////////////////////////////////////////////////////////////////////////////////
[294]140// The default ISR is called when there is no active IRQ when the interrupt
141// handler is called. It simply displays a warning message on TTY[0].
[258]142///////////////////////////////////////////////////////////////////////////////////
[294]143void _isr_default()
[258]144{
[294]145    unsigned int gpid       = _get_procid();
146    unsigned int cluster_xy = gpid / NB_PROCS_MAX;
147    unsigned int x          = cluster_xy >> Y_WIDTH;
148    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
149    unsigned int lpid       = gpid % NB_PROCS_MAX;
[258]150
[322]151    _printf("\n[GIET WARNING] IRQ handler called but no active IRQ "
152            "on processor[%d,%d,%d] at cycle %d\n",
153            x, y, lpid, _get_proctime() );
[258]154}
155
156
157///////////////////////////////////////////////////////////////////////////////////
[294]158// This ISR can only be executed after a WTI (IPI) to force a context switch
159// on a remote processor. The context switch is only executed if the current task
160// is the IDLE_TASK, or if the value written in the mailbox is non zero.
[258]161///////////////////////////////////////////////////////////////////////////////////
[294]162void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
163                 unsigned int irq_id,     // index returned by ICU
164                 unsigned int channel )   // unused
[258]165{
[294]166    unsigned int procid     = _get_procid();
167    unsigned int cluster_xy = procid / NB_PROCS_MAX;
168    unsigned int x          = cluster_xy >> Y_WIDTH;
169    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
170    unsigned int lpid       = procid % NB_PROCS_MAX;
171    unsigned int task       = _get_current_task_id();
172    unsigned int value;
[258]173
[294]174    if ( irq_type != IRQ_TYPE_WTI )
[258]175    {
[294]176        // we don't take the TTY lock to avoid deadlocks
177        _puts("[GIET ERROR] _isr_wakup() not called by a WTI on processor[");
178        _putd( x );
179        _puts(",");
180        _putd( y );
181        _puts(",");
182        _putd( lpid );
183        _puts("] at cycle ");
184        _putd( _get_proctime() );
185        _puts("\n");
186        _exit();
[258]187    }
188
[294]189    // get mailbox value and acknowledge WTI
190    _xcu_get_wti_value( cluster_xy, irq_id, &value );
191
192#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
193_puts("\n[IRQS DEBUG] Processor[");
194_putd( x );
195_puts(",");
196_putd( y );
197_puts(",");
198_putd( lpid );
199_puts("] enters _isr_wakup() at cycle ");
200_putd( _get_proctime() );
201_puts("\n  WTI / mailbox data = ");
202_putx( value );
203_puts(" / current task index = ");
204_putd( task );
205_puts("\n  ");
[258]206#endif
207
[294]208    // context swich if required
209    if ( (task == IDLE_TASK_INDEX) || (value != 0) ) _ctx_switch();
[258]210}
211
212/////////////////////////////////////////////////////////////////////////////////////
[294]213// This ISR is in charge of context switch, and handles the IRQs generated by
214// the "system" timers contained in the MULTI_TIMER or in the XICU component.
215// The ISR acknowledges the IRQ, and calls the _ctx_switch() function.
[258]216/////////////////////////////////////////////////////////////////////////////////////
[294]217void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
218                unsigned int irq_id,     // index returned by ICU
219                unsigned int channel )   // channel index if HWI
[258]220{
[294]221    unsigned int procid     = _get_procid();
222    unsigned int cluster_xy = procid / NB_PROCS_MAX;
[258]223
[294]224    // acknowledge HWI or PTI
225    if ( irq_type == IRQ_TYPE_HWI ) _timer_reset_irq( cluster_xy, channel );
226    else                            _xcu_timer_reset_irq( cluster_xy, irq_id );
[258]227
[294]228#if GIET_DEBUG_IRQS  // we don't take the lock to avoid deadlock
229unsigned int x          = cluster_xy >> Y_WIDTH;
230unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
231unsigned int lpid       = procid % NB_PROCS_MAX;
232_puts("\n[IRQS DEBUG] Processor[");
233_putd( x );
234_puts(",");
235_putd( y );
236_puts(",");
237_putd( lpid );
238_puts("] enters _isr_tick() at cycle ");
239_putd( _get_proctime() );
240_puts("\n  ");
[258]241#endif
242
[294]243    // context switch
[258]244    _ctx_switch();
245}
246
247
248// Local Variables:
249// tab-width: 4
250// c-basic-offset: 4
251// c-file-offsets:((innamespace . 0)(inline-open . 0))
252// indent-tabs-mode: nil
253// End:
254// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
255
Note: See TracBrowser for help on using the repository browser.