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

Last change on this file since 306 was 297, checked in by alain, 11 years ago

Bug fix in both _tty_rx_isr() and _bdv_isr():
The ISR must do nothing it the status indicates that
there is no pending ISR.

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