Processor modes and interrupts

All CTL threads run in privileged thread mode.

When CTL requires exclusive access to variables—for example when traversing the task list—interrupts are disabled using calls to ctl_global_interrupts_disable and ctl_global_interrupts_enable.

The default implementation of global interrupt disable and enable for the Cortex-M3/M4 will set or clear the top bit of the BASEPRI register. This enables interrupts that have the highest half of the available priority numbers (lowest priority levels) to use CTL API calls. The lowest half of the available priority numbers (highest priority levels) cannot use CTL API calls but will not be disabled during CTL API calls. If, for example, the device has four priority bits, then priority numbers 8 through 15 can be used for interrupts that make CTL API calls and priorities 0 through 7 can be used for interrupts that cannot make CTL API calls.

The default implementation of global interrupts and enable for the Cortex-M0/M1 will set or clear the PRIMASK register.

Exceptions

Context switching is implemented using the PendSV exception handler which should be set to run at the lowest exception priority i.e. the highest exception priority number. The SVCall exception handler is not used.

Stacks

CTL threads use the Cortex-M process stack pointer (psp) and exceptions use the main stack pointer (msp). This means that you don't have to allocate space for exceptions in the thread stacks.

Register save order

When a task is not executing, the register context is saved on the task's stack in the following order:

…with the stack_pointer member of the task structure pointing to the R4 entry which requires 16 words of memory.

For Cortex-M4F the 32 single precision floating point registers are also saved when they have been used by a task. This changes the register context saved on the task's stack to:

…with the stack_pointer member of the task structure pointing to the S16 entry (with 1 added to indicate that the floating point registers have been saved) which requires 49 words of memory.

Interrupt handlers

A Cortex-M interrupt handler that uses CTL services should use the following template code for entry and exit:

void SysTick_ISR(void)
{
  ctl_enter_isr();// handle interrupt herectl_exit_isr();
}

The call to ctl_enter_isr will increment the ctl_interrupt_count and the call to ctl_exit_isr will decrement the ctl_interrupt_count and, if required, trigger the PendSV exception.

Note that you must ensure that an interrupt handler that uses CTL services cannot interrupt an interrupt handler that does not use CTL services. You can do this by setting the interrupt priority of interrupt handlers that do not use CTL services to be higher than those that do.

Interrupt handler support code (including ctl_enter_isr and ctl_exit_isr) is not part of CTL, but there are common definitions that are available in ctl_api.h and will be defined by code or libraries supplied by the CPU support package you are using.

System timer

The CPU support package you are using will use the Cortex-M SysTick timer to implement the CTL timer. Typically, the timer will be programmed to interrupt at 10 millisecond intervals and increment the CTL timer by 10 to create the millisecond CTL timer.