SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: How to Switch Between Programs on the Cortex-M0?
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

How to Switch Between Programs on the Cortex-M0?

Neil Salmon
Last updated: September 16, 2023 2:55 pm
Neil Salmon 6 Min Read
Share
SHARE

The Cortex-M0 is an extremely low power and space efficient 32-bit microcontroller aimed at simple, low-cost embedded applications. One of the key features of the Cortex-M0 is its ability to quickly switch between different programs or contexts. This allows you to create complex applications with multiple tasks while maintaining real-time responsiveness.

Contents
Context Switching on Cortex-M0Setting Up the SysTick TimerContext Switching ProcedureDefining Tasks for Context SwitchingExample Task DefinitionStarting the SchedulerPrioritizing Tasks with NVICAdvanced Context Switching MethodsPotential Issues with Context SwitchingConclusion

Context Switching on Cortex-M0

Context switching refers to the ability of an operating system or firmware to store the current state of a running program or task, so that it can later resume execution from the same point. This allows multiple programs to share the M0’s single core by taking turns running.

On the Cortex-M0, context switching is handled by the NVIC (Nested Vectored Interrupt Controller) and SysTick peripherals. When an interrupt or timer event occurs, the NVIC suspends the currently running program, saves its context, handles the interrupt, then recalls the previous context to resume where it left off.

Setting Up the SysTick Timer

The SysTick peripheral is a simple countdown timer that can be used to trigger context switches. To configure it for context switching:

  1. Enable the SysTick peripheral clock in RCC register.
  2. Configure SYST_RVR register with the timer reload value (e.g. 48MHz clock -> 1ms tick)
  3. Write 0x07 to SYST_CVR to clear the current value register.
  4. Enable SysTick and its interrupt by writing to SYST_CSR.

This will start the SysTick timer, which will then call the SysTick_Handler() interrupt each time the timer reaches zero. This periodic interrupt can be used to trigger a context switch.

Context Switching Procedure

A basic context switch procedure on Cortex-M0 involves:

  1. Saving context of current task/program:
    • Push registers onto stack using exception handling
    • Stack pointer moved to task’s stack
  2. Retrieve context of next task:
    • Pop registers from next task’s stack
    • Load stack pointer for next task
  3. Resume execution of next task

The SysTick_Handler implements this context save/restore by using the PendSV exception. Pushing registers onto the current stack, loading the stack pointer from the next task’s TCB, then doing the opposite to restore the new task.

Defining Tasks for Context Switching

To enable context switching between multiple programs, each program must be defined as a separate task. This involves:

  • Defining a task control block (TCB) to store context – stack pointer, registers etc.
  • Allocating stack space for each task’s context
  • Creating task functions as separate code modules
  • Scheduling policy to select next task

Task 1 and Task 2 can then be switched in and out by saving each one’s context to its TCB/stack area. The scheduler policy determines which task runs after each timer interrupt.

Example Task Definition

// Task Control Blocks
#define TASK1_STACK_SIZE 64 
static uint32_t Task1Stack[TASK1_STACK_SIZE];

// Task Stacks
static TCB Task1TCB; 

// Task Functions
void Task1_Handler() {
  // Task 1 code... 
}

// Scheduler Policy 
void Scheduler_SelectNextTask() {
  if(currentTask == &Task1TCB) {
    currentTask = &Task2TCB; 
  }
  else {
    currentTask = &Task1TCB;
  }
}

Starting the Scheduler

To start context switching between tasks:

  1. Set up SysTick for timer interrupts
  2. Enable PendSV exception in NVIC
  3. Initialize task TCBs and stacks
  4. Call OS scheduler start routine

This will begin context switching between the defined tasks each time the SysTick interrupt occurs. The PendSV handler manages the context switch itself.

Prioritizing Tasks with NVIC

Setting interrupt priorities allows more important tasks to preempt less important ones. This can be achieved by:

  • Assign priority level 0 – 3 to each task’s exception in NVIC
  • Set BASEPRI register to prevent interrupts below a threshold
  • Use PRIMASK to enable/disable all exceptions

For example, BASEPRI=2 will only allow exceptions at priority 2 or higher to trigger. This allows higher priority tasks to run more frequently.

Advanced Context Switching Methods

Some advanced techniques to optimize context switching on Cortex-M0 include:

  • Lazy Context Saving – Only save the registers that are actually modified rather than the entire context.
  • Stack Limit Checking – Check for stack overflow to prevent corruption.
  • Tickless Idle – Stop SysTick timer when idle to reduce power.
  • Lockless Scheduling – Use atomic bitwise operations to schedule without disabling interrupts.

However these add complexity and are often not needed for simple applications. The basic methods are usually sufficient.

Potential Issues with Context Switching

Some potential issues to be aware of when implementing context switching include:

  • Race Conditions – Tasks accessing shared resources without synchronization.
  • Stack Overflow – Running out of stack space for context saves.
  • Priority Inversion – High priority task blocked by lower priority task.
  • Deadlock – Two or more competing tasks waiting on each other.

Careful design with use of mutexes, semaphores, priority inheritance etc can resolve these issues.

Conclusion

In summary, the Cortex-M0 allows preemptive context switching between multiple tasks using its SysTick timer and PendSV exception. This involves defining tasks as separate code modules, allocating stack space for their context, and scheduling policy to determine task switching. Care must be taken to avoid race conditions, deadlock and other concurrency issues when sharing resources between tasks.

With good design, context switching allows much more complex behaviors compared to a simple superloop, while retaining the Cortex-M0’s low cost and power efficiency for embedded applications.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article Cortex M0 toggle pins not responding
Next Article Cortex-M0+ core Hang up in FFFF FFFEh address when executing DSB instruction
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

What is the use of arm cortex M?

The ARM Cortex-M is a group of 32-bit RISC ARM…

6 Min Read

What is the reset sequence in ARM Cortex-M0?

The reset sequence in ARM Cortex-M0 microcontrollers involves several steps…

8 Min Read

ARM Cortex-M4 Microcontroller

The ARM Cortex-M4 is a 32-bit microcontroller core developed by…

7 Min Read

Tips on Implementing Cortex-M1 Bootloader

Implementing a bootloader for Cortex-M1 chips allows greater control and…

12 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account