MPU

Definitions for ARMv6, ARMv7 and ARMv8 MPU configuration.

This file contains definitions and macros for configuring the Memory Protection Unit (MPU) on ARM cores. It includes definitions for execution permissions, access permissions, memory attributes, and memory types.

Defines

QRT_MPU_EXECUTE (0u)

Execute

QRT_MPU_EXECUTE_NEVER (1u)

Execute never

QRT_MPU_READWRITE (0u)

Read/write access for privileged and unprivileged code

QRT_MPU_READONLY (1u)

Read-only access for privileged and unprivileged code

QRT_MPU_DEVICE_NGNRNE (0u)
QRT_MPU_DEVICE_NGNRE (1u)
QRT_MPU_DEVICE_GRE (2u)

Not supported on ARMv6/7

QRT_MPU_STRONGLY_ORDERED (QRT_MPU_DEVICE_NGNRNE)

ARMv6/7 compatibility

QRT_MPU_DEVICE (QRT_MPU_DEVICE_NGNRE)

ARMv6/7 compatibility

QRT_MPU_NORM_NCACHE (3u)
QRT_MPU_NORM_WB_WRA (4u)

Outer & inner cacheable, write-back, write allocate

QRT_MPU_NORM_WT_NWA (5u)

Outer & inner cacheable, write-through, no write allocate

QRT_MPU_NORM_WB_NWA (6u)

Outer & inner cacheable, write-back, no write allocate

QRT_MPU_NONSHAREABLE (0x00u)

Non-shareable

QRT_MPU_INNER_SHAREABLE (0x01u)

Inner Shareable (not supported on ARMv6/7)

QRT_MPU_OUTER_SHAREABLE (0x02u)

Outer Shareable (Inner + Outer Shareable for ARMv6/7)

QRT_MPU_SHAREABLE (QRT_MPU_OUTER_SHAREABLE)

Inner + Outer Shareable

QRT_MPU_SUBREGION_DISABLE(mask) (((mask) & 0xFFu) << 8)

Not supported on ARMv8

Functions

qrt_s32_t qrt_mpu_threadregionadd(pthread_t thread, qrt_s32_t *region_id, qrt_u32_t executability, qrt_u32_t permissions, qrt_u32_t shareability, qrt_u32_t attributes, qrt_u32_t address, qrt_u32_t size)

Add a memory region to threads region table.

The region size is rounded up, not rejected: on ARMv6 and ARMv7 to the next power of two and to at least the minimum size (256 bytes for ARMv6, 32 bytes for ARMv7); on ARMv8 the end of the region is rounded up to the next 32-byte boundary.

Error numbers:

  • EINVAL Region base address is not aligned to the rounded-up region size (ARMv6 and ARMv7) or is not 32-byte aligned (ARMv8).

  • EINVAL executability, permissions, shareability or attributes is not one of the values supported on the core.

  • ENOSPC No more MPU regions available.

  • EPERM Called from unprivileged thread.

  • ENOSYS MPU support is disabled (QRT_CFG_MPU_ENABLE is 0).

Parameters:
  • thread – Thread handle; 0 selects the calling thread.

  • region_id – Pointer to assigned region ID. NULL if not needed.

  • executability – Executability of the region.

  • permissions – Permissions of the region: QRT_MPU_READWRITE or QRT_MPU_READONLY.

  • shareability – Shareability of the region.

  • attributes – Attributes of the region.

  • address – Base address of the region, aligned as described above.

  • size – Size of the region in bytes.

Returns:

0 if success, error number otherwise.

#define DEVICE_BASE (0x40010000u)
#define DEVICE_SIZE (0x100u)

void *driver_thread(void *arg);

qrt_s32_t start_driver(void)
{
    pthread_t driver;
    qrt_s32_t status;

    status = pthread_create(&driver, NULL, driver_thread, NULL);
    if (status == 0)
    {
        status = qrt_mpu_threadregionadd(driver, NULL,
                                         QRT_MPU_EXECUTE_NEVER,
                                         QRT_MPU_READWRITE,
                                         QRT_MPU_SHAREABLE,
                                         QRT_MPU_DEVICE,
                                         DEVICE_BASE, DEVICE_SIZE);
    }
    return status;
}

qrt_s32_t qrt_mpu_threadregionremove(pthread_t thread, qrt_s32_t region_number)

Remove a memory region from a thread’s region table. The calling thread must be privileged and the following rule applies: (5 < region_number < QRT_CFG_MPU_ENTRIES).

Parameters:
  • thread – Thread handle.

  • region_number – Region number to remove.

Returns:

0 if success EINVAL if 5 < region_number < QRT_CFG_MPU_ENTRIES not fulfilled. EPERM if called from unprivileged thread. ENOSYS if QRT_CFG_MPU_ENABLE is 0.

qrt_s32_t qrt_mpu_faultcallbackset(void (*callback)(pthread_t thread, qrt_u32_t address, qrt_u32_t pc, qrt_u32_t status))

Set an optional callback function that is invoked when a Memory Protection Unit (MPU) fault occurs. The registered callback allows the application to handle MPU faults, such as invalid memory accesses.

The registered callback will be called in the fault handler context, so it must be minimal and must not make any System Calls. ARMv7 and ARMv8 Mainline only. Only privileged threads can set the callback; an unprivileged caller gets EPERM and the callback already set stays in place.

Error numbers:

  • EINVAL Callback function pointer is NULL.

  • EPERM Called from unprivileged thread.

  • ENOSYS MPU support is disabled (QRT_CFG_MPU_ENABLE is 0), or the core is ARMv6 or ARMv8 Baseline.

Parameters:
  • callback –

    Pointer to the callback function. The function must match the signature void (*callback)(

    pthread_t thread,

    qrt_u32_t address,

    qrt_u32_t pc,

    qrt_u32_t status).

Returns:

0 if success, error number otherwise.

static volatile pthread_t fault_thread;
static volatile qrt_u32_t fault_address;

void mpu_fault(pthread_t thread, qrt_u32_t address,
               qrt_u32_t pc, qrt_u32_t status)
{
    (void)pc;
    (void)status;
    fault_thread  = thread;
    fault_address = address;
}

void *startup_thread(void *arg)
{
    (void)arg;
    (void)qrt_mpu_faultcallbackset(mpu_fault);
    return NULL;
}

void qrt_mpu_faulthandler(void)

MPU fault handler called when a Memory Protection Unit (MPU) fault occurs.

Must be called from the Memory Management interrupt handler.

void MemManage_Handler(void)
{
    qrt_mpu_faulthandler();
}