SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Step-by-Step Guide to Cortex-M0 PendSV Exception Handling
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

Step-by-Step Guide to Cortex-M0 PendSV Exception Handling

Andrew Irwin
Last updated: September 17, 2023 2:41 am
Andrew Irwin 6 Min Read
Share
SHARE

The Cortex-M0 processor implements a basic exception model with 7 exception types. The PendSV (pendable service request) exception is one of these and allows low priority or background tasks to be run when no other exception is active. Handling the PendSV exception properly is key to implementing an RTOS or multitasking firmware on Cortex-M0 devices.

Contents
What is the PendSV Exception?PendSV Exception Priority LevelEnabling the PendSV ExceptionPendSV Exception HandlerSaving ContextSwitching ContextsRestoring ContextReturning to Thread ModeSetting PendSV in Thread ModeUsing SysTick and PendSVTesting PendSV SwitchingConclusion

What is the PendSV Exception?

The PendSV exception is triggered by software to request a context switch to a low priority thread or task. This allows background processing or lower priority tasks to execute when the processor is idle or not handling other exceptions. The PendSV has the lowest priority of all exceptions, below even the SysTick timer interrupt. This ensures background tasks only run when all other system events are serviced.

PendSV Exception Priority Level

The Cortex-M0 processor implements a system of prioritized exceptions called the Nested Vectored Interrupt Controller (NVIC). There are 256 programmable priority levels, with 0 being the highest priority. Reset has fixed priority of -3, NMI has -2, HardFault has -1, and PendSV has priority 254 which is the lowest possible priority level.

Enabling the PendSV Exception

The PendSV exception must be enabled in order for it to trigger a context switch:

  1. Set the PENDSVSET bit in the Interrupt Control and State Register (ICSR) to pending.
  2. Configure the PendSV exception priority in the NVIC to level 254.
  3. Enable PendSV interrupts in the NVIC Interrupt Set Enable Register (ISER).

Once enabled, any write to the ICSR PENDSVSET bit will trigger a PendSV exception once all higher priority exceptions complete.

PendSV Exception Handler

The PendSV_Handler code is called when the processor vectors to the PendSV exception: void PendSV_Handler(void) { // Context save // Switch context // Context restore }

This handler must save the context of the current task, select the next task to run, restore its context, then return to Thread Mode to resume it. This completes the context switch to the new task.

Saving Context

The context of the current task must be saved before it can be switched out. This usually involves pushing CPU registers onto the current stack: // Save context __asm volatile( “MRS R0, PSP\n\t” “STMDB R0!, {R4-R11}\n\t” “PUSH {R0, LR}\n\t” );

The stack pointer, R0 through R11 registers, and the link register are saved. The PSP stack pointer should be used for context saving.

Switching Contexts

Once the current task context is saved, the next task can be selected and its context restored: // Switch context currentTask = nextTask; nextTask = pickNextTask();

This involves updating the current and next task pointers to the appropriate TCBs (Task Control Blocks). The pickNextTask() function selects the next highest priority task that is ready to run.

Restoring Context

The context of the next task must be restored before returning to Thread Mode: // Restore context __asm volatile( “LDR R0, =currentTask\n\t” “LDR R0, [R0]\n\t” “LDMIA R0!, {R4-R11}\n\t” “POP {R0, PC}\n\t” );

This loads the stack pointer and registers from the task’s TCB, before returning to the task using POP and PC. The PSP stack pointer should be restored before registers.

Returning to Thread Mode

Once the next task’s context is restored, the exception return takes place: __asm volatile( “MOV LR, #0xFFFFFFFD\n\t” “BX LR\n\t” );

The exception return value is set before performing a BX to LR. This restores the task’s EXC_RETURN value and switches back to Thread Mode.

Setting PendSV in Thread Mode

To request a context switch from Thread Mode, the PENDSVSET bit must be set in the ICSR register: void yield(void) { SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; }

This will trigger a PendSV exception once interrupts are enabled and all higher priority exceptions complete. The yield() function can be called by tasks to voluntarily give up the CPU.

Using SysTick and PendSV

The SysTick timer is commonly used with PendSV to create periodic context switches for an RTOS. When the SysTick expires, it sets the PENDSVSET bit to trigger a context switch: void SysTick_Handler(void) { SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; }

This allows the RTOS to periodically pause the current task and switch to the next highest priority task that is ready. The SysTick provides the heartbeat while PendSV performs the context switches.

Testing PendSV Switching

To test PendSV exception handling and context switching:

  1. Enable SysTick interrupts at a known frequency.
  2. Setup the PendSV handler and enable PendSV interrupts.
  3. Implement context saving/restoring in the PendSV handler.
  4. Toggle LEDs on each context switch to visually track switching.
  5. Call yield() to voluntarily invoke PendSV.

The LEDs blinking at the SysTick frequency confirm PendSV exception handling and context switches are working as expected.

Conclusion

The Cortex-M0 PendSV exception provides essential context switching capabilities for multitasking firmware. Combined with the SysTick timer, it enables simple cooperative RTOS implementations. Proper exception handling, context saving/restoring, and return procedures are key to leveraging PendSV in Cortex-M0 designs.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article Fixing Incorrect Vector Tables When Using a Bootloader with Cortex-M0
Next Article Bootloader Impact on Cortex-M0 PendSV Exception Handling
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

Is CMSIS a library?

Yes, CMSIS stands for Cortex Microcontroller Software Interface Standard and…

7 Min Read

ARM Cortex M Registers

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

6 Min Read

Cortex-M0 Vector Table Management with a Bootloader

The Cortex-M0 is one of ARM's smallest and simplest microcontroller…

9 Min Read

What is arm cortex-m support from embedded coder?

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

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

Sign in to your account