2018-11-01 21:46:39 +00:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
#include "hal/mpu_api.h"
|
2018-11-06 15:42:44 +00:00
|
|
|
#include "platform/mbed_assert.h"
|
|
|
|
#include "platform/mbed_error.h"
|
2018-11-01 21:46:39 +00:00
|
|
|
#include "cmsis.h"
|
|
|
|
|
|
|
|
#if ((__ARM_ARCH_8M_BASE__ == 1U) || (__ARM_ARCH_8M_MAIN__ == 1U)) && \
|
2018-11-06 15:42:44 +00:00
|
|
|
defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
|
|
|
|
!defined(MBED_MPU_CUSTOM)
|
2018-11-01 21:46:39 +00:00
|
|
|
|
|
|
|
#if !DEVICE_MPU
|
|
|
|
#error "Device has v8m MPU but it is not enabled. Add 'MPU' to device_has in targets.json"
|
|
|
|
#endif
|
|
|
|
|
2018-11-06 15:42:44 +00:00
|
|
|
#if !defined(MBED_MPU_ROM_END)
|
|
|
|
#define MBED_MPU_ROM_END (0x20000000 - 1)
|
|
|
|
#endif
|
2018-11-01 21:46:39 +00:00
|
|
|
|
2018-11-06 15:42:44 +00:00
|
|
|
MBED_STATIC_ASSERT(MBED_MPU_ROM_END == 0x1fffffff, "Changing MBED_MPU_ROM_END for ARMv8-M is not supported.");
|
2018-11-01 21:46:39 +00:00
|
|
|
|
2018-11-06 15:42:44 +00:00
|
|
|
void mbed_mpu_init()
|
2018-11-01 21:46:39 +00:00
|
|
|
{
|
|
|
|
// Flush memory writes before configuring the MPU.
|
2018-12-11 14:01:34 +00:00
|
|
|
__DMB();
|
2018-11-01 21:46:39 +00:00
|
|
|
|
|
|
|
const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
|
2018-11-06 15:42:44 +00:00
|
|
|
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.");
|
|
|
|
}
|
2018-11-01 21:46:39 +00:00
|
|
|
|
|
|
|
// Disable the MCU
|
|
|
|
MPU->CTRL = 0;
|
|
|
|
|
|
|
|
// Reset all mapping
|
|
|
|
for (uint32_t i = 0; i < regions; i++) {
|
2018-12-11 16:21:28 +00:00
|
|
|
ARM_MPU_ClrRegion(i);
|
2018-11-01 21:46:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2018-11-06 15:42:44 +00:00
|
|
|
* ARMv8-M memory map:
|
2018-11-01 21:46:39 +00:00
|
|
|
*
|
|
|
|
* Start End Name Executable by default Default cache Mbed MPU protection
|
2018-11-06 15:42:44 +00:00
|
|
|
* 0x00000000 - 0x1FFFFFFF Code Yes WT, WA Write disabled
|
2018-11-01 21:46:39 +00:00
|
|
|
* 0x20000000 - 0x3FFFFFFF SRAM Yes WB, WA, RA Execute disabled
|
|
|
|
* 0x40000000 - 0x5FFFFFFF Peripheral No
|
|
|
|
* 0x60000000 - 0x7FFFFFFF RAM Yes WB, WA, RA Execute disabled
|
|
|
|
* 0x80000000 - 0x9FFFFFFF RAM Yes WT, RA Execute disabled
|
|
|
|
* 0xA0000000 - 0xBFFFFFFF Device No
|
|
|
|
* 0xC0000000 - 0xDFFFFFFF Device No
|
|
|
|
* 0xE0000000 - 0xFFFFFFFF System No
|
|
|
|
*/
|
|
|
|
|
2018-12-11 16:21:28 +00:00
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
|
|
|
ARM_MPU_SetMemAttr(AttrIndex_WTRA, ARM_MPU_ATTR(WTRA, WTRA));
|
|
|
|
ARM_MPU_SetMemAttr(AttrIndex_WBWARA, ARM_MPU_ATTR(WBWARA, WBWARA));
|
|
|
|
|
|
|
|
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
|
|
|
|
);
|
|
|
|
|
|
|
|
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
|
|
|
|
);
|
|
|
|
|
|
|
|
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
|
|
|
|
);
|
2018-11-01 21:46:39 +00:00
|
|
|
|
|
|
|
// Enable the MPU
|
|
|
|
MPU->CTRL =
|
|
|
|
(1 << MPU_CTRL_PRIVDEFENA_Pos) | // Use the default memory map for unmapped addresses
|
|
|
|
(1 << MPU_CTRL_HFNMIENA_Pos) | // Keep MPU turned on for faults
|
|
|
|
(1 << MPU_CTRL_ENABLE_Pos); // Enable MPU
|
|
|
|
|
|
|
|
// Ensure changes take effect
|
|
|
|
__DSB();
|
2018-12-11 14:01:34 +00:00
|
|
|
__ISB();
|
2018-11-01 21:46:39 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 15:42:44 +00:00
|
|
|
void mbed_mpu_free()
|
|
|
|
{
|
|
|
|
// Flush memory writes before configuring the MPU.
|
2018-12-11 14:01:34 +00:00
|
|
|
__DMB();
|
2018-11-06 15:42:44 +00:00
|
|
|
|
|
|
|
// Disable the MCU
|
|
|
|
MPU->CTRL = 0;
|
|
|
|
|
|
|
|
// Ensure changes take effect
|
|
|
|
__DSB();
|
2018-12-11 14:01:34 +00:00
|
|
|
__ISB();
|
2018-11-06 15:42:44 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 16:21:04 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-11-06 15:42:44 +00:00
|
|
|
void mbed_mpu_enable_rom_wn(bool enable)
|
|
|
|
{
|
|
|
|
// Flush memory writes before configuring the MPU.
|
2018-12-11 14:01:34 +00:00
|
|
|
__DMB();
|
2018-11-06 15:42:44 +00:00
|
|
|
|
2018-12-11 16:21:04 +00:00
|
|
|
enable_region(enable, 0);
|
2018-11-06 15:42:44 +00:00
|
|
|
|
|
|
|
// Ensure changes take effect
|
|
|
|
__DSB();
|
2018-12-11 14:01:34 +00:00
|
|
|
__ISB();
|
2018-11-06 15:42:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void mbed_mpu_enable_ram_xn(bool enable)
|
|
|
|
{
|
|
|
|
// Flush memory writes before configuring the MPU.
|
2018-12-11 14:01:34 +00:00
|
|
|
__DMB();
|
2018-11-06 15:42:44 +00:00
|
|
|
|
2018-12-11 16:21:04 +00:00
|
|
|
for (uint32_t region = 1; region <= 3; region++) {
|
|
|
|
enable_region(enable, region);
|
|
|
|
}
|
2018-11-06 15:42:44 +00:00
|
|
|
|
|
|
|
// Ensure changes take effect
|
|
|
|
__DSB();
|
2018-12-11 14:01:34 +00:00
|
|
|
__ISB();
|
2018-11-06 15:42:44 +00:00
|
|
|
}
|
|
|
|
|
2018-11-01 21:46:39 +00:00
|
|
|
#endif
|