Embedded Design Handbook

ID 683689
Date 8/28/2023
Public
Document Table of Contents

4.3.3.4. Software

The design files accompanying this section include the following example software projects:

  • mpu_basic—Configures the MPU with several data and instruction regions, and prints a simple message.
  • mpu_exc_detection—Configures the MPU with the same data instruction regions as in mpu_basic, and sets up an exception handler to detect the following conditions:
    • Null pointer
    • Wild pointer
    • Stack overflow

The software examples in each subdirectory are identical. The code is written to detect the whether the MPU is configured for mask or limit region sizes, and to behave appropriately.

The mpu_exc_detection example detects stack overflow by creating a small high-priority exclusion data region in the middle of a larger data region where both the stack and the heap reside. Whenever the stack grows downwards or the heap grows upwards into this exclusion region, the MPU triggers an exception and the software detects it.

The mpu_exc_detection example detects null pointer usage by making sure that no regions include offset 0x0. The example system is designed such that no components (memory or otherwise) are located at this offset. If software attempts to access address 0x0, the MPU triggers an exception, allowing the software to recover. If you ensure that memories are preinitialized to zero, null pointer detection helps protects against uninitialized data access.

The mpu_exc_detection example detects wild pointer usage by creating very large low-priority exclusion regions covering the majority of the memory map. In this way, if the Nios® II processor attempts to access an address outside of valid memory and peripheral I/O address space, the MPU triggers an exception and software can detect it.

Both of these software examples use the MPU utility functions and macros in mpu_utils.c and mpu_utils.h. In both examples, initialization and reinitialization are handled by two functions: one for data regions, and one for instruction regions. In most real-world systems, a single function is sufficient to handle initialization and reinitialization for both types of regions.