Ignore:
Timestamp:
Aug 7, 2012, 6:37:49 PM (12 years ago)
Author:
alain
Message:

Introducing a new release where all initialisation
is done in the boot code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/sys/irq_handler.c

    r169 r189  
    22// File     : irq_handler.c
    33// Date     : 01/04/2012
    4 // Author   : alain greiner and joel porquet
     4// Author   : alain greiner
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
    7 // The irq_handler.c and irq_handler.h files are part of the GIET nano-kernel.
    8 // They contain the code of the _int_demux function that handle
    9 // the ICU (Interupt Controler Unit), and the various ISRs associated
    10 // to the CoCLib peripherals.
     7// The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel.
     8// They contain the code of the _irq_demux() function that access the XICU or
     9// ICU component (Interupt Controler Unit), and the various ISRs (Interrupt
     10// Service Routine) associated to the peripherals.
    1111///////////////////////////////////////////////////////////////////////////////////
    1212
     
    2020
    2121///////////////////////////////////////////////////////////////////////////////////
    22 // Initialize the whole interrupt vector with the default ISR
    23 ///////////////////////////////////////////////////////////////////////////////////
    24 
    25 __attribute__((section (".kdata"))) _isr_func_t _interrupt_vector[32] =
    26                                                   { [0 ... 31] = &_isr_default };
    27 
    28 ///////////////////////////////////////////////////////////////////////////////////
    29 //      _int_demux()
    30 // This functions uses an external ICU component (Interrupt Controler Unit)
    31 // that concentrates up to 32 input interrupts lines. This component
    32 // can support up to NB_PROCS output IRQ.
     22//      _irq_demux()
     23// This function uses the ICU or XICU component (Interrupt Controler Unit)
     24// to get the interrupt vector entry. There is one ICU or XICU component per
     25// cluster, and this component can support up to NB_PROCS_MAX output IRQs.
     26// It returns the highest priority active interrupt index (smaller
     27// indexes have the highest priority).
     28// Any value larger than 31 means "no active interrupt", and no ISR is executed.
    3329//
    34 // This component returns the highest priority active interrupt index (smaller
    35 // indexes have the highest priority) by reading the ICU_IT_VECTOR register.
    36 // Any value larger than 31 means "no active interrupt", and the default ISR
    37 // (that does nothing) is executed.
     30// There is one interrupt vector per processor (stored in the scheduler associated
     31// to the processor. Each interrupt vector entry contains two 16 bits fields:
     32// - isr_id : defines the type of ISR to be executed.
     33// - channel_id : defines the specific channel for multi-channels peripherals.
    3834//
    39 // The interrupt vector (32 ISR addresses array stored at _interrupt_vector
    40 // address) is initialised with the default ISR address. The actual ISR
    41 // addresses are supposed to be written in the interrupt vector array
    42 // during system initialisation.
    43 ///////////////////////////////////////////////////////////////////////////////////
    44 void _int_demux(void)
    45 {
    46     int                         interrupt_index;
    47     _isr_func_t         isr;
    48     unsigned int        pid = _procid();
    49 
    50     // retrieves the highest priority active interrupt index
    51     if (!_icu_read( pid / NB_PROCS,
    52                     pid % NB_PROCS,
     35// If the peripheral is replicated in clusters (TIMER or DMA), the channel_id is
     36// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
     37///////////////////////////////////////////////////////////////////////////////////
     38void _irq_demux()
     39{
     40    unsigned int    pid = _procid();
     41    unsigned int        irq_id;
     42
     43    // get the highest priority active IRQ index
     44
     45#if GIET_USE_XICU
     46
     47#else
     48
     49    if ( _icu_read( pid / NB_PROCS_MAX,
     50                    pid % NB_PROCS_MAX,
    5351                    ICU_IT_VECTOR,
    54                     (unsigned int*)&interrupt_index ) )
     52                    &irq_id ) )
    5553    {
    56         if (interrupt_index == -1)      // no interrupt is active
    57             return;
    58 
    59         isr = _interrupt_vector[interrupt_index];
    60         isr();
    61     }
    62     else
    63     {
    64         _puts("\n[GIET ERROR] In _demux function : wrong arguments in _icu_read()\n");
     54        _puts("\n[GIET ERROR] wrong _icu_read in _irq_demux() function\n");
    6555        _exit();
    6656    }
     57
     58#endif
     59
     60    if ( irq_id < 32 )  // do nothing if no interrupt active
     61    {
     62        unsigned int entry      = _get_interrupt_vector_entry(irq_id);
     63        unsigned int isr_id     = entry & 0x000000FF;
     64        unsigned int channel_id = (entry>>16) & 0x0000FFFF;
     65        if      ( isr_id == ISR_SWITCH  ) _isr_switch();
     66        else if ( isr_id == ISR_IOC     ) _isr_ioc();
     67        else if ( isr_id == ISR_DMA     ) _isr_dma( channel_id );
     68        else if ( isr_id == ISR_TTY     ) _isr_tty( channel_id );
     69        else if ( isr_id == ISR_TIMER   ) _isr_timer( channel_id );
     70        else                              _isr_default();
     71    }
    6772}
    6873///////////////////////////////////////////////////////////////////////////////////
    6974//      _isr_default()
    7075// The default ISR is called when no specific ISR has been installed in the
    71 // interrupt vector. It simply displays a message on TTY0.
     76// interrupt vector. It simply displays a message on kernel TTY[0].
    7277///////////////////////////////////////////////////////////////////////////////////
    7378void _isr_default()
    7479{
    75     _puts("\n\n!!! Default ISR !!!\n");
     80    _puts("\n\n!!! Strange... Default ISR activated !!!\n");
    7681}
    7782
    7883///////////////////////////////////////////////////////////////////////////////////
    7984//      _isr_dma()
    80 // This ISR handles up to 8 IRQs generated by 8 independant channels of the
    81 // multi_dma component. It acknowledges the interrupt and reset the synchronisation
    82 // variable _dma_busy[i], after copying the status into the _dma_status[i] variable.
    83 ///////////////////////////////////////////////////////////////////////////////////
    84 void _isr_dma_indexed( unsigned int dma_id )
    85 {
    86     volatile unsigned int* dma_address;
     85// This ISR handles all IRQs generated by the multi-channels DMA controlers.
     86// The multi_dma components can be distributed in the clusters.
     87// The channel_id argument is the global DMA channel index.
     88//     channel_id = cluster_id*NB_DMAS_MAX + loc_id
     89// - The ISR saves the transfert status in _dma_status[channel_id].
     90// - It acknowledges the interrupt to reinitialize the DMA controler.
     91// - it resets the synchronisation variable _dma_busy[channel_id].
     92///////////////////////////////////////////////////////////////////////////////////
     93void _isr_dma( unsigned int channel_id )
     94{
     95    // compute cluster_id and loc_id
     96    unsigned int cluster_id = channel_id / NB_DMAS_MAX;
     97    unsigned int loc_id     = channel_id % NB_DMAS_MAX;
    8798
    8899    // compute DMA channel address
    89     dma_address = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN);
     100    unsigned int*       dma_address = (unsigned int*)&seg_dma_base +
     101                                  (loc_id * DMA_SPAN) +
     102                                  (cluster_id * CLUSTER_SPAN);
    90103
    91104    // save DMA channel status 
    92     _dma_status[dma_id] = dma_address[DMA_LEN]; /* save status */
     105    _dma_status[channel_id] = dma_address[DMA_LEN];
    93106
    94107    // reset DMA channel
    95     dma_address[DMA_RESET] = 0;                                 /* reset IRQ */
     108    dma_address[DMA_RESET] = 0;                 
    96109
    97110    // release DMA channel
    98     _dma_busy[dma_id] = 0;                      /* release DMA */
    99 }
    100 
    101 void _isr_dma_0() { _isr_dma_indexed(0); }
    102 void _isr_dma_1() { _isr_dma_indexed(1); }
    103 void _isr_dma_2() { _isr_dma_indexed(2); }
    104 void _isr_dma_3() { _isr_dma_indexed(3); }
    105 void _isr_dma_4() { _isr_dma_indexed(4); }
    106 void _isr_dma_5() { _isr_dma_indexed(5); }
    107 void _isr_dma_6() { _isr_dma_indexed(6); }
    108 void _isr_dma_7() { _isr_dma_indexed(7); }
     111    _dma_done[channel_id] = 1; 
     112}
    109113
    110114///////////////////////////////////////////////////////////////////////////////////
    111115//      _isr_ioc()
    112 // There is only one IOC controler shared by all tasks. It acknowledge the IRQ
    113 // using the ioc base address, save the status, and set the _ioc_done variable
    114 // to signal completion.
     116// There is only one IOC controler shared by all tasks.
     117// - The ISR save the status and acknowledge the IRQ.
     118// - It sets the _ioc_done variable to signal completion.
    115119///////////////////////////////////////////////////////////////////////////////////
    116120void _isr_ioc()
    117121{
    118     volatile unsigned int* ioc_address;
    119 
    120     ioc_address = (unsigned int*)&seg_ioc_base;
     122    unsigned int* ioc_address = (unsigned int*)&seg_ioc_base;
    121123
    122124    _ioc_status = ioc_address[BLOCK_DEVICE_STATUS]; /* save status & reset IRQ */
     
    125127
    126128///////////////////////////////////////////////////////////////////////////////////
    127 //      _isr_timer_* (* = 0,1,2,3,4,5,6,7)
    128 // This ISR handles up to 8 IRQs generated by 8 independant timers.
    129 // It acknowledges the IRQ on TIMER[*] and displays a message on TTY0
    130 ///////////////////////////////////////////////////////////////////////////////////
    131 void _isr_timer_indexed(unsigned int timer_id)
    132 {
    133     volatile unsigned int *timer_address;
    134 
    135     timer_address = (unsigned int*)&seg_timer_base + (timer_id * TIMER_SPAN);
    136 
    137     timer_address[TIMER_RESETIRQ] = 0; /* reset IRQ */
    138 
    139     _puts("\n\n!!! Interrupt timer received from timer ");
    140     _putw( timer_id );
    141     _puts(" at cycle ");
    142     _putw( _proctime() );
    143     _puts("\n\n");
    144 }
    145 
    146 void _isr_timer_0()  { _isr_timer_indexed(0);  }
    147 void _isr_timer_1()  { _isr_timer_indexed(1);  }
    148 void _isr_timer_2()  { _isr_timer_indexed(2);  }
    149 void _isr_timer_3()  { _isr_timer_indexed(3);  }
    150 void _isr_timer_4()  { _isr_timer_indexed(4);  }
    151 void _isr_timer_5()  { _isr_timer_indexed(5);  }
    152 void _isr_timer_6()  { _isr_timer_indexed(6);  }
    153 void _isr_timer_7()  { _isr_timer_indexed(7);  }
    154 
    155 ///////////////////////////////////////////////////////////////////////////////////
    156 // _isr_tty_get_* (* = 0,1,2,3,4,5,6,7,9,10,11,12,13,14,15)
    157 // The Giet supports up to 16 TTY terminals.
    158 // These 16 ISRs handle the up to 16 IRQs associated to 16 independant
    159 // terminals, signaling that a character is available.
    160 // There is one communication buffer _tty_get_buf[tty_id] per terminal.
    161 // The sychronisation variable _tty_get_full[tty_id], is set by the ISR,
     129//         _isr_timer()
     130// This ISR handles the IRQs generated by the "user" timers (the IRQs
     131// generated by the "system" timers should be handled by the _isr_switch().
     132// These timers are distributed in all clusters, and can be implemented
     133// in a vci_multi_timer component, or in a vci_xicu component.
     134// The channel_id argument is the global channel index:
     135//     channel_id = cluster_id*(NB_TIMERS_MAX+NB_PROCS_MAX) + loc_id
     136// The user timer local index is (loc_id - NB_PROCS_MAX).
     137//
     138// The ISR acknowledges the IRQ and registers the event in the proper entry
     139// of the _timer_event[] array.
     140// A log message is displayed on the kernel terminal.
     141///////////////////////////////////////////////////////////////////////////////////
     142void _isr_timer(unsigned int channel_id)
     143{
     144
     145    unsigned int cluster_id = channel_id / (NB_TIMERS_MAX + NB_PROCS_MAX);
     146    unsigned int loc_id     = channel_id % (NB_TIMERS_MAX + NB_PROCS_MAX);
     147
     148    if (loc_id < NB_PROCS_MAX )
     149    {
     150        _puts("[GIET ERROR] Receiving a user timer IRQ for a system timer\n");
     151        _puts("             cluster = ");
     152        _putw(cluster_id);
     153        _puts(" / local_id = ");
     154        _putw(loc_id);
     155    }
     156
     157#if GIET_USE_XICU
     158
     159// TODO
     160
     161#else
     162
     163    // compute Timer address
     164    unsigned int* timer_address = (unsigned int*)&seg_timer_base +
     165                                  (loc_id * TIMER_SPAN) +
     166                                  (cluster_id * CLUSTER_SPAN);
     167
     168    // reset IRQ
     169    timer_address[TIMER_RESETIRQ] = 0;
     170
     171#endif
     172
     173#if NB_TIMERS_MAX
     174    // register the event
     175    _timer_event[(cluster_id*NB_TIMERS_MAX) + (loc_id - NB_PROCS_MAX)] = 1;
     176#endif
     177
     178    // display a message on TTY 0
     179    _puts("[GIET] User Timer IRQ / cluster = ");
     180    _putw(cluster_id);
     181    _puts(" / timer = ");
     182    _putw(loc_id - NB_PROCS_MAX);
     183    _puts("\n");
     184}
     185
     186///////////////////////////////////////////////////////////////////////////////////
     187//  _isr_tty()
     188// This ISR handles the IRQs generated by the multi_tty controler,
     189// signaling that a character is available.
     190// There is one single multi_tty component controling all TTYs, and the tty_id
     191// argument is the global TTY index.
     192// There is one communication buffer _tty_buf[tty_id] per terminal.
     193// The sychronisation variable _tty_full[tty_id], is set by the ISR,
    162194// and reset by the OS.
    163195// A character is lost if the buffer is full when the ISR is executed.
    164196///////////////////////////////////////////////////////////////////////////////////
    165 void _isr_tty_get_indexed(unsigned int tty_id)
    166 {
    167     volatile unsigned int *tty_address;
    168 
    169     /* compute terminal base address */
    170     tty_address = (unsigned int*)&seg_tty_base + (tty_id * TTY_SPAN);
    171 
    172     /* save character and reset IRQ */
     197void _isr_tty(unsigned int tty_id)
     198{
     199    // compute terminal base address
     200    unsigned int *tty_address = (unsigned int*)&seg_tty_base + (tty_id * TTY_SPAN);
     201
     202    // save character and reset IRQ
    173203    _tty_get_buf[tty_id] = (unsigned char)tty_address[TTY_READ];
    174204
    175     /* signals character available */
     205    // signals character available
    176206    _tty_get_full[tty_id] = 1;
    177207}
    178 
    179 void _isr_tty_get_0()  { _isr_tty_get_indexed(0);  }
    180 void _isr_tty_get_1()  { _isr_tty_get_indexed(1);  }
    181 void _isr_tty_get_2()  { _isr_tty_get_indexed(2);  }
    182 void _isr_tty_get_3()  { _isr_tty_get_indexed(3);  }
    183 void _isr_tty_get_4()  { _isr_tty_get_indexed(4);  }
    184 void _isr_tty_get_5()  { _isr_tty_get_indexed(5);  }
    185 void _isr_tty_get_6()  { _isr_tty_get_indexed(6);  }
    186 void _isr_tty_get_7()  { _isr_tty_get_indexed(7);  }
    187 void _isr_tty_get_8()  { _isr_tty_get_indexed(8);  }
    188 void _isr_tty_get_9()  { _isr_tty_get_indexed(9);  }
    189 void _isr_tty_get_10() { _isr_tty_get_indexed(10); }
    190 void _isr_tty_get_11() { _isr_tty_get_indexed(11); }
    191 void _isr_tty_get_12() { _isr_tty_get_indexed(12); }
    192 void _isr_tty_get_13() { _isr_tty_get_indexed(13); }
    193 void _isr_tty_get_14() { _isr_tty_get_indexed(14); }
    194 void _isr_tty_get_15() { _isr_tty_get_indexed(15); }
    195208
    196209/////////////////////////////////////////////////////////////////////////////////////
    197210// _isr_switch
    198 // This ISR is in charge of context switch.
    199 // It acknowledges the IRQ on TIMER[proc_id] and calls the _ctx_switch() function.
     211// This ISR is in charge of context switch, and handle the IRQs generated by
     212// the "system" timers.
     213// The IRQs can be generated by the MULTI_TIMER component or by the XICU component,
     214// that are distributed in all clusters.
     215// The ISR acknowledges the IRQ and calls the _ctx_switch() function.
    200216/////////////////////////////////////////////////////////////////////////////////////
    201217void _isr_switch()
    202218{
    203     volatile unsigned int *timer_address;
    204     unsigned int proc_id;
    205 
    206     proc_id = _procid();
    207     timer_address = (unsigned int*)&seg_timer_base + (proc_id * TIMER_SPAN);
    208 
    209     timer_address[TIMER_RESETIRQ] = 0; /* reset IRQ */
     219    // get cluster index and proc local index
     220    unsigned int pid        = _procid();
     221    unsigned int loc_id     = pid % NB_PROCS_MAX;
     222    unsigned int cluster_id = pid / NB_PROCS_MAX;
     223
     224#if GIET_USE_XICU
     225
     226    unsigned int* timer_address = // TODO
     227
     228#else
     229
     230    // compute Timer address
     231    unsigned int* timer_address = (unsigned int*)&seg_timer_base +
     232                                  (loc_id * TIMER_SPAN) +
     233                                  (cluster_id * CLUSTER_SPAN);
     234
     235    // reset IRQ
     236    timer_address[TIMER_RESETIRQ] = 0;
     237
     238#endif
     239
     240    // performs the context switch
    210241    _ctx_switch();
    211 }
    212 
     242
     243}
     244
Note: See TracChangeset for help on using the changeset viewer.