eCos Product
RedBoot Product
Supported Hardware |
![]() eCos Interrupts [TBD]Interrupt system
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. |