eCos Product

eCos Net Distribution


RedBoot Product
 
RedBoot Net Distribution


Supported Hardware

Downloading and Installation

Documentation

FAQ

Keeping in Touch

Problems

Licensing

Anonymous CVS

Contributions and Third Party Projects

Red Hat eCos

eCos Interrupts [TBD]


Interrupt system
  • Path: (Vector decoding function) -> Interrupt VSRs -> Interrupt ISRs -> Interrupt DSRs
  • Porting: kernel clock, using hal/intr.c test to ensure it's working
  • Arbitration: Where to draw the line between HAL an application responsibilities. See PPC mpc8xx HAL for examples of some simple interrupt arbiters.
  • Context switches & interrupts:
    • context switch code saves/restores interrupt state
    • initial thread context must enable interrupts.
ISR/DSR description (Gary Thomas):
The idea of this code (why I changed it in the first place) was to be
able to enable interrupts while processing DSRs, but insure that the
processing took place on the interrupt stack.  The previous implementation
had simply enabled interrupts in the VSR, after switching to the thread
stack, but before calling "interrupt_end".  This was clearly wrong as
it required all thread stacks to be large enough to handle any possible
interrupt nesting.

The way it is supposed to work is like this (pseudo-code to abstract
machine details):

VSR:
  mask interrupts (if necessary)
  save interrupt context on thread stack 
  lock scheduler
  switch to interrupt stack (if defined)
  call ISR
  switch back to thread stack
  call interrupt_end
  restore interrupt context from thread stack
  exit VSR

Note: interrupt_end called with interrupts disabled, scheduler locked

interrupt_end:
  possibly schedule a DSR, based on paramters from VSR
  drop scheduler lock  
  if scheduling enabled, run pending DSRs (actually just part of scheduling)
  note: interrupts are still disabled when entered from VSR

hal_interrupt_stack_call_pending_DSRs:
  [disable interrupts (may be moot)]
  switch to interrupt stack
  enable interrupts
  run DSRs
  disable interrupts
  switch back to thread stack
  restore interrupts


Remember the premise: run DSRs with interrupts enabled, using the separate
interrupt stack.  However, this can't be done directly by the VSR since DSRs
must be scheduled (i.e. they can't run until scheduling is allowed).  In
order to keep the knowledge of how this works (proper layering) out of the
VSRs, it has to be in 'interrupt_end', thus the additional complexity.
Hugo had another nice description (pretty much the same):
eCos interrupt handlers currently tend to go
	o [all interrupts are masked]
	o Stash initial regset on app stack [1]
	o switch to interrupt stack [1]
	o unmask higher prio interrupts than current source
	o call ISRs
	o switch back to app stack [1]
	o call into scheduler
	o if scheduler is unlocked, then // not a recursive interrupt
	o    if there are DSRs to call
	o       switch to interrupt stack
	o       run DSRs
	o       switch back to app stack
	o    if reschedule is needed
	o       switch to new thread
	o       (saves context on interrupted app stack)
	o       (when this thread resumes, drop out to...)
	o restore initial regset from app stack
	o RTI sequence, unmasking all interrupts

[1] recursive interrupts might mean you are already in the interrupt stack,
    so you don't switch stacks at all in that case.
And Nick had something to say about separate interrupt stacks:
> As far as i know there is no separate interrupt stack for the i386-PC
> target, am I right?
> 
> So how should this be done ? Any advice ? Someone already thought of that?
> 

The basic advice here is to take a look at an architecture that
already has this done, I always suggest MIPS. Take a look at the bits
surrounded by the CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
ifdefs in vectors.S.

There are basically three pieces of code that need to be written:

1. Early in the interrupt VSR detect whether you are already on the
   interrupt stack and move to it if not.

2. Before calling interrupt_end() move back to the thread stack for
   the last nested interrupt to be returned from. The technique of
   always pushing the original stack address in step 1 and just
   popping it here makes this very simple.

3. Write the hal_interrupt_stack_call_pending_DSRs function. This just
   switches to the interrupt stack, enables interrupts and calls back
   into the kernel to call DSRs. The only complication here is to make
   sure that the original interrupt state is restored before
   returning.

And that's all there is to it.