mirror of https://github.com/ARMmbed/mbed-os.git
Overhaul MPU for new requirements
Make the following changes: -Allow a vector specific ARM MPU driver by defining MBED_MPU_CUSTOM -Allow ROM address to be configured for ARMv7-M devices by setting the define MBED_MPU_ROM_END -Add ROM write protection -Add new functions and lock -enable at boot -disable during flash programmingpull/8871/head
parent
d27566c955
commit
1821d37621
|
@ -252,7 +252,8 @@ Case cases[] = {
|
|||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
||||
{
|
||||
mbed_mpu_manager_lock_mem_xn();
|
||||
mbed_mpu_manager_lock_ram_xn();
|
||||
mbed_mpu_manager_lock_rom_wn();
|
||||
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
|
@ -260,7 +261,8 @@ utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
|||
|
||||
void greentea_test_teardown(const size_t passed, const size_t failed, const failure_t failure)
|
||||
{
|
||||
mbed_mpu_manager_unlock_mem_xn();
|
||||
mbed_mpu_manager_unlock_ram_xn();
|
||||
mbed_mpu_manager_unlock_rom_wn();
|
||||
|
||||
greentea_test_teardown_handler(passed, failed, failure);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "FlashIAP.h"
|
||||
#include "platform/mbed_assert.h"
|
||||
#include "platform/ScopedMpuXnLock.h"
|
||||
#include "platform/ScopedMpuWnLock.h"
|
||||
|
||||
|
||||
#ifdef DEVICE_FLASH
|
||||
|
@ -59,6 +60,7 @@ int FlashIAP::init()
|
|||
_mutex->lock();
|
||||
{
|
||||
ScopedMpuXnLock xn;
|
||||
ScopedMpuWnLock wn;
|
||||
if (flash_init(&_flash)) {
|
||||
ret = -1;
|
||||
}
|
||||
|
@ -76,6 +78,7 @@ int FlashIAP::deinit()
|
|||
_mutex->lock();
|
||||
{
|
||||
ScopedMpuXnLock xn;
|
||||
ScopedMpuWnLock wn;
|
||||
if (flash_free(&_flash)) {
|
||||
ret = -1;
|
||||
}
|
||||
|
@ -92,6 +95,7 @@ int FlashIAP::read(void *buffer, uint32_t addr, uint32_t size)
|
|||
_mutex->lock();
|
||||
{
|
||||
ScopedMpuXnLock xn;
|
||||
ScopedMpuWnLock wn;
|
||||
ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
|
||||
}
|
||||
_mutex->unlock();
|
||||
|
@ -138,6 +142,7 @@ int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
|
|||
}
|
||||
{
|
||||
ScopedMpuXnLock xn;
|
||||
ScopedMpuWnLock wn;
|
||||
if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
|
||||
ret = -1;
|
||||
break;
|
||||
|
@ -185,6 +190,7 @@ int FlashIAP::erase(uint32_t addr, uint32_t size)
|
|||
while (size) {
|
||||
{
|
||||
ScopedMpuXnLock xn;
|
||||
ScopedMpuWnLock wn;
|
||||
ret = flash_erase_sector(&_flash, addr);
|
||||
}
|
||||
if (ret != 0) {
|
||||
|
|
|
@ -14,31 +14,43 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#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)) && \
|
||||
defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
|
||||
defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
|
||||
!defined(MBED_MPU_CUSTOM)
|
||||
|
||||
#if !DEVICE_MPU
|
||||
#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)
|
||||
#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 == 0x04000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x08000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x0C000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x10000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x14000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x18000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x1C000000 - 1 ||
|
||||
MBED_MPU_ROM_END == 0x20000000 - 1,
|
||||
"Unsupported value for MBED_MPU_ROM_END");
|
||||
|
||||
void mbed_mpu_init()
|
||||
{
|
||||
mbed_mpu_enable_ram_xn(false);
|
||||
}
|
||||
|
||||
void mbed_mpu_free()
|
||||
{
|
||||
mbed_mpu_enable_ram_xn(false);
|
||||
}
|
||||
|
||||
void mbed_mpu_enable_ram_xn(bool enable)
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
// Disable the MCU
|
||||
MPU->CTRL = 0;
|
||||
|
@ -48,15 +60,11 @@ void mbed_mpu_enable_ram_xn(bool enable)
|
|||
ARM_MPU_ClrRegion(i);
|
||||
}
|
||||
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ARMv6m and ARMv7m memory map:
|
||||
* ARMv6m and ARMv7-M memory map:
|
||||
*
|
||||
* Start End Name Executable by default Mbed MPU protection
|
||||
* 0x00000000 - 0x1FFFFFFF Code Yes Execute disabled for second half
|
||||
* 0x00000000 - 0x1FFFFFFF Code Yes Write disabled for first portion and execute disabled for the rest
|
||||
* 0x20000000 - 0x3FFFFFFF SRAM Yes Execute disabled
|
||||
* 0x40000000 - 0x5FFFFFFF Peripheral No
|
||||
* 0x60000000 - 0x7FFFFFFF RAM Yes Execute disabled
|
||||
|
@ -66,81 +74,102 @@ void mbed_mpu_enable_ram_xn(bool enable)
|
|||
* 0xE0000000 - 0xFFFFFFFF System No
|
||||
*/
|
||||
|
||||
if (regions >= 3) {
|
||||
// Select region 0 and used it for the WT rom region
|
||||
// - RAM 0x10000000 - 0x1FFFFFFF
|
||||
MPU->RNR = 0;
|
||||
// Set address to 0
|
||||
MPU->RBAR = 0;
|
||||
// Configure and enable region
|
||||
MPU->RASR =
|
||||
MPU_RASR_ENABLE_Msk |
|
||||
ARM_MPU_RASR(
|
||||
1, // DisableExec
|
||||
ARM_MPU_AP_FULL, // AccessPermission
|
||||
0, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
0, // IsBufferable
|
||||
// SubRegionDisable
|
||||
(1 << 0) | // Disable Sub-region
|
||||
(1 << 1) | // Disable Sub-region
|
||||
(1 << 2) | // Disable Sub-region
|
||||
(1 << 3) | // Disable Sub-region
|
||||
(0 << 4) | // Enable Sub-region RAM 0x10000000 - 0x1FFFFFFF
|
||||
(0 << 5) |
|
||||
(0 << 6) |
|
||||
(0 << 7),
|
||||
ARM_MPU_REGION_SIZE_512MB // Size
|
||||
);
|
||||
// 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 =
|
||||
ARM_MPU_RASR(
|
||||
0, // DisableExec
|
||||
ARM_MPU_AP_RO, // AccessPermission
|
||||
0, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
0, // IsBufferable
|
||||
// SubRegionDisable - based on where ROM ends
|
||||
((MBED_MPU_ROM_END >= 0x00000000) ? 0 : (1 << 0)) | // 0 to enable, 1 << n to disable
|
||||
((MBED_MPU_ROM_END >= 0x04000000) ? 0 : (1 << 1)) |
|
||||
((MBED_MPU_ROM_END >= 0x08000000) ? 0 : (1 << 2)) |
|
||||
((MBED_MPU_ROM_END >= 0x0C000000) ? 0 : (1 << 3)) |
|
||||
((MBED_MPU_ROM_END >= 0x10000000) ? 0 : (1 << 4)) |
|
||||
((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
|
||||
);
|
||||
|
||||
// Select region 1 and used it for WBWA ram regions
|
||||
// - SRAM 0x20000000 - 0x3FFFFFFF
|
||||
// - RAM 0x60000000 - 0x7FFFFFFF
|
||||
MPU->RNR = 1;
|
||||
// Set address to 0
|
||||
MPU->RBAR = 0;
|
||||
// Configure and enable region
|
||||
MPU->RASR =
|
||||
MPU_RASR_ENABLE_Msk |
|
||||
ARM_MPU_RASR(
|
||||
1, // DisableExec
|
||||
ARM_MPU_AP_FULL, // AccessPermission
|
||||
1, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
1, // IsBufferable
|
||||
// SubRegionDisable
|
||||
(1 << 0) | // Disable Sub-region
|
||||
(0 << 1) | // Enable Sub-region SRAM 0x20000000 - 0x3FFFFFFF
|
||||
(1 << 2) | // Disable Sub-region
|
||||
(0 << 3) | // Enable Sub-region RAM 0x60000000 - 0x7FFFFFFF
|
||||
(1 << 4) | // Disable Sub-region
|
||||
(1 << 5) | // Disable Sub-region
|
||||
(1 << 6) | // Disable Sub-region
|
||||
(1 << 7), // Disable Sub-region
|
||||
ARM_MPU_REGION_SIZE_4GB // 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 =
|
||||
ARM_MPU_RASR(
|
||||
1, // DisableExec
|
||||
ARM_MPU_AP_FULL, // AccessPermission
|
||||
0, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
0, // IsBufferable
|
||||
// SubRegionDisable - based on where RAM starts
|
||||
((MBED_MPU_RAM_START <= 0x04000000) ? 0 : (1 << 0)) | // 0 to enable, 1 << n to disable
|
||||
((MBED_MPU_RAM_START <= 0x08000000) ? 0 : (1 << 1)) |
|
||||
((MBED_MPU_RAM_START <= 0x0C000000) ? 0 : (1 << 2)) |
|
||||
((MBED_MPU_RAM_START <= 0x10000000) ? 0 : (1 << 3)) |
|
||||
((MBED_MPU_RAM_START <= 0x14000000) ? 0 : (1 << 4)) |
|
||||
((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
|
||||
);
|
||||
|
||||
// Select region 2 and used it for the WT ram region
|
||||
// - RAM RAM 0x80000000 - 0x9FFFFFFF
|
||||
MPU->RNR = 2;
|
||||
// Set address
|
||||
MPU->RBAR = 0x80000000;
|
||||
// Configure and enable region
|
||||
MPU->RASR =
|
||||
MPU_RASR_ENABLE_Msk |
|
||||
ARM_MPU_RASR(
|
||||
1, // DisableExec
|
||||
ARM_MPU_AP_FULL, // AccessPermission
|
||||
0, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
0, // IsBufferable
|
||||
~0U, // SubRegionDisable
|
||||
ARM_MPU_REGION_SIZE_512MB // Size
|
||||
);
|
||||
}
|
||||
// Select region 2 and used 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_RASR(
|
||||
1, // DisableExec
|
||||
ARM_MPU_AP_FULL, // AccessPermission
|
||||
1, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
1, // IsBufferable
|
||||
// SubRegionDisable
|
||||
(1 << 0) | // Disable Sub-region
|
||||
(0 << 1) | // Enable Sub-region SRAM 0x20000000 - 0x3FFFFFFF
|
||||
(1 << 2) | // Disable Sub-region
|
||||
(0 << 3) | // Enable Sub-region RAM 0x60000000 - 0x7FFFFFFF
|
||||
(1 << 4) | // Disable Sub-region
|
||||
(1 << 5) | // Disable Sub-region
|
||||
(1 << 6) | // Disable Sub-region
|
||||
(1 << 7), // Disable Sub-region
|
||||
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 =
|
||||
ARM_MPU_RASR(
|
||||
1, // DisableExec
|
||||
ARM_MPU_AP_FULL, // AccessPermission
|
||||
0, // TypeExtField
|
||||
0, // IsShareable
|
||||
1, // IsCacheable
|
||||
0, // IsBufferable
|
||||
~0U, // SubRegionDisable
|
||||
ARM_MPU_REGION_SIZE_512MB // Size
|
||||
);
|
||||
|
||||
// Enable the MPU
|
||||
MPU->CTRL =
|
||||
|
@ -153,4 +182,49 @@ void mbed_mpu_enable_ram_xn(bool enable)
|
|||
__DSB();
|
||||
}
|
||||
|
||||
void mbed_mpu_free()
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
// Disable the MPU
|
||||
MPU->CTRL = 0;
|
||||
|
||||
// Ensure changes take effect
|
||||
__ISB();
|
||||
__DSB();
|
||||
}
|
||||
|
||||
void mbed_mpu_enable_rom_wn(bool enable)
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
MPU->RNR = 0;
|
||||
MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0);
|
||||
|
||||
// Ensure changes take effect
|
||||
__ISB();
|
||||
__DSB();
|
||||
}
|
||||
|
||||
void mbed_mpu_enable_ram_xn(bool enable)
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
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);
|
||||
|
||||
// Ensure changes take effect
|
||||
__ISB();
|
||||
__DSB();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,31 +14,33 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#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)) && \
|
||||
defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
|
||||
defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
|
||||
!defined(MBED_MPU_CUSTOM)
|
||||
|
||||
#if !DEVICE_MPU
|
||||
#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)
|
||||
#endif
|
||||
|
||||
MBED_STATIC_ASSERT(MBED_MPU_ROM_END == 0x1fffffff, "Changing MBED_MPU_ROM_END for ARMv8-M is not supported.");
|
||||
|
||||
void mbed_mpu_init()
|
||||
{
|
||||
mbed_mpu_enable_ram_xn(false);
|
||||
}
|
||||
|
||||
void mbed_mpu_free()
|
||||
{
|
||||
mbed_mpu_enable_ram_xn(false);
|
||||
}
|
||||
|
||||
void mbed_mpu_enable_ram_xn(bool enable)
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
// Disable the MCU
|
||||
MPU->CTRL = 0;
|
||||
|
@ -48,15 +50,11 @@ void mbed_mpu_enable_ram_xn(bool enable)
|
|||
ARM_MPU_ClrRegionEx(MPU, i);
|
||||
}
|
||||
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ARMv8m memory map:
|
||||
* ARMv8-M memory map:
|
||||
*
|
||||
* Start End Name Executable by default Default cache Mbed MPU protection
|
||||
* 0x00000000 - 0x1FFFFFFF Code Yes WT, WA
|
||||
* 0x00000000 - 0x1FFFFFFF Code Yes WT, WA Write disabled
|
||||
* 0x20000000 - 0x3FFFFFFF SRAM Yes WB, WA, RA Execute disabled
|
||||
* 0x40000000 - 0x5FFFFFFF Peripheral No
|
||||
* 0x60000000 - 0x7FFFFFFF RAM Yes WB, WA, RA Execute disabled
|
||||
|
@ -66,50 +64,57 @@ void mbed_mpu_enable_ram_xn(bool enable)
|
|||
* 0xE0000000 - 0xFFFFFFFF System No
|
||||
*/
|
||||
|
||||
if (regions >= 3) {
|
||||
uint32_t region;
|
||||
uint8_t outer;
|
||||
uint8_t inner;
|
||||
uint32_t region;
|
||||
uint8_t outer;
|
||||
uint8_t inner;
|
||||
|
||||
region = 0;
|
||||
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); // Enable region
|
||||
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
|
||||
|
||||
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 = (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); // Enable region
|
||||
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
|
||||
|
||||
region = 2;
|
||||
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); // Enable region
|
||||
}
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
// Enable the MPU
|
||||
MPU->CTRL =
|
||||
|
@ -122,4 +127,49 @@ void mbed_mpu_enable_ram_xn(bool enable)
|
|||
__DSB();
|
||||
}
|
||||
|
||||
void mbed_mpu_free()
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
// Disable the MCU
|
||||
MPU->CTRL = 0;
|
||||
|
||||
// Ensure changes take effect
|
||||
__ISB();
|
||||
__DSB();
|
||||
}
|
||||
|
||||
void mbed_mpu_enable_rom_wn(bool enable)
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
MPU->RNR = 0;
|
||||
MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0);
|
||||
|
||||
// Ensure changes take effect
|
||||
__ISB();
|
||||
__DSB();
|
||||
}
|
||||
|
||||
void mbed_mpu_enable_ram_xn(bool enable)
|
||||
{
|
||||
// Flush memory writes before configuring the MPU.
|
||||
__DSB();
|
||||
|
||||
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);
|
||||
|
||||
// Ensure changes take effect
|
||||
__ISB();
|
||||
__DSB();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,7 @@ extern "C" {
|
|||
* * Execution from RAM results in a fault when execute never is enabled.
|
||||
* This RAM includes heap, stack, data and zero init - Verified by ::mpu_fault_test_data,
|
||||
* ::mpu_fault_test_bss, ::mpu_fault_test_stack and ::mpu_fault_test_heap.
|
||||
* * Writing to ROM results in a fault when write never is enabled - Not verified
|
||||
*
|
||||
* # Undefined behavior
|
||||
* * Calling any function other than ::mbed_mpu_init before the initialization of the MPU.
|
||||
|
@ -68,6 +69,16 @@ extern "C" {
|
|||
*/
|
||||
void mbed_mpu_init(void);
|
||||
|
||||
/**
|
||||
* Enable or disable ROM MPU protection
|
||||
*
|
||||
* This function is used to mark all of ROM as read and execute only.
|
||||
* When enabled writes to ROM cause a fault.
|
||||
*
|
||||
* @param enable true to disable execution in ram, false otherwise
|
||||
*/
|
||||
void mbed_mpu_enable_rom_wn(bool enable);
|
||||
|
||||
/**
|
||||
* Enable or disable ram MPU protection
|
||||
*
|
||||
|
@ -90,6 +101,8 @@ void mbed_mpu_free(void);
|
|||
|
||||
#define mbed_mpu_init()
|
||||
|
||||
#define mbed_mpu_enable_rom_wn(enable) (void)enable
|
||||
|
||||
#define mbed_mpu_enable_ram_xn(enable) (void)enable
|
||||
|
||||
#define mbed_mpu_free()
|
||||
|
|
1
mbed.h
1
mbed.h
|
@ -95,6 +95,7 @@
|
|||
#include "platform/DirHandle.h"
|
||||
#include "platform/CriticalSectionLock.h"
|
||||
#include "platform/DeepSleepLock.h"
|
||||
#include "platform/ScopedMpuWnLock.h"
|
||||
#include "platform/ScopedMpuXnLock.h"
|
||||
#include "platform/mbed_stats.h"
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_SCOPEDMPUWNLOCK_H
|
||||
#define MBED_SCOPEDMPUWNLOCK_H
|
||||
|
||||
#include "platform/mbed_mpu_mgmt.h"
|
||||
#include "platform/NonCopyable.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/** \addtogroup platform */
|
||||
/** @{*/
|
||||
|
||||
/** RAII object for disabling, then restoring ROM write never mode
|
||||
* Usage:
|
||||
* @code
|
||||
*
|
||||
* void f() {
|
||||
* // some code here
|
||||
* {
|
||||
* ScopedMpuXnLock xn;
|
||||
* // Code in this block is allowed to call functions in RAM
|
||||
* }
|
||||
* // Execution from RAM is no longer allowed
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
class ScopedMpuWnLock : private mbed::NonCopyable<ScopedMpuWnLock> {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Allow execution from RAM
|
||||
*
|
||||
* Increment the execute never lock to ensure code can
|
||||
* be executed from RAM. This class uses RAII to allow
|
||||
* execution from ram while it is in scope.
|
||||
*/
|
||||
ScopedMpuWnLock()
|
||||
{
|
||||
mbed_mpu_manager_lock_rom_wn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore previous execution from RAM settings
|
||||
*
|
||||
* Decrement the execute never lock to return execute from RAM
|
||||
* to its prior state.
|
||||
*/
|
||||
~ScopedMpuWnLock()
|
||||
{
|
||||
mbed_mpu_manager_unlock_rom_wn();
|
||||
}
|
||||
};
|
||||
|
||||
/**@}*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -50,7 +50,7 @@ public:
|
|||
*/
|
||||
ScopedMpuXnLock()
|
||||
{
|
||||
mbed_mpu_manager_lock_mem_xn();
|
||||
mbed_mpu_manager_lock_ram_xn();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@ public:
|
|||
*/
|
||||
~ScopedMpuXnLock()
|
||||
{
|
||||
mbed_mpu_manager_unlock_mem_xn();
|
||||
mbed_mpu_manager_unlock_ram_xn();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -21,13 +21,14 @@
|
|||
#include <limits.h>
|
||||
|
||||
static uint16_t mem_xn_lock;
|
||||
static uint16_t mem_wn_lock;
|
||||
|
||||
void mbed_mpu_manager_lock_mem_xn()
|
||||
void mbed_mpu_manager_lock_ram_xn()
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (mem_xn_lock == USHRT_MAX) {
|
||||
core_util_critical_section_exit();
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "Memory execute never lock overflow (> USHRT_MAX)", mem_xn_lock);
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "Ram execute never lock overflow (> USHRT_MAX)", mem_xn_lock);
|
||||
}
|
||||
if (mem_xn_lock == 0) {
|
||||
mbed_mpu_enable_ram_xn(false);
|
||||
|
@ -36,12 +37,12 @@ void mbed_mpu_manager_lock_mem_xn()
|
|||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void mbed_mpu_manager_unlock_mem_xn()
|
||||
void mbed_mpu_manager_unlock_ram_xn()
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (mem_xn_lock == 0) {
|
||||
core_util_critical_section_exit();
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "Memory execute never lock underflow (< 0)", mem_xn_lock);
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "Ram execute never lock underflow (< 0)", mem_xn_lock);
|
||||
}
|
||||
mem_xn_lock--;
|
||||
if (mem_xn_lock == 0) {
|
||||
|
@ -49,3 +50,31 @@ void mbed_mpu_manager_unlock_mem_xn()
|
|||
}
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void mbed_mpu_manager_lock_rom_wn()
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (mem_wn_lock == USHRT_MAX) {
|
||||
core_util_critical_section_exit();
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "Rom write never lock overflow (> USHRT_MAX)", mem_wn_lock);
|
||||
}
|
||||
if (mem_wn_lock == 0) {
|
||||
mbed_mpu_enable_rom_wn(false);
|
||||
}
|
||||
mem_wn_lock++;
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void mbed_mpu_manager_unlock_rom_wn()
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (mem_wn_lock == 0) {
|
||||
core_util_critical_section_exit();
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "Rom write never lock underflow (< 0)", mem_wn_lock);
|
||||
}
|
||||
mem_wn_lock--;
|
||||
if (mem_wn_lock == 0) {
|
||||
mbed_mpu_enable_rom_wn(true);
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
|
|
@ -45,16 +45,40 @@ extern "C" {
|
|||
* The lock is a counter, can be locked up to USHRT_MAX
|
||||
* This function is IRQ and thread safe
|
||||
*/
|
||||
void mbed_mpu_manager_lock_mem_xn(void);
|
||||
void mbed_mpu_manager_lock_ram_xn(void);
|
||||
|
||||
/** Unlock ram execute never mode
|
||||
*
|
||||
* Use unlocking in pair with mbed_mpu_manager_lock_mem_xn().
|
||||
* Use unlocking in pair with mbed_mpu_manager_lock_ram_xn().
|
||||
*
|
||||
* The lock is a counter, should be equally unlocked as locked
|
||||
* This function is IRQ and thread safe
|
||||
*/
|
||||
void mbed_mpu_manager_unlock_mem_xn(void);
|
||||
void mbed_mpu_manager_unlock_ram_xn(void);
|
||||
|
||||
/** Lock rom write never mode off
|
||||
*
|
||||
* This disables the MPU's write never ROM protection and allows
|
||||
* ROM to be written to. Writing to ROM will not result in an MPU
|
||||
* fault if this function is invoked at least once(the internal
|
||||
* counter is non-zero).
|
||||
*
|
||||
* Use this locking mechanism for code which needs to write to
|
||||
* ROM such as flash programming algorithms.
|
||||
*
|
||||
* The lock is a counter, can be locked up to USHRT_MAX
|
||||
* This function is IRQ and thread safe
|
||||
*/
|
||||
void mbed_mpu_manager_lock_rom_wn(void);
|
||||
|
||||
/** Unlock rom write never mode
|
||||
*
|
||||
* Use unlocking in pair with mbed_mpu_manager_lock_rom_wn().
|
||||
*
|
||||
* The lock is a counter, should be equally unlocked as locked
|
||||
* This function is IRQ and thread safe
|
||||
*/
|
||||
void mbed_mpu_manager_unlock_rom_wn(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ void mbed_init(void)
|
|||
{
|
||||
mbed_mpu_init();
|
||||
mbed_mpu_enable_ram_xn(true);
|
||||
mbed_mpu_enable_rom_wn(true);
|
||||
mbed_cpy_nvic();
|
||||
mbed_sdk_init();
|
||||
mbed_rtos_init();
|
||||
|
|
Loading…
Reference in New Issue