DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
...
A generic up_doirq() might look like the following. It can be very simple because interrupts are disabled:
| Code Block |
|---|
uint32_t *up_doirq(int irq, uint32_t *regs) { /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. |
...
| Code Block |
|---|
*/ current_regs = regs; |
| Code Block |
/* Deliver the IRQ */
|
| Code Block |
irq_dispatch(irq, regs);
|
| Code Block |
/* If a context switch occurred while processing the interrupt then * current_regs may have change value. If we return any value |
...
| Code Block |
|---|
different * from the input regs, then the lower level will know that a context * switch occurred during interrupt processing. */ regs = (uint32_t*)current_regs; current_regs = NULL; return regs; } |
What has to change to support nested interrupts is:
...
So the modified version of up_doirq() would be as follows. Here we assume that interrupts are enabled.
| Code Block |
|---|
uint32_t *up_doirq(int irq, uint32_t *regs) { irqstate_t flags; |
| Code Block |
/* Current regs non-zero indicates that we are processing an interrupt; * regs holds the state of the interrupted logic; current_regs holds |
...
the * state of the interrupted user task. current_regs should, therefor, |
...
* only be modified for outermost interrupt handler (when g_nestlevel == 0) |
...
| Code Block |
|---|
*/ flags = irqsave(); if (g_nestlevel == 0) { current_regs = regs; } g_nestlevel++ irqrestore(flags); |
| Code Block |
/* Deliver the IRQ */
|
| Code Block |
irq_dispatch(irq, regs);
|
| Code Block |
/* Context switches are indicated by the returned value of this function. * If a context switch occurred while processing the interrupt |
...
then * current_regs may have change value. If we return any value |
...
| Code Block |
|---|
different * from the input regs, then the lower level will know that a context * switch occurred during interrupt processing. Context switching should * only be performed when the outermost interrupt handler returns. */ flags = irqsave(); g_nestlevel--; if (g_nestlevel == 0) { regs = (uint32_t*)current_regs; current_regs = NULL; } |
| Code Block |
/* Note that interrupts are left disabled. This needed if context switch * will be performed. But, any case, the correct interrupt state |
...
| Code Block |
|---|
should * be restored when returning from the interrupt. */ return regs; } |
NOTE: An alternative, cleaner design might also be possible. If one were to defer all context switching to a PendSV handler, then the interrupts could vector to the do_irq() logic and then all interrupts would be naturally nestable.
...