From cdc61c5954ce66319bf7883f13497e7a9c3bb957 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Tue, 11 Dec 2018 08:42:12 -0600 Subject: [PATCH 1/9] Use MPU platform deinit rather than hal free Use the MPU through the platform layer rather than through the HAL. --- platform/mbed_application.c | 4 ++-- platform/mbed_mpu_mgmt.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/mbed_application.c b/platform/mbed_application.c index b55519491b..ae925a3b36 100644 --- a/platform/mbed_application.c +++ b/platform/mbed_application.c @@ -19,7 +19,7 @@ #include #include "device.h" #include "platform/mbed_application.h" -#include "hal/mpu_api.h" +#include "platform/mbed_mpu_mgmt.h" #if MBED_APPLICATION_SUPPORT @@ -69,7 +69,7 @@ void mbed_start_application(uintptr_t address) SysTick->CTRL = 0x00000000; powerdown_nvic(); powerdown_scb(address); - mbed_mpu_free(); + mbed_mpu_manager_deinit(); sp = *((void **)address + 0); pc = *((void **)address + 1); diff --git a/platform/mbed_mpu_mgmt.h b/platform/mbed_mpu_mgmt.h index 6140c3110f..8364941d79 100644 --- a/platform/mbed_mpu_mgmt.h +++ b/platform/mbed_mpu_mgmt.h @@ -35,6 +35,8 @@ extern "C" { #define mbed_mpu_manager_init() mbed_mpu_init() +#define mbed_mpu_manager_deinit() mbed_mpu_free() + /** Lock ram execute never mode off * * This disables the MPU's execute never ram protection and allows @@ -87,6 +89,8 @@ void mbed_mpu_manager_unlock_rom_write(void); #define mbed_mpu_manager_init() (void)0 +#define mbed_mpu_manager_deinit() (void)0 + #define mbed_mpu_manager_lock_ram_execution() (void)0 #define mbed_mpu_manager_unlock_ram_execution() (void)0 From e585eac31bd7a0dc6e17ee9ffbeac2a0385e9a72 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Tue, 11 Dec 2018 16:01:34 +0200 Subject: [PATCH 2/9] Fix MPU synchronisation Synchronisation instructions were not quite right - too strict on entry, and not quite correctly synchronising the instruction stream on exit. References: * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf * https://static.docs.arm.com/100699/0100/armv8m_architecture_memory_protection_unit_100699_0100_00_en.pdf --- hal/mpu/mbed_mpu_v7m.c | 16 ++++++++-------- hal/mpu/mbed_mpu_v8m.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/hal/mpu/mbed_mpu_v7m.c b/hal/mpu/mbed_mpu_v7m.c index 5778e74739..d4cfbcf79d 100644 --- a/hal/mpu/mbed_mpu_v7m.c +++ b/hal/mpu/mbed_mpu_v7m.c @@ -45,7 +45,7 @@ MBED_STATIC_ASSERT( void mbed_mpu_init() { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; if (regions < 4) { @@ -178,40 +178,40 @@ void mbed_mpu_init() (1 << MPU_CTRL_ENABLE_Pos); // Enable MPU // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } void mbed_mpu_free() { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); // Disable the MPU MPU->CTRL = 0; // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } void mbed_mpu_enable_rom_wn(bool enable) { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); MPU->RNR = 0; MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } void mbed_mpu_enable_ram_xn(bool enable) { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); MPU->RNR = 1; MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); @@ -223,8 +223,8 @@ void mbed_mpu_enable_ram_xn(bool enable) MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } #endif diff --git a/hal/mpu/mbed_mpu_v8m.c b/hal/mpu/mbed_mpu_v8m.c index 7304c149b9..15225733ad 100644 --- a/hal/mpu/mbed_mpu_v8m.c +++ b/hal/mpu/mbed_mpu_v8m.c @@ -35,7 +35,7 @@ MBED_STATIC_ASSERT(MBED_MPU_ROM_END == 0x1fffffff, "Changing MBED_MPU_ROM_END fo void mbed_mpu_init() { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; if (regions < 4) { @@ -127,40 +127,40 @@ void mbed_mpu_init() (1 << MPU_CTRL_ENABLE_Pos); // Enable MPU // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } void mbed_mpu_free() { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); // Disable the MCU MPU->CTRL = 0; // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } void mbed_mpu_enable_rom_wn(bool enable) { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); MPU->RNR = 0; MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } void mbed_mpu_enable_ram_xn(bool enable) { // Flush memory writes before configuring the MPU. - __DSB(); + __DMB(); MPU->RNR = 1; MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); @@ -172,8 +172,8 @@ void mbed_mpu_enable_ram_xn(bool enable) MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); // Ensure changes take effect - __ISB(); __DSB(); + __ISB(); } #endif From 2b5518a3d881a9cebb2a68f2998535754bdeda5e Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Tue, 11 Dec 2018 18:21:04 +0200 Subject: [PATCH 3/9] Reduce dynamic MPU code size with a loop --- hal/mpu/mbed_mpu_v7m.c | 20 ++++++++++---------- hal/mpu/mbed_mpu_v8m.c | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/hal/mpu/mbed_mpu_v7m.c b/hal/mpu/mbed_mpu_v7m.c index d4cfbcf79d..51112a6707 100644 --- a/hal/mpu/mbed_mpu_v7m.c +++ b/hal/mpu/mbed_mpu_v7m.c @@ -195,13 +195,18 @@ void mbed_mpu_free() __ISB(); } +static void enable_region(bool enable, uint32_t region) +{ + MPU->RNR = region; + MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable << MPU_RASR_ENABLE_Pos); +} + void mbed_mpu_enable_rom_wn(bool enable) { // Flush memory writes before configuring the MPU. __DMB(); - MPU->RNR = 0; - MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); + enable_region(enable, 0); // Ensure changes take effect __DSB(); @@ -213,14 +218,9 @@ void mbed_mpu_enable_ram_xn(bool enable) // Flush memory writes before configuring the MPU. __DMB(); - MPU->RNR = 1; - MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); - - MPU->RNR = 2; - MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); - - MPU->RNR = 3; - MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0); + for (uint32_t region = 1; region <= 3; region++) { + enable_region(enable, region); + } // Ensure changes take effect __DSB(); diff --git a/hal/mpu/mbed_mpu_v8m.c b/hal/mpu/mbed_mpu_v8m.c index 15225733ad..b1f98f43bf 100644 --- a/hal/mpu/mbed_mpu_v8m.c +++ b/hal/mpu/mbed_mpu_v8m.c @@ -144,13 +144,18 @@ void mbed_mpu_free() __ISB(); } +static void enable_region(bool enable, uint32_t region) +{ + MPU->RNR = region; + MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable << MPU_RLAR_EN_Pos); +} + void mbed_mpu_enable_rom_wn(bool enable) { // Flush memory writes before configuring the MPU. __DMB(); - MPU->RNR = 0; - MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); + enable_region(enable, 0); // Ensure changes take effect __DSB(); @@ -162,14 +167,9 @@ void mbed_mpu_enable_ram_xn(bool enable) // Flush memory writes before configuring the MPU. __DMB(); - MPU->RNR = 1; - MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); - - MPU->RNR = 2; - MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); - - MPU->RNR = 3; - MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0); + for (uint32_t region = 1; region <= 3; region++) { + enable_region(enable, region); + } // Ensure changes take effect __DSB(); From 9e300013e52ab3edacddf5b9f7a049ae0e4b58f3 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Tue, 11 Dec 2018 18:21:28 +0200 Subject: [PATCH 4/9] MPU - use higher-level calls, fix ARMv8-M error Switch to higher-level calls and macros, and fix an error in the ARMv8-M version - "inner" attributes were not being set correctly due to a copy/paste error - "outer" was being set twice. This means RAM would have been marked WTRA rather than WBWA for the inner cache. Slightly reduces ARMv7-M init code size by feeding region number into RBAR instead of using RNR. --- hal/mpu/mbed_mpu_v7m.c | 66 ++++++++++++------------- hal/mpu/mbed_mpu_v8m.c | 110 ++++++++++++++++++++++------------------- 2 files changed, 89 insertions(+), 87 deletions(-) diff --git a/hal/mpu/mbed_mpu_v7m.c b/hal/mpu/mbed_mpu_v7m.c index 51112a6707..57c63f4c4d 100644 --- a/hal/mpu/mbed_mpu_v7m.c +++ b/hal/mpu/mbed_mpu_v7m.c @@ -74,13 +74,12 @@ void mbed_mpu_init() * 0xE0000000 - 0xFFFFFFFF System No */ - // Select region 1 and used it for the WT rom region - // - RAM 0x00000000 to MBED_MPU_ROM_END - MPU->RNR = 0; - // Set address to 0 - MPU->RBAR = 0; - // Configure and enable region - MPU->RASR = + // Select region 0 and use it for the WT read-only rom region + // - Code 0x00000000 to MBED_MPU_ROM_END + ARM_MPU_SetRegion( + ARM_MPU_RBAR( + 0, // Region + 0x00000000), // Base ARM_MPU_RASR( 0, // DisableExec ARM_MPU_AP_RO, // AccessPermission @@ -97,16 +96,15 @@ void mbed_mpu_init() ((MBED_MPU_ROM_END >= 0x14000000) ? 0 : (1 << 5)) | ((MBED_MPU_ROM_END >= 0x18000000) ? 0 : (1 << 6)) | ((MBED_MPU_ROM_END >= 0x1C000000) ? 0 : (1 << 7)), - ARM_MPU_REGION_SIZE_512MB // Size - ); + ARM_MPU_REGION_SIZE_512MB) // Size + ); - // Select region 1 and used it for the WT rom region - // - RAM MBED_MPU_ROM_END + 1 to 0x1FFFFFFF - MPU->RNR = 1; - // Set address to 0 - MPU->RBAR = 0; - // Configure and enable region - MPU->RASR = + // Select region 1 and use it for a WT ram region in the Code area + // - Code MBED_MPU_ROM_END + 1 to 0x1FFFFFFF + ARM_MPU_SetRegion( + ARM_MPU_RBAR( + 1, // Region + 0x00000000), // Base ARM_MPU_RASR( 1, // DisableExec ARM_MPU_AP_FULL, // AccessPermission @@ -123,17 +121,16 @@ void mbed_mpu_init() ((MBED_MPU_RAM_START <= 0x18000000) ? 0 : (1 << 5)) | ((MBED_MPU_RAM_START <= 0x1C000000) ? 0 : (1 << 6)) | ((MBED_MPU_RAM_START <= 0x20000000) ? 0 : (1 << 7)), - ARM_MPU_REGION_SIZE_512MB // Size - ); + ARM_MPU_REGION_SIZE_512MB) // Size + ); - // Select region 2 and used it for WBWA ram regions + // Select region 2 and use it for WBWA ram regions // - SRAM 0x20000000 to 0x3FFFFFFF // - RAM 0x60000000 to 0x7FFFFFFF - MPU->RNR = 2; - // Set address to 0 - MPU->RBAR = 0; - // Configure and enable region - MPU->RASR = + ARM_MPU_SetRegion( + ARM_MPU_RBAR( + 2, // Region + 0x00000000), // Base ARM_MPU_RASR( 1, // DisableExec ARM_MPU_AP_FULL, // AccessPermission @@ -150,16 +147,15 @@ void mbed_mpu_init() (1 << 5) | // Disable Sub-region (1 << 6) | // Disable Sub-region (1 << 7), // Disable Sub-region - ARM_MPU_REGION_SIZE_4GB // Size - ); + ARM_MPU_REGION_SIZE_4GB) // Size + ); - // Select region 3 and used it for the WT ram region - // - RAM RAM 0x80000000 to 0x9FFFFFFF - MPU->RNR = 3; - // Set address - MPU->RBAR = 0x80000000; - // Configure and enable region - MPU->RASR = + // Select region 3 and use it for the WT ram region + // - RAM 0x80000000 to 0x9FFFFFFF + ARM_MPU_SetRegion( + ARM_MPU_RBAR( + 3, // Region + 0x80000000), // Base ARM_MPU_RASR( 1, // DisableExec ARM_MPU_AP_FULL, // AccessPermission @@ -168,8 +164,8 @@ void mbed_mpu_init() 1, // IsCacheable 0, // IsBufferable ~0U, // SubRegionDisable - ARM_MPU_REGION_SIZE_512MB // Size - ); + ARM_MPU_REGION_SIZE_512MB) // Size + ); // Enable the MPU MPU->CTRL = diff --git a/hal/mpu/mbed_mpu_v8m.c b/hal/mpu/mbed_mpu_v8m.c index b1f98f43bf..4e8ce1100e 100644 --- a/hal/mpu/mbed_mpu_v8m.c +++ b/hal/mpu/mbed_mpu_v8m.c @@ -47,7 +47,7 @@ void mbed_mpu_init() // Reset all mapping for (uint32_t i = 0; i < regions; i++) { - ARM_MPU_ClrRegionEx(MPU, i); + ARM_MPU_ClrRegion(i); } /* @@ -64,61 +64,67 @@ void mbed_mpu_init() * 0xE0000000 - 0xFFFFFFFF System No */ - uint32_t region; - uint8_t outer; - uint8_t inner; + const uint8_t WTRA = ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0); // Non-transient, Write-Through, Read-allocate, Not Write-allocate + const uint8_t WBWARA = ARM_MPU_ATTR_MEMORY_(1, 1, 1, 1); // Non-transient, Write-Back, Read-allocate, Write-allocate + enum { + AttrIndex_WTRA, + AttrIndex_WBWARA, + }; - region = 0; - MPU->RNR = region; - outer = 0xA; // Write-Through, Non-transient, Read-allocate - inner = 0xA; // Write-Through, Non-transient, Read-allocate - ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0)); - MPU->RBAR = (0x00000000 & MPU_RBAR_BASE_Msk) | // Start address is 0x00000000 - (0 << MPU_RBAR_SH_Pos) | // Not shareable - (3 << MPU_RBAR_AP_Pos) | // RO allowed by all privilege levels - (0 << MPU_RBAR_XN_Pos); // Execute Never disabled - MPU->RLAR = (0x1FFFFFFF & MPU_RLAR_LIMIT_Msk) | // Last address is 0x1FFFFFFF - (region << MPU_RLAR_AttrIndx_Pos) | // Attribute index - configured to be the same as the region number - (1 << MPU_RLAR_EN_Pos); // Region enabled + ARM_MPU_SetMemAttr(AttrIndex_WTRA, ARM_MPU_ATTR(WTRA, WTRA)); + ARM_MPU_SetMemAttr(AttrIndex_WBWARA, ARM_MPU_ATTR(WBWARA, WBWARA)); - region = 1; - MPU->RNR = region; - outer = 0xF; // Write-Back, Non-transient, Read-allocate, Write-allocate - outer = 0xF; // Write-Back, Non-transient, Read-allocate, Write-allocate - ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0)); - MPU->RBAR = (0x20000000 & MPU_RBAR_BASE_Msk) | // Start address is 0x20000000 - (0 << MPU_RBAR_SH_Pos) | // Not shareable - (1 << MPU_RBAR_AP_Pos) | // RW allowed by all privilege levels - (1 << MPU_RBAR_XN_Pos); // Execute Never enabled - MPU->RLAR = (0x3FFFFFFF & MPU_RLAR_LIMIT_Msk) | // Last address is 0x3FFFFFFF - (region << MPU_RLAR_AttrIndx_Pos) | // Attribute index - configured to be the same as the region number - (1 << MPU_RLAR_EN_Pos); // Region enabled + ARM_MPU_SetRegion( + 0, // Region + ARM_MPU_RBAR( + 0x00000000, // Base + ARM_MPU_SH_NON, // Non-shareable + 1, // Read-Only + 1, // Non-Privileged + 0), // Execute Never disabled + ARM_MPU_RLAR( + 0x1FFFFFFF, // Limit + AttrIndex_WTRA) // Attribute index - Write-Through, Read-allocate + ); - region = 2; - MPU->RNR = region; - outer = 0xF; // Write-Back, Non-transient, Read-allocate, Write-allocate - outer = 0xF; // Write-Back, Non-transient, Read-allocate, Write-allocate - ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0)); - MPU->RBAR = (0x60000000 & MPU_RBAR_BASE_Msk) | // Start address is 0x60000000 - (0 << MPU_RBAR_SH_Pos) | // Not shareable - (1 << MPU_RBAR_AP_Pos) | // RW allowed by all privilege levels - (1 << MPU_RBAR_XN_Pos); // Execute Never enabled - MPU->RLAR = (0x7FFFFFFF & MPU_RLAR_LIMIT_Msk) | // Last address is 0x7FFFFFFF - (region << MPU_RLAR_AttrIndx_Pos) | // Attribute index - configured to be the same as the region number - (1 << MPU_RLAR_EN_Pos); // Region enabled + ARM_MPU_SetRegion( + 1, // Region + ARM_MPU_RBAR( + 0x20000000, // Base + ARM_MPU_SH_NON, // Non-shareable + 0, // Read-Write + 1, // Non-Privileged + 1), // Execute Never enabled + ARM_MPU_RLAR( + 0x3FFFFFFF, // Limit + AttrIndex_WBWARA) // Attribute index - Write-Back, Write-allocate + ); - region = 3; - MPU->RNR = region; - outer = 0xA; // Write-Through, Non-transient, Read-allocate - inner = 0xA; // Write-Through, Non-transient, Read-allocate - ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0)); - MPU->RBAR = (0x80000000 & MPU_RBAR_BASE_Msk) | // Start address is 0x80000000 - (0 << MPU_RBAR_SH_Pos) | // Not shareable - (1 << MPU_RBAR_AP_Pos) | // RW allowed by all privilege levels - (1 << MPU_RBAR_XN_Pos); // Execute Never enabled - MPU->RLAR = (0x9FFFFFFF & MPU_RLAR_LIMIT_Msk) | // Last address is 0x9FFFFFFF - (region << MPU_RLAR_AttrIndx_Pos) | // Attribute index - configured to be the same as the region number - (1 << MPU_RLAR_EN_Pos); // Region enabled + ARM_MPU_SetRegion( + 2, // Region + ARM_MPU_RBAR( + 0x60000000, // Base + ARM_MPU_SH_NON, // Non-shareable + 0, // Read-Write + 1, // Non-Privileged + 1), // Execute Never enabled + ARM_MPU_RLAR( + 0x7FFFFFFF, // Limit + AttrIndex_WBWARA) // Attribute index - Write-Back, Write-allocate + ); + + ARM_MPU_SetRegion( + 3, // Region + ARM_MPU_RBAR( + 0x80000000, // Base + ARM_MPU_SH_NON, // Non-shareable + 0, // Read-Write + 1, // Non-Privileged + 1), // Execute Never enabled + ARM_MPU_RLAR( + 0x9FFFFFFF, // Limit + AttrIndex_WTRA) // Attribute index - Write-Through, Read-allocate + ); // Enable the MPU MPU->CTRL = From 171e575b9482b96796cbf039c9ec154dc960cfdf Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 12 Dec 2018 10:36:35 +0200 Subject: [PATCH 5/9] Assert MPU regions, rather than error As we build for a specific CPU, a runtime check for number of MPU regions in release builds is not worthwhile. Make it an assert only. Saves a little space in develop images, a lot in release. --- hal/mpu/mbed_mpu_v7m.c | 8 ++++---- hal/mpu/mbed_mpu_v8m.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hal/mpu/mbed_mpu_v7m.c b/hal/mpu/mbed_mpu_v7m.c index 57c63f4c4d..5c48554a4a 100644 --- a/hal/mpu/mbed_mpu_v7m.c +++ b/hal/mpu/mbed_mpu_v7m.c @@ -15,7 +15,6 @@ */ #include "hal/mpu_api.h" #include "platform/mbed_assert.h" -#include "platform/mbed_error.h" #include "cmsis.h" #if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_6M__ == 1U)) && \ @@ -48,9 +47,10 @@ void mbed_mpu_init() __DMB(); const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; - if (regions < 4) { - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_EINVAL), "Device is not capable of supporting an MPU - remove DEVICE_MPU for device_has."); - } + + // Our MPU setup requires 4 regions - if this assert is hit, remove + // DEVICE_MPU from device_has + MBED_ASSERT(regions >= 4); // Disable the MCU MPU->CTRL = 0; diff --git a/hal/mpu/mbed_mpu_v8m.c b/hal/mpu/mbed_mpu_v8m.c index 4e8ce1100e..e9a4cdfa81 100644 --- a/hal/mpu/mbed_mpu_v8m.c +++ b/hal/mpu/mbed_mpu_v8m.c @@ -15,7 +15,6 @@ */ #include "hal/mpu_api.h" #include "platform/mbed_assert.h" -#include "platform/mbed_error.h" #include "cmsis.h" #if ((__ARM_ARCH_8M_BASE__ == 1U) || (__ARM_ARCH_8M_MAIN__ == 1U)) && \ @@ -38,9 +37,10 @@ void mbed_mpu_init() __DMB(); const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; - if (regions < 4) { - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_EINVAL), "Device is not capable of supporting an MPU - remove DEVICE_MPU for device_has."); - } + + // Our MPU setup requires 4 regions - if this assert is hit, remove + // DEVICE_MPU from device_has + MBED_ASSERT(regions >= 4); // Disable the MCU MPU->CTRL = 0; From 170b73442b6543f1dbf96949e1cea0e142d6f234 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 12 Dec 2018 15:01:19 +0200 Subject: [PATCH 6/9] ARMv7-M MPU: correctly protect 80000000 RAM region Subregion mask for this region was set fully disabled, instead of fully enabled. --- hal/mpu/mbed_mpu_v7m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hal/mpu/mbed_mpu_v7m.c b/hal/mpu/mbed_mpu_v7m.c index 5c48554a4a..63bdc32b1c 100644 --- a/hal/mpu/mbed_mpu_v7m.c +++ b/hal/mpu/mbed_mpu_v7m.c @@ -163,7 +163,7 @@ void mbed_mpu_init() 0, // IsShareable 1, // IsCacheable 0, // IsBufferable - ~0U, // SubRegionDisable + 0U, // SubRegionDisable ARM_MPU_REGION_SIZE_512MB) // Size ); From 02330336f20815da46452a22989b494ac556add0 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 12 Dec 2018 15:03:40 +0200 Subject: [PATCH 7/9] Fix target.mpu-rom-end setting, for ARMv8-M too targets.json was not specifying the same macro name as the code was checking for, so setting was ineffective. Making this work tripped up not-supported checks in ARMv8-M - rather than deal with making this work, support it instead. Both ARMv7-M and ARMv8-M slightly reduce code size and runtime impact if mpu-rom-end is 0x1fffffff, using one fewer region. This means default setup for ARMv8-M now requires 5 regions, with mpu-rom-end set to default 0x0fffffff, but this can be put back to 4 by changing the setting. --- hal/mpu/mbed_mpu_v7m.c | 31 +++++++++++++++++++++---------- hal/mpu/mbed_mpu_v8m.c | 40 +++++++++++++++++++++++++++++++++------- targets/targets.json | 3 +-- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/hal/mpu/mbed_mpu_v7m.c b/hal/mpu/mbed_mpu_v7m.c index 63bdc32b1c..7b7a7c7259 100644 --- a/hal/mpu/mbed_mpu_v7m.c +++ b/hal/mpu/mbed_mpu_v7m.c @@ -25,7 +25,9 @@ #error "Device has v7m MPU but it is not enabled. Add 'MPU' to device_has in targets.json" #endif -#if !defined(MBED_MPU_ROM_END) +#ifdef MBED_CONF_TARGET_MPU_ROM_END +#define MBED_MPU_ROM_END MBED_CONF_TARGET_MPU_ROM_END +#else #define MBED_MPU_ROM_END (0x10000000 - 1) #endif #define MBED_MPU_RAM_START (MBED_MPU_ROM_END + 1) @@ -48,9 +50,13 @@ void mbed_mpu_init() const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; - // Our MPU setup requires 4 regions - if this assert is hit, remove - // DEVICE_MPU from device_has + // Our MPU setup requires 3 or 4 regions - if this assert is hit, remove + // a region by setting MPU_ROM_END to 0x1fffffff, or remove MPU from device_has +#if MBED_MPU_RAM_START == 0x20000000 + MBED_ASSERT(regions >= 3); +#else MBED_ASSERT(regions >= 4); +#endif // Disable the MCU MPU->CTRL = 0; @@ -99,11 +105,12 @@ void mbed_mpu_init() ARM_MPU_REGION_SIZE_512MB) // Size ); - // Select region 1 and use it for a WT ram region in the Code area +#if MBED_MPU_RAM_START < 0x20000000 + // Select region 3 and use it for a WT ram region in the Code area // - Code MBED_MPU_ROM_END + 1 to 0x1FFFFFFF ARM_MPU_SetRegion( ARM_MPU_RBAR( - 1, // Region + 3, // Region 0x00000000), // Base ARM_MPU_RASR( 1, // DisableExec @@ -123,13 +130,17 @@ void mbed_mpu_init() ((MBED_MPU_RAM_START <= 0x20000000) ? 0 : (1 << 7)), ARM_MPU_REGION_SIZE_512MB) // Size ); +#define LAST_RAM_REGION 3 +#else +#define LAST_RAM_REGION 2 +#endif - // Select region 2 and use it for WBWA ram regions + // Select region 1 and use it for WBWA ram regions // - SRAM 0x20000000 to 0x3FFFFFFF // - RAM 0x60000000 to 0x7FFFFFFF ARM_MPU_SetRegion( ARM_MPU_RBAR( - 2, // Region + 1, // Region 0x00000000), // Base ARM_MPU_RASR( 1, // DisableExec @@ -150,11 +161,11 @@ void mbed_mpu_init() ARM_MPU_REGION_SIZE_4GB) // Size ); - // Select region 3 and use it for the WT ram region + // Select region 2 and use it for the WT ram region // - RAM 0x80000000 to 0x9FFFFFFF ARM_MPU_SetRegion( ARM_MPU_RBAR( - 3, // Region + 2, // Region 0x80000000), // Base ARM_MPU_RASR( 1, // DisableExec @@ -214,7 +225,7 @@ void mbed_mpu_enable_ram_xn(bool enable) // Flush memory writes before configuring the MPU. __DMB(); - for (uint32_t region = 1; region <= 3; region++) { + for (uint32_t region = 1; region <= LAST_RAM_REGION; region++) { enable_region(enable, region); } diff --git a/hal/mpu/mbed_mpu_v8m.c b/hal/mpu/mbed_mpu_v8m.c index e9a4cdfa81..4b992f543d 100644 --- a/hal/mpu/mbed_mpu_v8m.c +++ b/hal/mpu/mbed_mpu_v8m.c @@ -25,11 +25,15 @@ #error "Device has v8m MPU but it is not enabled. Add 'MPU' to device_has in targets.json" #endif -#if !defined(MBED_MPU_ROM_END) -#define MBED_MPU_ROM_END (0x20000000 - 1) +#ifdef MBED_CONF_TARGET_MPU_ROM_END +#define MBED_MPU_ROM_END MBED_CONF_TARGET_MPU_ROM_END +#else +#define MBED_MPU_ROM_END (0x10000000 - 1) #endif +#define MBED_MPU_RAM_START (MBED_MPU_ROM_END + 1) -MBED_STATIC_ASSERT(MBED_MPU_ROM_END == 0x1fffffff, "Changing MBED_MPU_ROM_END for ARMv8-M is not supported."); +MBED_STATIC_ASSERT(MBED_MPU_ROM_END <= 0x20000000 - 1, + "Unsupported value for MBED_MPU_ROM_END"); void mbed_mpu_init() { @@ -38,9 +42,13 @@ void mbed_mpu_init() const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; - // Our MPU setup requires 4 regions - if this assert is hit, remove - // DEVICE_MPU from device_has + // Our MPU setup requires 4 or 5 regions - if this assert is hit, remove + // a region by setting MPU_ROM_END to 0x1fffffff, or remove MPU from device_has +#if MBED_MPU_RAM_START == 0x20000000 MBED_ASSERT(regions >= 4); +#else + MBED_ASSERT(regions >= 5); +#endif // Disable the MCU MPU->CTRL = 0; @@ -54,7 +62,7 @@ void mbed_mpu_init() * ARMv8-M memory map: * * Start End Name Executable by default Default cache Mbed MPU protection - * 0x00000000 - 0x1FFFFFFF Code Yes WT, WA Write disabled + * 0x00000000 - 0x1FFFFFFF Code Yes WT, WA Write disabled for first portion and execute disabled for the rest * 0x20000000 - 0x3FFFFFFF SRAM Yes WB, WA, RA Execute disabled * 0x40000000 - 0x5FFFFFFF Peripheral No * 0x60000000 - 0x7FFFFFFF RAM Yes WB, WA, RA Execute disabled @@ -82,10 +90,28 @@ void mbed_mpu_init() 1, // Read-Only 1, // Non-Privileged 0), // Execute Never disabled + ARM_MPU_RLAR( + MBED_MPU_ROM_END, // Limit + AttrIndex_WTRA) // Attribute index - Write-Through, Read-allocate + ); + +#if MBED_MPU_RAM_START != 0x20000000 + ARM_MPU_SetRegion( + 4, // Region + ARM_MPU_RBAR( + MBED_MPU_RAM_START, // Base + ARM_MPU_SH_NON, // Non-shareable + 0, // Read-Write + 1, // Non-Privileged + 1), // Execute Never enabled ARM_MPU_RLAR( 0x1FFFFFFF, // Limit AttrIndex_WTRA) // Attribute index - Write-Through, Read-allocate ); +#define LAST_RAM_REGION 4 +#else +#define LAST_RAM_REGION 3 +#endif ARM_MPU_SetRegion( 1, // Region @@ -173,7 +199,7 @@ void mbed_mpu_enable_ram_xn(bool enable) // Flush memory writes before configuring the MPU. __DMB(); - for (uint32_t region = 1; region <= 3; region++) { + for (uint32_t region = 1; region <= LAST_RAM_REGION; region++) { enable_region(enable, region); } diff --git a/targets/targets.json b/targets/targets.json index 703e165c42..e6475be710 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -32,8 +32,7 @@ }, "mpu-rom-end": { "help": "Last address of ROM protected by the MPU", - "value": "0x0fffffff", - "macro_name": "MPU_ROM_END" + "value": "0x0fffffff" } } }, From 574f9fad212a79c1095e8ed7ada33d5a0347b288 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 12 Dec 2018 15:11:14 +0200 Subject: [PATCH 8/9] nRF52840: Set mpu-rom-end to 0x1fffffff So we have at least one test platform exercising the special case of mpu-rom-end being 0x1fffffff, set that for nRF52840. --- targets/targets.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/targets/targets.json b/targets/targets.json index e6475be710..a590d1ed3a 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -6678,6 +6678,9 @@ "value": 0 } }, + "overrides": { + "mpu-rom-end": "0x1fffffff" + }, "OUTPUT_EXT": "hex", "is_disk_virtual": true, "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], From adf253e1fda5cfeb431660c3102770742055d9d5 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Tue, 18 Dec 2018 17:35:10 -0600 Subject: [PATCH 9/9] Update MPU ram/rom split for Nuvoton M2351 Move the start of RAM from 0x10000000 to 0x20000000 on the NUMAKER_PFM_M2351. This allows the target to work correctly. --- targets/targets.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/targets/targets.json b/targets/targets.json index a590d1ed3a..0ef0db15bd 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -7474,6 +7474,9 @@ "value": "GPIO_DBCTL_DBCLKSEL_16" } }, + "overrides": { + "mpu-rom-end": "0x1fffffff" + }, "inherits": ["Target"], "device_has": [ "USTICKER",