The _ISR_Handler
routine provides the RTEMS interrupt management.
void _ISR_Handler()
This discussion ignores a lot of the ugly details in a real implementation such as saving enough registers/state to be able to do something real. Keep in mind that the goal is to invoke a user's ISR handler which is written in C. That ISR handler uses a known set of registers thus allowing the ISR to preserve only those that would normally be corrupted by a subroutine call.
Also note that the exact order is to a large extent flexible. Hardware
will dictate a sequence for a certain subset of _ISR_Handler
while
requirements for setting the RTEMS state variables that indicate the
interrupt nest level (_ISR_Nest_level
) and dispatching disable
level (_Thread_Dispatch_disable_level
) will also
restrict the allowable order.
Upon entry to _ISR_Handler
, _Thread_Dispatch_disable_level
is
zero if the interrupt occurred while outside an RTEMS service call.
Conversely, it will be non-zero if interrupting an RTEMS service
call. Thus, _Thread_Dispatch_disable_level
will always be
greater than or equal to _ISR_Nest_level
and not strictly
equal.
Upon entry to the "common" _ISR_Handler
, the vector number must be
available. On some CPUs the hardware puts either the vector number or the
offset into the vector table for this ISR in a known place. If the
hardware does not provide this information, then the assembly portion of
RTEMS for this port will contain a set of distinct interrupt entry points
which somehow place the vector number in a known place (which is safe if
another interrupt nests this one) and branches to _ISR_Handler
.
save some or all context on stack may need to save some special interrupt information for exit #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) if ( _ISR_Nest_level == 0 ) switch to software interrupt stack #endif _ISR_Nest_level++; _Thread_Dispatch_disable_level++; (*_ISR_Vector_table[ vector ])( vector ); --_ISR_Nest_level; if ( _ISR_Nest_level ) goto the label "exit interrupt (simple case)" #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) restore stack #endif if ( _Thread_Dispatch_disable_level ) _ISR_Signals_to_thread_executing = FALSE; goto the label "exit interrupt (simple case)" if ( _Context_Switch_necessary || _ISR_Signals_to_thread_executing ) _ISR_Signals_to_thread_executing = FALSE; call _Thread_Dispatch() or prepare to return to _ISR_Dispatch prepare to get out of interrupt return from interrupt (maybe to _ISR_Dispatch) LABEL "exit interrupt (simple case): prepare to get out of interrupt return from interrupt
Some ports have the special routine _ISR_Dispatch
because
the CPU has a special "interrupt mode" and RTEMS must switch back
to the task stack and/or non-interrupt mode before invoking
_Thread_Dispatch
. For example, consider the MC68020 where
upon return from the outermost interrupt, the CPU must switch
from the interrupt stack to the master stack before invoking
_Thread_Dispatch
. _ISR_Dispatch
is the special port
specific wrapper for _Thread_Dispatch
used in this case.
Copyright © 1988-2003 OAR Corporation