Skip to main content
  • Products
  • Evaluate our Software
  • Downloads
  • Free Utilities
  • Purchase
  • Support
  • About Us
  • Blog
  • Forum
  • Search
    • Contact Us
    • Forum
    • Knowledge Base
    • Web Shop
    • Newsletter
    • RSS
  •   Jobs
  •   Videos
  •   Blog
  •   Sustainability
  • embOS
  • embOS-MPU example application
  • Editions
  • Technology
  • Supported Cores / Compiler
  • Tools

embOS-MPU
Example application

Suitable for any safety-critical application, embOS-MPU is available for any MCU containing a hardware MPU or MMU.

Contact us
Downloads
Documentation
SEGGER embOS-MPU

Example application

embOS-MPU offers simple and straightforward runtime configuration that is easy to integrate into both new and existing products. It provides an unlimited number of privileged and unprivileged tasks 100 % sandboxed.

The following example details embOS-MPU’s ease-of-use:

#include "RTOS.h"
#include "BSP.h"
#include <stdio.h>

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
//
// Linker symbols to get section addresses.
// embOS-MPU needs to know where RAM, ROM and the OS section is located.
//
extern unsigned int __FLASH_segment_start__;
extern unsigned int __FLASH_segment_size__;
extern unsigned int __RAM_segment_start__;
extern unsigned int __RAM_segment_size__;
extern unsigned int __os_start__;
extern unsigned int __os_size__;
//
// Control structures for tasks and event object
//
static OS_EVENT HW_Event;
static OS_TASK TCBHP;
static OS_TASK TCBLP;
//
// Stack for privileged task.
// This stack has not to be aligned because it does not affect MPU settings
//
static OS_STACKPTR int StackHP[128];
//
// Stack for unprivileged task. This will be used for MPU settings and with Cortex-M it requires alignment.
// In most cases, the same power of 2 will work for both size and alignment
//
static OS_STACKPTR int StackLP[128] __attribute__ ((aligned (512)));
//
// List of allowed OS objects for the LPTask
//
static const OS_MPU_OBJ _aObjList[] = { {(OS_U32)&HW_Event, OS_MPU_OBJTYPE_EVENT},
                                        {(OS_U32)NULL,      OS_MPU_OBJTYPE_INVALID}};  // Last entry

/*********************************************************************
*
*       Local functions
*
**********************************************************************
*/

/*********************************************************************
*
*       _HPTask()
*
*  Function description
*    High priority task.
*    Periodically resumes the low priority task via an event object
*/
static void _HPTask(void) {
  while (1) {
    BSP_ToggleLED(1);
    OS_EVENT_Set(&HW_Event);  // Signal Event to wake LP task
    OS_Delay(200);
  }
}

/*********************************************************************
*
*       _Recursive()
*
*  Function description
*    This function produces a stack overflow.
*    embOS detects the illegal memory access and automatically suspends
*    the task. Additionally the error callback function is called.
*/
static void _Recursive(unsigned int i) {
  volatile int k;
  k = i + 1;
  _Recursive(k);
}

/*********************************************************************
*
*       _Unpriv()
*
*  Function description
*    Routine for demonstrating an illegal memory access after
*    toggling an LED for 4 seconds.
*/
static void _Unpriv(void) {
  unsigned int i;

  for (i = 0u; i < 20u; i++) {
    OS_EVENT_Wait(&HW_Event);
    BSP_SetLED(0);
    OS_Delay(20);
    BSP_ClrLED(0);
  }
  //
  // Produce illegal memory access
  //
  _Recursive(1u);
}

/*********************************************************************
*
*       _LPTask()
*
*  Function description
*    Low priority task.
*/
static void _LPTask(void) {
  OS_MPU_SetAllowedObjects(&TCBLP, _aObjList);
  OS_MPU_SwitchToUnprivState();
  _Unpriv();
}

