PowerPC exceptions and interrupts
Till Straumann
strauman at slac.stanford.edu
Fri May 23 17:55:26 UTC 2008
>> The next algorithm is required to handle correctly shared edge
>> triggered sources
>>
>> rtems_interrupt_handled_state again;
>> rtems_interrupt_handled_state res;
>> do {
>> again = 0;
>> for_each(vector->rtems_irq_connect_data_list, connect) {
>> res=connect->hndl(connect->handle);
>> if(res == RTEMS_INTERRUPT_HANDLED)
>> again = 1;
>> }
>> } while(again);
>>
>>
>
> If understand the above scheme correctly, the intention is to handle
> shared interrupt sources onan edge triggered interrupt input.
>
> From my perspective as a (sometimes) hardware developer, I assume such
> a structure as a severe bug. I consider it at least questionable,
> whether it makes sense to cure such a design fault in a general way,
> which will greatly increase the interrupt response time for other
> interrupt sources (Note, that normally each chain of interrupt handlers
> will be called at least twice instead of once).
>
> If such a hardware must be serviced correctly, a better, "realtime" way
> would be that the interrupt dispatcher code will check the state of the
> interrupt line AFTER the handlers have been called ONCE and, if the
> (GPIO?) line is still active, will call the handlers again. But this
> must be controlled by specific code in the dispatcher area of the BSP.
>
Not sure I understand this all but IMO in order to
properly support shared, edge-triggered interrupts
you must clear the interrupt at the IRQ controller
*before* dispatching them (so that a possible IRQ
raised by device 'X' just after the handler for 'X' returns
but before the interrupt is cleared in the IRQ controller
is not lost):
active_irqs = get_active_irqs();
if ( edge_triggered ) {
/* disable irqs so that new IRQ occurring just
* after clearing does not interrupt us again
* further down when we enable IRQS
*/
clear_irqs_at_irq_controller(active_irqs);
/* temporarily mask interrupts we're working on */
disable_irqs_at_irq_controller(active_irqs);
}
enable_interrupts(); /* enable other irqs during dipatch of the
handlers */
dispatch_all_handlers(active_irqs)
disable_interrupts(); /* turn off again */
if ( edge_triggered ) {
/* re-enable 'active_irqs' here. There could be an IRQ
* latched which has already be handled (occurred between
* clear_irqs_at_irq_controller() and the handler being
* called) but that would only result in an extra (unnecessary)
* execution of the irq dispatcher.
*/
enable_irqs_at_irq_controller(active_irqs);
} else {
/* clear active irqs. If a new level-triggered IRQ occurred
* after the corresponding handler was executed then
* the irq will be asserted again after clearing and
* the irq dispatcher will execute immediately.
*/
clear_irqs_at_irq_controller(active_irqs);
}
FWIW
-- Till
> wkr,
> Thomas.
>
>
More information about the users
mailing list