If your system doesn't support a programmable interrupt controller and you want tasks to be rescheduled when interrupts occur then on entry to an ISR the register state of the current task must be saved and the ctl_interrupt_count variable must be incremented.

When you are executing an interrupt handler the ctl_task_wait function should not be called. Other CrossWorks tasking library functions may be called but a task switch will only occur when the last interrupt handler has complete execution.

In order to achieve a task switch from an interrupt service routine the ctl_exit_isr function must be called (or rather jumped to) as the last action of an interrupt service routine.

void

ctl_exit_isr(void *savedRegisters);

The savedRegisters parameter points to the registers saved on the stack on entry to the interrupt service routine. This function will decrement the TaskInterruptCount variable and if it is zero it will check if a task switch is required. If a task switch is needed then the register state in savedRegisters will be stored in the currently executing task and a new task will be made the executing task. If a context switch isn't required or the ctl_interrupt_count is non-zero then the register state in savedRegisters is restored and the interrupt handler returns.

Interrupt Service Routine ARM example

This example declares an ISR using the GCC syntax for declaring naked functions and accessing assembly code instructions.

void irq_handler(void) __attribute__((naked));



void

irq_handler(void)

{

  asm("stmfd sp!, {r0-r12, lr}"); 

  asm("mrs r0, spsr");

  asm("stmfd sp!, {r0}");

  ctl_interrupt_count++;

  ....

  // do interrupt handling stuff in here

  ....

  asm("mov r0, sp");

  asm("b ctl_exit_isr");

}

Note that the registers spsr, r0-r12 and the r14 (user mode pc) must be saved on the stack. The user mode r13 and r14 registers don't need to be saved because they are held in banked registers.

Note that FIQ handlers are not supported on the ARM.

Interrupt Service Routine MSP430 example

This example declares an ISR using the CrossWorks assembler. Currently there is no way to use the CrossWorks C compiler to declare an ISR that can be used with the CrossWorks tasking library.

ISR:

  push.w r4

  push.w r5

  push.w r6

  push.w r7

  push.w r8

  push.w r9

  push.w r10

  push.w r11

  push.w r12

  push.w r13

  push.w r14

  push.w r15        

  add.w #1, &_ctl_interrupt_count           

  ....

  // do interrupt handling stuff in here

  ....

  mov.w sp, r15        

  jmp _ctl_exit_isr

Note that registers r4-r15 have to be saved on the stack - the pc and status registers are saved by the processor when the interrupt occurs.