/*********************************************************************
*
*       _ErrorCallback()
*
*  Function description
*    User callback function which is called when an unprivileged task
*    does something disallowed, e.g. tries to write to memory which
*    does not belong to the task
*/
static void _ErrorCallback(OS_TASK* pTask, OS_MPU_ERRORCODE ErrorCode) {
  static const char* _sErrTxt[] = {  "OS_MPU_ERROR_INVALID_REGION", "OS_MPU_ERROR_INVALID_OBJECT",
                                     "OS_MPU_ERROR_INVALID_API", "OS_MPU_ERROR_HARDFAULT",
                                     "OS_MPU_ERROR_MEMFAULT", "OS_MPU_ERROR_BUSFAULT",
                                     "OS_MPU_ERROR_USAGEFAULT", "OS_MPU_ERROR_SVC"};
  printf("Task with ID 0x%x has been stopped due to error %s\n", (OS_U32)pTask, _sErrTxt[ErrorCode]);
}

/*********************************************************************
*
*       Global functions
*
**********************************************************************
*/

/*********************************************************************
*
*       main()
*/
int main(void) {
  OS_InitKern();                /* Initialize OS                 */
  OS_InitHW();                  /* Initialize Hardware for OS    */
  BSP_Init();                   /* Initialize LED ports          */
  //
  // Setup memory information, must be done before first task is created
  //
  OS_MPU_ConfigMem((OS_U32)&__FLASH_segment_start__, (OS_U32)&__FLASH_segment_size__,
                   (OS_U32)&__RAM_segment_start__,   (OS_U32)&__RAM_segment_size__,
                   (OS_U32)&__os_start__,            (OS_U32)&__os_size__);
  //
  // Setup optionally error callback function
  //
  OS_MPU_SetErrorCallback(&_ErrorCallback);
  //
  // Enable embOS-MPU support
  //
  OS_MPU_Enable();
  OS_CREATETASK(&TCBHP, "HP Task", _HPTask, 100, StackHP);
  OS_CREATETASK(&TCBLP, "LP Task", _LPTask,  50, StackLP);
  OS_EVENT_Create(&HW_Event);
  OS_Start();                   /* Start multitasking            */
  return 0;
}

Detailed description

The example application simulates a stack overflow and shows how the issue is handled by embOS-MPU. Easy to use, embOS-MPU needs just three additional API calls:

  • OS_MPU_ConfigMem()tells the OS where RAM, ROM and the OS is located in the memory.
  • OS_MPU_SetErrorCallback() sets an optional callback function which is called whenever embOS-MPU detects an issue.
  • OS_MPU_Enable() actually enables the memory protection unit.

The example application creates two tasks:

  • The HPTaskruns completely in a privileged state.
  • TheLPTask also starts in a privileged state but switches to unprivileged state with OS_MPU_SwitchToUnprivState().

The HPTask toggles a LED and sends events to the LPTask.

/*********************************************************************
*
*       main()
*/
int main(void) {
  OS_InitKern();                /* Initialize OS                 */
  OS_InitHW();                  /* Initialize Hardware for OS    */
  BSP_Init();                   /* Initialize LED ports          */
  //
  // Setup memory information, must be done before first task is created
  //
  OS_MPU_ConfigMem((OS_U32)&__FLASH_segment_start__, (OS_U32)&__FLASH_segment_size__,
                   (OS_U32)&__RAM_segment_start__,   (OS_U32)&__RAM_segment_size__,
                   (OS_U32)&__os_start__,            (OS_U32)&__os_size__);
  //
  // Setup optionally error callback function
  //
  OS_MPU_SetErrorCallback(&_ErrorCallback);
  //
  // Enable embOS-MPU support
  //
  OS_MPU_Enable();
  OS_CREATETASK(&TCBHP, "HP Task", _HPTask, 100, StackHP);
  OS_CREATETASK(&TCBLP, "LP Task", _LPTask, 50, StackLP);
  OS_EVENT_Create(&HW_Event);
  OS_Start();                   /* Start multitasking           */
  return 0;
}

The HPTask toggles a LED and sends events to the LPTask.

