mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_mpu_v7m.c Source File

mbed_mpu_v7m.c

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "hal/mpu_api.h"
00017 #include "platform/mbed_assert.h"
00018 #include "cmsis.h"
00019 
00020 #if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_6M__ == 1U)) && \
00021     defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
00022     !defined(MBED_MPU_CUSTOM)
00023 
00024 #if !DEVICE_MPU
00025 #error "Device has v7m MPU but it is not enabled. Add 'MPU' to device_has in targets.json"
00026 #endif
00027 
00028 #ifdef MBED_CONF_TARGET_MPU_ROM_END
00029 #define MBED_MPU_ROM_END             MBED_CONF_TARGET_MPU_ROM_END
00030 #else
00031 #define MBED_MPU_ROM_END             (0x10000000 - 1)
00032 #endif
00033 #define MBED_MPU_RAM_START           (MBED_MPU_ROM_END + 1)
00034 
00035 MBED_STATIC_ASSERT(
00036     MBED_MPU_ROM_END == 0x04000000 - 1 ||
00037     MBED_MPU_ROM_END == 0x08000000 - 1 ||
00038     MBED_MPU_ROM_END == 0x0C000000 - 1 ||
00039     MBED_MPU_ROM_END == 0x10000000 - 1 ||
00040     MBED_MPU_ROM_END == 0x14000000 - 1 ||
00041     MBED_MPU_ROM_END == 0x18000000 - 1 ||
00042     MBED_MPU_ROM_END == 0x1C000000 - 1 ||
00043     MBED_MPU_ROM_END == 0x20000000 - 1,
00044     "Unsupported value for MBED_MPU_ROM_END");
00045 
00046 void mbed_mpu_init()
00047 {
00048     // Flush memory writes before configuring the MPU.
00049     __DMB();
00050 
00051     const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
00052 
00053     // Our MPU setup requires 3 or 4 regions - if this assert is hit, remove
00054     // a region by setting MPU_ROM_END to 0x1fffffff, or remove MPU from device_has
00055 #if MBED_MPU_RAM_START == 0x20000000
00056     MBED_ASSERT(regions >= 3);
00057 #else
00058     MBED_ASSERT(regions >= 4);
00059 #endif
00060 
00061     // Disable the MCU
00062     MPU->CTRL = 0;
00063 
00064     // Reset all mapping
00065     for (uint32_t i = 0; i < regions; i++) {
00066         ARM_MPU_ClrRegion(i);
00067     }
00068 
00069     /*
00070      * ARMv6m and ARMv7-M memory map:
00071      *
00072      * Start        End            Name            Executable by default        Mbed MPU protection
00073      * 0x00000000 - 0x1FFFFFFF     Code            Yes                          Write disabled for first portion and execute disabled for the rest
00074      * 0x20000000 - 0x3FFFFFFF     SRAM            Yes                          Execute disabled
00075      * 0x40000000 - 0x5FFFFFFF     Peripheral      No
00076      * 0x60000000 - 0x7FFFFFFF     RAM             Yes                          Execute disabled
00077      * 0x80000000 - 0x9FFFFFFF     RAM             Yes                          Execute disabled
00078      * 0xA0000000 - 0xBFFFFFFF     Device          No
00079      * 0xC0000000 - 0xDFFFFFFF     Device          No
00080      * 0xE0000000 - 0xFFFFFFFF     System          No
00081      */
00082 
00083     // Select region 0 and use it for the WT read-only rom region
00084     // - Code 0x00000000 to MBED_MPU_ROM_END
00085     ARM_MPU_SetRegion(
00086         ARM_MPU_RBAR(
00087             0,                          // Region
00088             0x00000000),                // Base
00089         ARM_MPU_RASR(
00090             0,                          // DisableExec
00091             ARM_MPU_AP_RO,              // AccessPermission
00092             0,                          // TypeExtField
00093             0,                          // IsShareable
00094             1,                          // IsCacheable
00095             0,                          // IsBufferable
00096             // SubRegionDisable - based on where ROM ends
00097             ((MBED_MPU_ROM_END >= 0x00000000) ? 0 : (1 << 0)) |    // 0 to enable, 1 << n to disable
00098             ((MBED_MPU_ROM_END >= 0x04000000) ? 0 : (1 << 1)) |
00099             ((MBED_MPU_ROM_END >= 0x08000000) ? 0 : (1 << 2)) |
00100             ((MBED_MPU_ROM_END >= 0x0C000000) ? 0 : (1 << 3)) |
00101             ((MBED_MPU_ROM_END >= 0x10000000) ? 0 : (1 << 4)) |
00102             ((MBED_MPU_ROM_END >= 0x14000000) ? 0 : (1 << 5)) |
00103             ((MBED_MPU_ROM_END >= 0x18000000) ? 0 : (1 << 6)) |
00104             ((MBED_MPU_ROM_END >= 0x1C000000) ? 0 : (1 << 7)),
00105             ARM_MPU_REGION_SIZE_512MB)  // Size
00106     );
00107 
00108 #if MBED_MPU_RAM_START < 0x20000000
00109     // Select region 3 and use it for a WT ram region in the Code area
00110     // - Code MBED_MPU_ROM_END + 1 to 0x1FFFFFFF
00111     ARM_MPU_SetRegion(
00112         ARM_MPU_RBAR(
00113             3,                          // Region
00114             0x00000000),                // Base
00115         ARM_MPU_RASR(
00116             1,                          // DisableExec
00117             ARM_MPU_AP_FULL,            // AccessPermission
00118             0,                          // TypeExtField
00119             0,                          // IsShareable
00120             1,                          // IsCacheable
00121             0,                          // IsBufferable
00122             // SubRegionDisable - based on where RAM starts
00123             ((MBED_MPU_RAM_START <= 0x04000000) ? 0 : (1 << 0)) |    // 0 to enable, 1 << n to disable
00124             ((MBED_MPU_RAM_START <= 0x08000000) ? 0 : (1 << 1)) |
00125             ((MBED_MPU_RAM_START <= 0x0C000000) ? 0 : (1 << 2)) |
00126             ((MBED_MPU_RAM_START <= 0x10000000) ? 0 : (1 << 3)) |
00127             ((MBED_MPU_RAM_START <= 0x14000000) ? 0 : (1 << 4)) |
00128             ((MBED_MPU_RAM_START <= 0x18000000) ? 0 : (1 << 5)) |
00129             ((MBED_MPU_RAM_START <= 0x1C000000) ? 0 : (1 << 6)) |
00130             ((MBED_MPU_RAM_START <= 0x20000000) ? 0 : (1 << 7)),
00131             ARM_MPU_REGION_SIZE_512MB)  // Size
00132     );
00133 #define LAST_RAM_REGION 3
00134 #else
00135 #define LAST_RAM_REGION 2
00136 #endif
00137 
00138     // Select region 1 and use it for WBWA ram regions
00139     // - SRAM 0x20000000 to 0x3FFFFFFF
00140     // - RAM  0x60000000 to 0x7FFFFFFF
00141     ARM_MPU_SetRegion(
00142         ARM_MPU_RBAR(
00143             1,                          // Region
00144             0x00000000),                // Base
00145         ARM_MPU_RASR(
00146             1,                          // DisableExec
00147             ARM_MPU_AP_FULL,            // AccessPermission
00148             1,                          // TypeExtField
00149             0,                          // IsShareable
00150             1,                          // IsCacheable
00151             1,                          // IsBufferable
00152             // SubRegionDisable
00153             (1 << 0) |     // Disable Sub-region
00154             (0 << 1) |     // Enable Sub-region SRAM 0x20000000 - 0x3FFFFFFF
00155             (1 << 2) |     // Disable Sub-region
00156             (0 << 3) |     // Enable Sub-region RAM 0x60000000 - 0x7FFFFFFF
00157             (1 << 4) |     // Disable Sub-region
00158             (1 << 5) |     // Disable Sub-region
00159             (1 << 6) |     // Disable Sub-region
00160             (1 << 7),      // Disable Sub-region
00161             ARM_MPU_REGION_SIZE_4GB)    // Size
00162     );
00163 
00164     // Select region 2 and use it for the WT ram region
00165     // - RAM 0x80000000 to 0x9FFFFFFF
00166     ARM_MPU_SetRegion(
00167         ARM_MPU_RBAR(
00168             2,                          // Region
00169             0x80000000),                // Base
00170         ARM_MPU_RASR(
00171             1,                          // DisableExec
00172             ARM_MPU_AP_FULL,            // AccessPermission
00173             0,                          // TypeExtField
00174             0,                          // IsShareable
00175             1,                          // IsCacheable
00176             0,                          // IsBufferable
00177             0U,                         // SubRegionDisable
00178             ARM_MPU_REGION_SIZE_512MB)  // Size
00179     );
00180 
00181     // Enable the MPU
00182     MPU->CTRL =
00183         (1 << MPU_CTRL_PRIVDEFENA_Pos) |            // Use the default memory map for unmapped addresses
00184         (1 << MPU_CTRL_HFNMIENA_Pos) |              // Keep MPU turned on for faults
00185         (1 << MPU_CTRL_ENABLE_Pos);                 // Enable MPU
00186 
00187     // Ensure changes take effect
00188     __DSB();
00189     __ISB();
00190 }
00191 
00192 void mbed_mpu_free()
00193 {
00194     // Flush memory writes before configuring the MPU.
00195     __DMB();
00196 
00197     // Disable the MPU
00198     MPU->CTRL = 0;
00199 
00200     // Ensure changes take effect
00201     __DSB();
00202     __ISB();
00203 }
00204 
00205 static void enable_region(bool enable, uint32_t region)
00206 {
00207     MPU->RNR = region;
00208     MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable << MPU_RASR_ENABLE_Pos);
00209 }
00210 
00211 void mbed_mpu_enable_rom_wn(bool enable)
00212 {
00213     // Flush memory writes before configuring the MPU.
00214     __DMB();
00215 
00216     enable_region(enable, 0);
00217 
00218     // Ensure changes take effect
00219     __DSB();
00220     __ISB();
00221 }
00222 
00223 void mbed_mpu_enable_ram_xn(bool enable)
00224 {
00225     // Flush memory writes before configuring the MPU.
00226     __DMB();
00227 
00228     for (uint32_t region = 1; region <= LAST_RAM_REGION; region++) {
00229         enable_region(enable, region);
00230     }
00231 
00232     // Ensure changes take effect
00233     __DSB();
00234     __ISB();
00235 }
00236 
00237 #endif