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

Last change on this file since 437 was 428, checked in by alain, 10 years ago

Introducing fixed format (X_WIDTH / Y_WIDTH / P_WIDTH) for processor index.

  • Property svn:executable set to *
File size: 9.3 KB
Line 
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>
16#include <nic_driver.h>
17#include <cma_driver.h>
18#include <mmc_driver.h>
19#include <bdv_driver.h>
20#include <dma_driver.h>
21#include <spi_driver.h>
22#include <mapping_info.h>
23#include <utils.h>
24
25#if !defined( USE_XCU )
26# error: You must define USE_XCU in the hard_config.h file
27#endif
28
29#if NB_TIM_CHANNELS
30extern volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS] ;
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//
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.
45// - channel_id bits[30:16] : defines the channel for multi-channels peripherals.
46// - valid      bit 31      : valid interrupt vector entry
47// If the peripheral is replicated in clusters, the channel_id is
48// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
49///////////////////////////////////////////////////////////////////////////////////
50void _irq_demux() 
51{
52    unsigned int gpid           = _get_procid();
53    unsigned int cluster_xy     = gpid >> P_WIDTH;
54    unsigned int x              = cluster_xy >> Y_WIDTH;
55    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
56    unsigned int lpid           = gpid & ((1<<P_WIDTH)-1);
57    unsigned int irq_id;
58    unsigned int irq_type;
59
60    // get the highest priority active IRQ index
61    unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR;
62
63#if USE_XCU
64    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
65#else
66    irq_type = IRQ_TYPE_HWI;
67    _icu_get_index( cluster_xy, icu_out_index, &irq_id );
68#endif
69
70    if (irq_id < 32) 
71    {
72        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
73        unsigned int        entry = 0;
74        unsigned int        isr_type;
75        unsigned int        channel;
76
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
81        {
82            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
83            _exit();
84        }
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
90char* irq_type_str[] = { "HWI", "WTI", "PTI" }; 
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 );
120        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
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 );
123        else
124        {
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 );
131        }
132    }
133    else   // no interrupt active
134    {
135        _isr_default();
136    } 
137}
138
139///////////////////////////////////////////////////////////////////////////////////
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].
142///////////////////////////////////////////////////////////////////////////////////
143void _isr_default()
144{
145    unsigned int gpid       = _get_procid();
146    unsigned int cluster_xy = gpid >> P_WIDTH;
147    unsigned int x          = cluster_xy >> Y_WIDTH;
148    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
149    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
150
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() );
154}
155
156
157///////////////////////////////////////////////////////////////////////////////////
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.
161///////////////////////////////////////////////////////////////////////////////////
162void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
163                 unsigned int irq_id,     // index returned by ICU
164                 unsigned int channel )   // unused
165{
166    unsigned int gpid       = _get_procid();
167    unsigned int cluster_xy = gpid >> P_WIDTH;
168    unsigned int x          = cluster_xy >> Y_WIDTH;
169    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
170    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
171
172    unsigned int task       = _get_current_task_id();
173    unsigned int value;
174
175    if ( irq_type != IRQ_TYPE_WTI )
176    {
177        // we don't take the TTY lock to avoid deadlocks
178        _puts("[GIET ERROR] _isr_wakup() not called by a WTI on processor[");
179        _putd( x );
180        _puts(",");
181        _putd( y );
182        _puts(",");
183        _putd( lpid );
184        _puts("] at cycle ");
185        _putd( _get_proctime() );
186        _puts("\n");
187        _exit();
188    }
189
190    // get mailbox value and acknowledge WTI
191    _xcu_get_wti_value( cluster_xy, irq_id, &value );
192
193#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
194_puts("\n[IRQS DEBUG] Processor[");
195_putd( x );
196_puts(",");
197_putd( y );
198_puts(",");
199_putd( lpid );
200_puts("] enters _isr_wakup() at cycle ");
201_putd( _get_proctime() );
202_puts("\n  WTI / mailbox data = ");
203_putx( value );
204_puts(" / current task index = ");
205_putd( task );
206_puts("\n  ");
207#endif
208
209    // context swich if required
210    if ( (task == IDLE_TASK_INDEX) || (value != 0) ) _ctx_switch();
211}
212
213/////////////////////////////////////////////////////////////////////////////////////
214// This ISR is in charge of context switch, and handles the IRQs generated by
215// the "system" timers contained in the MULTI_TIMER or in the XICU component.
216// The ISR acknowledges the IRQ, and calls the _ctx_switch() function.
217/////////////////////////////////////////////////////////////////////////////////////
218void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
219                unsigned int irq_id,     // index returned by ICU
220                unsigned int channel )   // channel index if HWI
221{
222    unsigned int gpid       = _get_procid();
223    unsigned int cluster_xy = gpid >> P_WIDTH;
224
225    // acknowledge HWI or PTI
226    if ( irq_type == IRQ_TYPE_HWI ) _timer_reset_irq( cluster_xy, channel );
227    else                            _xcu_timer_reset_irq( cluster_xy, irq_id );
228
229#if GIET_DEBUG_IRQS  // we don't take the lock to avoid deadlock
230unsigned int x          = cluster_xy >> Y_WIDTH;
231unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
232unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
233_puts("\n[IRQS DEBUG] Processor[");
234_putd( x );
235_puts(",");
236_putd( y );
237_puts(",");
238_putd( lpid );
239_puts("] enters _isr_tick() at cycle ");
240_putd( _get_proctime() );
241_puts("\n  ");
242#endif
243
244    // context switch
245    _ctx_switch();
246}
247
248
249// Local Variables:
250// tab-width: 4
251// c-basic-offset: 4
252// c-file-offsets:((innamespace . 0)(inline-open . 0))
253// indent-tabs-mode: nil
254// End:
255// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
256
Note: See TracBrowser for help on using the repository browser.