From b94c5b16fe7e1dc6ac9eff1b0db56cc9fe7b86ab Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Wed, 29 Mar 2017 11:26:08 +0100 Subject: [PATCH] arm: core: mpu: Add core support to ARM MPU This patch add arm core MPU support to ARM MPU driver. Change-Id: I5a61da4615ae687bf42f1c9947e291ebfd2d2c1d Signed-off-by: Vincenzo Frascino --- arch/arm/core/cortex_m/mpu/arm_mpu.c | 95 ++++++++++++++++++++++++- include/arch/arm/cortex_m/mpu/arm_mpu.h | 8 +++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/arch/arm/core/cortex_m/mpu/arm_mpu.c b/arch/arm/core/cortex_m/mpu/arm_mpu.c index 6b3452e7954..8a0f00ee709 100644 --- a/arch/arm/core/cortex_m/mpu/arm_mpu.c +++ b/arch/arm/core/cortex_m/mpu/arm_mpu.c @@ -10,9 +10,45 @@ #include #include #include +#include +#include #define ARM_MPU_DEV ((volatile struct arm_mpu *) ARM_MPU_BASE) +/* ARM MPU Enabled state */ +static u8_t arm_mpu_enabled; + +/** + * The attributes referenced in this function are described at: + * https://goo.gl/hMry3r + * This function is private to the driver. + */ +static inline u32_t _get_region_attr(u32_t xn, u32_t ap, u32_t tex, + u32_t c, u32_t b, u32_t s, + u32_t srd, u32_t size) +{ + return ((xn << 28) | (ap) | (tex << 19) | (s << 18) + | (c << 17) | (b << 16) | (srd << 5) | (size)); +} + +/** + * This internal function is utilized by the MPU driver to parse the intent + * type (i.e. THREAD_STACK_REGION) and return the correct parameter set. + */ +static inline u32_t _get_region_attr_by_type(u32_t type, u32_t size) +{ + switch (type) { + case THREAD_STACK_REGION: + return 0; + case THREAD_STACK_GUARD_REGION: + return _get_region_attr(1, P_RO_U_RO, 0, 1, 0, + 1, 0, REGION_32B); + default: + /* Size 0 region */ + return 0; + } +} + static inline u8_t _get_num_regions(void) { u32_t type = ARM_MPU_DEV->type; @@ -32,6 +68,61 @@ static void _region_init(u32_t index, u32_t region_addr, ARM_MPU_DEV->rasr = region_attr | REGION_ENABLE; } +/* ARM Core MPU Driver API Implementation for ARM MPU */ + +/** + * @brief enable the MPU + */ +void arm_core_mpu_enable(void) +{ + if (arm_mpu_enabled == 0) { + /* Enable MPU */ + ARM_MPU_DEV->ctrl = ARM_MPU_ENABLE | ARM_MPU_PRIVDEFENA; + + arm_mpu_enabled = 1; + } +} + +/** + * @brief disable the MPU + */ +void arm_core_mpu_disable(void) +{ + if (arm_mpu_enabled == 1) { + /* Disable MPU */ + ARM_MPU_DEV->ctrl = 0; + + arm_mpu_enabled = 0; + } +} + +/** + * @brief configure the base address and size for an MPU region + * + * @param type MPU region type + * @param base base address in RAM + * @param size size of the region + */ +void arm_core_mpu_configure(u8_t type, u32_t base, u32_t size) +{ + SYS_LOG_DBG("Region info: 0x%x 0x%x", base, size); + /* + * The new MPU regions are are allocated per type after the statically + * configured regions. + */ + u32_t region_index = mpu_config.num_regions + type; + u32_t region_attr = _get_region_attr_by_type(type, size); + + /* ARM MPU supports up to 16 Regions */ + if (region_index > _get_num_regions()) { + return; + } + + _region_init(region_index, base, region_attr); +} + +/* ARM MPU Driver Initial Setup */ + /* * @brief MPU default configuration * @@ -58,7 +149,9 @@ static void _arm_mpu_config(void) } /* Enable MPU */ - ARM_MPU_DEV->ctrl = 1; + ARM_MPU_DEV->ctrl = ARM_MPU_ENABLE | ARM_MPU_PRIVDEFENA; + + arm_mpu_enabled = 1; /* Make sure that all the registers are set before proceeding */ __DSB(); diff --git a/include/arch/arm/cortex_m/mpu/arm_mpu.h b/include/arch/arm/cortex_m/mpu/arm_mpu.h index a87390fbaf8..5a8399ef9d7 100644 --- a/include/arch/arm/cortex_m/mpu/arm_mpu.h +++ b/include/arch/arm/cortex_m/mpu/arm_mpu.h @@ -35,6 +35,14 @@ struct arm_mpu { #define ARM_MPU_BASE 0xE000ED90 +/* ARM MPU CTRL Register */ +/* Enable MPU */ +#define ARM_MPU_ENABLE (1 << 0) +/* Enable MPU during hard fault, NMI, and FAULTMASK handlers */ +#define ARM_MPU_HFNMIENA (1 << 1) +/* Enable privileged software access to the default memory map */ +#define ARM_MPU_PRIVDEFENA (1 << 2) + #define REGION_VALID (1 << 4) /* eXecute Never */