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_v8m.c Source File

mbed_mpu_v8m.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_8M_BASE__ == 1U) || (__ARM_ARCH_8M_MAIN__ == 1U)) && \
00021     defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
00022     !defined(MBED_MPU_CUSTOM)
00023 
00024 #if !DEVICE_MPU
00025 #error "Device has v8m 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(MBED_MPU_ROM_END <= 0x20000000 - 1,
00036                    "Unsupported value for MBED_MPU_ROM_END");
00037 
00038 void mbed_mpu_init()
00039 {
00040     // Flush memory writes before configuring the MPU.
00041     __DMB();
00042 
00043     const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
00044 
00045     // Our MPU setup requires 4 or 5 regions - if this assert is hit, remove
00046     // a region by setting MPU_ROM_END to 0x1fffffff, or remove MPU from device_has
00047 #if MBED_MPU_RAM_START == 0x20000000
00048     MBED_ASSERT(regions >= 4);
00049 #else
00050     MBED_ASSERT(regions >= 5);
00051 #endif
00052 
00053     // Disable the MCU
00054     MPU->CTRL = 0;
00055 
00056     // Reset all mapping
00057     for (uint32_t i = 0; i < regions; i++) {
00058         ARM_MPU_ClrRegion(i);
00059     }
00060 
00061     /*
00062      * ARMv8-M memory map:
00063      *
00064      * Start        End            Name            Executable by default    Default cache       Mbed MPU protection
00065      * 0x00000000 - 0x1FFFFFFF     Code            Yes                      WT, WA              Write disabled for first portion and execute disabled for the rest
00066      * 0x20000000 - 0x3FFFFFFF     SRAM            Yes                      WB, WA, RA          Execute disabled
00067      * 0x40000000 - 0x5FFFFFFF     Peripheral      No
00068      * 0x60000000 - 0x7FFFFFFF     RAM             Yes                      WB, WA, RA          Execute disabled
00069      * 0x80000000 - 0x9FFFFFFF     RAM             Yes                      WT, RA              Execute disabled
00070      * 0xA0000000 - 0xBFFFFFFF     Device          No
00071      * 0xC0000000 - 0xDFFFFFFF     Device          No
00072      * 0xE0000000 - 0xFFFFFFFF     System          No
00073      */
00074 
00075     const uint8_t WTRA = ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0);      // Non-transient, Write-Through, Read-allocate, Not Write-allocate
00076     const uint8_t WBWARA = ARM_MPU_ATTR_MEMORY_(1, 1, 1, 1);    // Non-transient, Write-Back, Read-allocate, Write-allocate
00077     enum {
00078         AttrIndex_WTRA,
00079         AttrIndex_WBWARA,
00080     };
00081 
00082     ARM_MPU_SetMemAttr(AttrIndex_WTRA, ARM_MPU_ATTR(WTRA, WTRA));
00083     ARM_MPU_SetMemAttr(AttrIndex_WBWARA, ARM_MPU_ATTR(WBWARA, WBWARA));
00084 
00085     ARM_MPU_SetRegion(
00086         0,                          // Region
00087         ARM_MPU_RBAR(
00088             0x00000000,             // Base
00089             ARM_MPU_SH_NON,         // Non-shareable
00090             1,                      // Read-Only
00091             1,                      // Non-Privileged
00092             0),                     // Execute Never disabled
00093         ARM_MPU_RLAR(
00094             MBED_MPU_ROM_END,       // Limit
00095             AttrIndex_WTRA)         // Attribute index - Write-Through, Read-allocate
00096     );
00097 
00098 #if MBED_MPU_RAM_START != 0x20000000
00099     ARM_MPU_SetRegion(
00100         4,                          // Region
00101         ARM_MPU_RBAR(
00102             MBED_MPU_RAM_START,     // Base
00103             ARM_MPU_SH_NON,         // Non-shareable
00104             0,                      // Read-Write
00105             1,                      // Non-Privileged
00106             1),                     // Execute Never enabled
00107         ARM_MPU_RLAR(
00108             0x1FFFFFFF,             // Limit
00109             AttrIndex_WTRA)         // Attribute index - Write-Through, Read-allocate
00110     );
00111 #define LAST_RAM_REGION 4
00112 #else
00113 #define LAST_RAM_REGION 3
00114 #endif
00115 
00116     ARM_MPU_SetRegion(
00117         1,                          // Region
00118         ARM_MPU_RBAR(
00119             0x20000000,             // Base
00120             ARM_MPU_SH_NON,         // Non-shareable
00121             0,                      // Read-Write
00122             1,                      // Non-Privileged
00123             1),                     // Execute Never enabled
00124         ARM_MPU_RLAR(
00125             0x3FFFFFFF,             // Limit
00126             AttrIndex_WBWARA)       // Attribute index - Write-Back, Write-allocate
00127     );
00128 
00129     ARM_MPU_SetRegion(
00130         2,                          // Region
00131         ARM_MPU_RBAR(
00132             0x60000000,             // Base
00133             ARM_MPU_SH_NON,         // Non-shareable
00134             0,                      // Read-Write
00135             1,                      // Non-Privileged
00136             1),                     // Execute Never enabled
00137         ARM_MPU_RLAR(
00138             0x7FFFFFFF,             // Limit
00139             AttrIndex_WBWARA)       // Attribute index - Write-Back, Write-allocate
00140     );
00141 
00142     ARM_MPU_SetRegion(
00143         3,                          // Region
00144         ARM_MPU_RBAR(
00145             0x80000000,             // Base
00146             ARM_MPU_SH_NON,         // Non-shareable
00147             0,                      // Read-Write
00148             1,                      // Non-Privileged
00149             1),                     // Execute Never enabled
00150         ARM_MPU_RLAR(
00151             0x9FFFFFFF,             // Limit
00152             AttrIndex_WTRA)         // Attribute index - Write-Through, Read-allocate
00153     );
00154 
00155     // Enable the MPU
00156     MPU->CTRL =
00157         (1 << MPU_CTRL_PRIVDEFENA_Pos) |            // Use the default memory map for unmapped addresses
00158         (1 << MPU_CTRL_HFNMIENA_Pos) |              // Keep MPU turned on for faults
00159         (1 << MPU_CTRL_ENABLE_Pos);                 // Enable MPU
00160 
00161     // Ensure changes take effect
00162     __DSB();
00163     __ISB();
00164 }
00165 
00166 void mbed_mpu_free()
00167 {
00168     // Flush memory writes before configuring the MPU.
00169     __DMB();
00170 
00171     // Disable the MCU
00172     MPU->CTRL = 0;
00173 
00174     // Ensure changes take effect
00175     __DSB();
00176     __ISB();
00177 }
00178 
00179 static void enable_region(bool enable, uint32_t region)
00180 {
00181     MPU->RNR = region;
00182     MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable << MPU_RLAR_EN_Pos);
00183 }
00184 
00185 void mbed_mpu_enable_rom_wn(bool enable)
00186 {
00187     // Flush memory writes before configuring the MPU.
00188     __DMB();
00189 
00190     enable_region(enable, 0);
00191 
00192     // Ensure changes take effect
00193     __DSB();
00194     __ISB();
00195 }
00196 
00197 void mbed_mpu_enable_ram_xn(bool enable)
00198 {
00199     // Flush memory writes before configuring the MPU.
00200     __DMB();
00201 
00202     for (uint32_t region = 1; region <= LAST_RAM_REGION; region++) {
00203         enable_region(enable, region);
00204     }
00205 
00206     // Ensure changes take effect
00207     __DSB();
00208     __ISB();
00209 }
00210 
00211 #endif