/*********************************************************************
*
*       _HPTask()
*
*  Function description
*    High priority task.
*    Periodically resumes the low priority task via an event object
*/
static void _HPTask(void) {
  while (1) {
    BSP_ToggleLED(1);
    OS_EVENT_Set(&HW_Event); // Signal Event to wake LP task
    OS_Delay(200);
  }
}

The LPTask adds permission to the event object before it switches to the unprivileged state with OS_MPU_SwitchToUnprivState().

/*********************************************************************
*
*       _LPTask()
*
*  Function description
*    Low priority task.
*/
static void _LPTask(void) {
  OS_MPU_SetAllowedObjects(&TCBLP, _aObjList);
  OS_MPU_SwitchToUnprivState();
  _Unpriv();
}

The _Unpriv() function runs in unprivileged state and toggles another LED for four seconds before it calls the function _Recursive().

/*********************************************************************
*
*       _Unpriv()
*
*  Function description
*    Routine for demonstrating an illegal memory access after
*    toggling an LED for 4 seconds.
*/
static void _Unpriv(void) {
  unsigned int i;

  for (i = 0u; i < 20u; i++) {
    OS_EVENT_Wait(&HW_Event);
    BSP_SetLED(0);
    OS_Delay(20);
    BSP_ClrLED(0);
  }
  //
  // Produce illegal memory access
  //
  _Recursive(1u);
}

The function _Recursive() generates the actual stack overflow.

/*********************************************************************
*
*       _Recursive()
*
*  Function description
*    This function produces a stack overflow.
*    embOS detects the illegal memory access and automatically suspends
*    the task. Additionally the error callback function is called.
*/
static void _Recursive(unsigned int i) {
  volatile int k;
  k = i + 1;
  _Recursive(k);
}

embOS-MPU will terminate the LPTask as soon as the task tries to write to memory outside its task stack. Additionally the error callback function is called. The error callback function prints a message with the task id and the error cause. The HPTask and the OS are not affected and still run.

/*********************************************************************
*
*       _ErrorCallback()
*
*  Function description
*    User callback function which is called when an unprivileged task
*    does something disallowed, e.g. tries to write to memory which
*    does not belong to the task
*/
static void _ErrorCallback(OS_TASK* pTask, OS_MPU_ERRORCODE ErrorCode) {
  static const char* _sErrTxt[] = {  "OS_MPU_ERROR_INVALID_REGION", "OS_MPU_ERROR_INVALID_OBJECT",
                                     "OS_MPU_ERROR_INVALID_API", "OS_MPU_ERROR_HARDFAULT",
                                     "OS_MPU_ERROR_MEMFAULT", "OS_MPU_ERROR_BUSFAULT",
                                     "OS_MPU_ERROR_USAGEFAULT", "OS_MPU_ERROR_SVC"};
  printf("Task with ID 0x%x has been stopped due to error %s\n", (OS_U32)pTask, _sErrTxt[ErrorCode]);
}

Headquarters

SEGGER Microcontroller GmbH

Ecolab-Allee 5
40789 Monheim am Rhein, Germany
info@segger.com
Tel.: +49-2173-99312-0
Fax: +49-2173-99312-28

Locations

USA: SEGGER Microcontroller Systems LLC

Boston area
101 Suffolk Lane
Gardner, MA 01440, USA
us-east@segger.com
Tel.: +1-978-874-0299
Fax: +1-978-874-0599

Silicon Valley
Milpitas, CA 95035, USA
us-west@segger.com
Tel.: +1-408-767-4068

China: SEGGER Microcontroller China Co., Ltd.

Room 218, Block A, Dahongqiaoguoji
No. 133 Xiulian Road
Minhang District, Shanghai 201199, China
china@segger.com
Tel.: +86-133-619-907-60

ISO 9001 certified

ISO 9001

30+ years of experience

First-class embedded software tools since 1992
  • Imprint
  • Disclaimer
  • Privacy Policy
© 2025 SEGGER - All rights reserved.