/** \defgroup mpu_functions MPU Functions for Armv7-M \brief Functions that relate to the Memory Protection Unit. \details The following functions support the optional Memory Protection Unit (MPU) that is available on the Cortex-M0+, M3, M4 and M7 processor. The MPU is used to prevent from illegal memory accesses that are typically caused by errors in an application software. Example: \code void main() { // Set Region 0 ARM_MPU_SetRegionEx(0UL, 0x08000000UL, MPU_RASR(0UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_1MB)); ARM_MPU_Enable(0); // Execute application code that is access protected by the MPU ARM_MPU_Disable(); } \endcode @{ */ /** */ typedef struct {} MPU_Type; /** \def ARM_MPU_RBAR * \brief MPU Region Base Address Register Value * * This preprocessor function can be used to construct a valid \ref MPU_Type::RBAR "RBAR" value. * The VALID bit is implicitly set to 1. * * \param Region The region to be configured, number 0 to 15. * \param BaseAddress The base address for the region. */ #define ARM_MPU_RBAR(Region, BaseAddress) /** * \def ARM_MPU_RASR * \brief MPU Region Attribute and Size Register Value * * This macro is used to construct a valid \ref MPU_Type::RASR "RASR" value. * The ENABLE bit of the RASR value is implicitly set to 1. * * \param DisableExec Instruction access disable bit. 1 = disable instruction fetches. * \param AccessPermission Data access permission configures read/write access for User and Privileged mode. Possible values see \ref ARM_MPU_AP_xxx. * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. * \param IsShareable 1 = region is shareable between multiple bus masters. * \param IsCacheable 1 = region is cacheable (values may be kept in cache). * \param IsBufferable 1 = region is bufferable (when using write-back caching). Cacheable but non-bufferable regions use write-through policy. * \param SubRegionDisable Sub-region disable field (8 bits). * \param Size Region size with values defined under \ref ARM_MPU_REGION_SIZE_xxx. */ #define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) /** * \brief Setup information of a single MPU Region * \details The typedef \ref ARM_MPU_Region_t allows to define a MPU table (array of MPU regions) with pre-compiled register values. * Such tables enable efficient MPU setup using the function \ref ARM_MPU_Load. * * Example: See \ref ARM_MPU_Load */ typedef struct { uint32_t RBAR; //!< The region base address register value (\ref MPU_Type::RBAR "RBAR") uint32_t RASR; //!< The region attribute and size register value (\ref MPU_Type::RASR "RASR"), see \ref ARM_MPU_RASR. } ARM_MPU_Region_t; /** \brief Enable the memory protection unit (MPU) and \param MPU_CTRL Additional control settings that configure MPU behaviour \details The function \ref ARM_MPU_Enable writes to the register \ref MPU_Type::CTRL "MPU->CTRL" and sets bit ENABLE. The parameter \em MPU_CTRL provides additional bit values (see table below) that configure the MPU behaviour. For processors that implement an MPU Fault Handler the \ref NVIC_gr "MemoryManagement_IRQn" exception is enabled by setting the bit MEMFAULTACT in register SBC->SHCSR. The following table contains possible values for the parameter \em MPU_CTRL that set specific bits in register MPU->CTRL. | Bit | MPU_CTRL value | When applied | When not applied |:----|:-------------------------|:------------------------------------------------------------------------|:--------------------------------------- | 1 | MPU_CTRL_HFNMIENA_Pos | Enable MPU during hard fault, NMI, and FAULTMASK handlers execution | Disable MPU during hard fault, NMI, and FAULTMASK handler execution | 2 | MPU_CTRL_PRIVDEFENA_Pos | Enable default memory map as a background region for privileged access | Use only MPU region settings Example: \code // enable MPU with all region definitions. Exceptions are not protected by MPU. MPU_Enable (0); // enable MPU with all region definitions and background regions for privileged access. Exceptions are protected by MPU. MPU_Enable (MPU_CTRL_PRIVDEFENA_Pos | MPU_CTRL_HFNMIENA_Pos); \endcode */ __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_CTRL); /** Disable the MPU. */ __STATIC_INLINE void ARM_MPU_Disable(); /** Clear and disable the given MPU region. * \param rnr Region number to be cleared. */ __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr); /** Configure an MPU region. * * The region number should be contained in the rbar value. * * \param rbar Value for \ref MPU_Type::RBAR "RBAR" register. * \param rasr Value for \ref MPU_Type::RASR "RASR" register. */ __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr); /** Configure the given MPU region. * \param rnr Region number to be configured. * \param rbar Value for \ref MPU_Type::RBAR "RBAR" register. * \param rasr Value for \ref MPU_Type::RASR "RASR" register. */ __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr); /** Load the given number of MPU regions from a table. * \param table Pointer to the MPU configuration table. * \param cnt Number of regions to be configured. * * \note only up to 16 regions can be handled as the function \ref ARM_MPU_Load uses the REGION field in \ref MPU_Type::RBAR "MPU->RBAR". * * Example: * \code * const ARM_MPU_Region_t mpuTable[3][4] = { * { * { .RBAR = ARM_MPU_RBAR(0UL, 0x08000000UL), .RASR = ARM_MPU_RASR(0UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_1MB) }, * { .RBAR = ARM_MPU_RBAR(1UL, 0x20000000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_32KB) }, * { .RBAR = ARM_MPU_RBAR(2UL, 0x40020000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 2UL, 0UL, 0UL, 0UL, 0x00UL, ARM_MPU_REGION_SIZE_8KB) }, * { .RBAR = ARM_MPU_RBAR(3UL, 0x40022000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 2UL, 0UL, 0UL, 0UL, 0xC0UL, ARM_MPU_REGION_SIZE_4KB) } * }, * { * { .RBAR = ARM_MPU_RBAR(4UL, 0x08000000UL), .RASR = ARM_MPU_RASR(0UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_1MB) }, * { .RBAR = ARM_MPU_RBAR(5UL, 0x20000000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_32KB) }, * { .RBAR = ARM_MPU_RBAR(6UL, 0x40020000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 2UL, 0UL, 0UL, 0UL, 0x00UL, ARM_MPU_REGION_SIZE_8KB) }, * { .RBAR = ARM_MPU_RBAR(7UL, 0x40022000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 2UL, 0UL, 0UL, 0UL, 0xC0UL, ARM_MPU_REGION_SIZE_4KB) } * }, * { * { .RBAR = ARM_MPU_RBAR(4UL, 0x18000000UL), .RASR = ARM_MPU_RASR(0UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_1MB) }, * { .RBAR = ARM_MPU_RBAR(5UL, 0x30000000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 0UL, 0UL, 1UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_32KB) }, * { .RBAR = ARM_MPU_RBAR(6UL, 0x50020000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 2UL, 0UL, 0UL, 0UL, 0x00UL, ARM_MPU_REGION_SIZE_8KB) }, * { .RBAR = ARM_MPU_RBAR(7UL, 0x50022000UL), .RASR = ARM_MPU_RASR(1UL, ARM_MPU_AP_FULL, 2UL, 0UL, 0UL, 0UL, 0xC0UL, ARM_MPU_REGION_SIZE_4KB) } * } * }; * * void UpdateMpu(uint32_t idx) * { * ARM_MPU_Load(mpuTable[idx], 4); * } * \endcode * */ __STATIC_INLINE void ARM_MPU_Load(MPU_Region_t const* table, uint32_t cnt); /** @} \defgroup mpu_defines Define values \ingroup mpu_functions \brief Define values for MPU region setup. \details The following define values are used with \ref ARM_MPU_RASR to setup the \ref MPU_Type::RASR "RASR" value field in the MPU region. \see ARM_MPU_Region_t, ARM_MPU_SetRegion, ARM_MPU_SetRegionEx. @{ */ /** \def ARM_MPU_REGION_SIZE_xxx \brief Size values of a MPU region (in RASR field) \details The following define values are used to compose the size information for an MPU region: |\#define | Value | Description | |:-------------------------|:-----------------|:---------------------------------------------------------| |ARM_MPU_REGION_SIZE_32B | 0x04U | Region size 32 Bytes |ARM_MPU_REGION_SIZE_64B | 0x05U | Region size 64 Bytes |ARM_MPU_REGION_SIZE_128B | 0x06U | Region size 128 Bytes |ARM_MPU_REGION_SIZE_256B | 0x07U | Region size 256 Bytes |ARM_MPU_REGION_SIZE_512B | 0x08U | Region size 512 Bytes |ARM_MPU_REGION_SIZE_1KB | 0x09U | Region size 1 KByte |ARM_MPU_REGION_SIZE_2KB | 0x0AU | Region size 2 KBytes |ARM_MPU_REGION_SIZE_4KB | 0x0BU | Region size 4 KBytes |ARM_MPU_REGION_SIZE_8KB | 0x0CU | Region size 8 KBytes |ARM_MPU_REGION_SIZE_16KB | 0x0DU | Region size 16 KBytes |ARM_MPU_REGION_SIZE_32KB | 0x0EU | Region size 32 KBytes |ARM_MPU_REGION_SIZE_64KB | 0x0FU | Region size 64 KBytes |ARM_MPU_REGION_SIZE_128KB | 0x10U | Region size 128 KBytes |ARM_MPU_REGION_SIZE_256KB | 0x11U | Region size 256 KBytes |ARM_MPU_REGION_SIZE_512KB | 0x12U | Region size 512 KBytes |ARM_MPU_REGION_SIZE_1MB | 0x13U | Region size 1 MByte |ARM_MPU_REGION_SIZE_2MB | 0x14U | Region size 2 MBytes |ARM_MPU_REGION_SIZE_4MB | 0x15U | Region size 4 MBytes |ARM_MPU_REGION_SIZE_8MB | 0x16U | Region size 8 MBytes |ARM_MPU_REGION_SIZE_16MB | 0x17U | Region size 16 MBytes |ARM_MPU_REGION_SIZE_32MB | 0x18U | Region size 32 MBytes |ARM_MPU_REGION_SIZE_64MB | 0x19U | Region size 64 MBytes |ARM_MPU_REGION_SIZE_128MB | 0x1AU | Region size 128 MBytes |ARM_MPU_REGION_SIZE_256MB | 0x1BU | Region size 256 MBytes |ARM_MPU_REGION_SIZE_512MB | 0x1CU | Region size 512 MBytes |ARM_MPU_REGION_SIZE_1GB | 0x1DU | Region size 1 GByte |ARM_MPU_REGION_SIZE_2GB | 0x1EU | Region size 2 GBytes |ARM_MPU_REGION_SIZE_4GB | 0x1FU | Region size 4 GBytes */ #define ARM_MPU_REGION_SIZE_xxx /** \def ARM_MPU_AP_xxx \brief Values for MPU region access permissions (in RASR field) \details The following define values are used to compose the access permission for an MPU region: |\#define | Value | Access permissions | |:-------------------------|:-----------------|:---------------------------------------------------------| |ARM_MPU_AP_NONE | 0x0U | None: any access generates a permission fault. |ARM_MPU_AP_PRIV | 0x1U | Privileged Read/Write: privileged access only; any unprivileged access generates a permission fault. |ARM_MPU_AP_URO | 0x2U | Privileged Read/Write; Unprivileged Read-only: any unprivileged write generates a permission fault. |ARM_MPU_AP_FULL | 0x3U | Privileged Read/Write. Unprivileged Read/Write: full access, permission faults are never generated. |ARM_MPU_AP_PRO | 0x5U | Privileged Read-only: any unprivileged access or privileged write generates a permission fault. |ARM_MPU_AP_RO | 0x6U | Privileged and Unprivileged Read-only: any write generates a permission fault. */ #define ARM_MPU_AP_xxx /** @} */ /** \var ARM_MPU_Region_t::RBAR This value specifies the start address of the MPU protected memory region. The address must be a multiple of the region size (size aligned). See \ref MPU_Type::RBAR for details about field bit format. \var ARM_MPU_Region_t::RASR This value specifies region attributes and size. Use the \ref ARM_MPU_RASR macro to compose this value. \var MPU_Type::TYPE The MPU Type Register indicates how many regions the MPU support. Software can use it to determine if the processor implements an MPU. | Bits | Name | Function | | :------ | :------------ | :------------------------------------------------------------ | | [31:24] | - | Reserved. | | [23:16] | IREGION | Instruction region. RAZ. Armv7-M only supports a unified MPU. | | [15:8] | DREGION | Number of regions supported by the MPU. If this field reads-as-zero the processor does not implement an MPU. | | [7:1] | - | Reserved. | | [0] | SEPARATE | Indicates support for separate instruction and data address maps. RAZ. Armv7-M only supports a unified MPU. | \var MPU_Type::CTRL Enables the MPU, and when the MPU is enabled, controls whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults, NMIs, and exception handlers when FAULTMASK is set to 1. | Bits | Name | Function | | :------ | :------------ | :------------------------------------------------------------ | | [31:3] | - | Reserved. | | [2] | PRIVDEFENA | 0 - Disables the default memory map. 1 - Enables the default memory map as a background region for privileged access. | | [1] | HFNMIENA | 0 - Disables the MPU for exception handlers. 1 - Use the MPU for memory accesses by exception handlers. | | [0] | ENABLE | 0 - The MPU is disabled. 1 - The MPU is enabled. | \var MPU_Type::RNR Selects the region currently accessed by \ref MPU_Type::RBAR and \ref MPU_Type::RASR. | Bits | Name | Function | | :------ | :------------ | :------------------------------------------------------------ | | [31:8] | - | Reserved. | | [7:0] | REGION | Indicates the memory region accessed. | \var MPU_Type::RBAR Holds the base address of the region identified by MPU_RNR. On a write, can also be used to update the base address of a specified region, in the range 0 to 15, updating MPU_RNR with the new region number. | Bits | Name | Function | | :------ | :------------ | :------------------------------------------------------------ | | [31:5] | ADDR | Base address of the region. | | [4] | VALID | 1 - Update \ref MPU_Type::RNR to the value obtained by zero extending the REGION value specified in this write, and apply the base address update to this region. | | [3:0] | REGION | On writes, can specify the number of the region to update, see VALID field description. | \var MPU_Type::RASR Defines the size and access behavior of the region identified by MPU_RNR, and enables that region. | Bits | Name | Function | | :------ | :------------ | :------------------------------------------------------------ | | [31:29] | - | Reserved. | | [28] | XN | Execute Never. | | [27] | - | Reserved. | | [26:24] | AP | Access Permissions, see \ref ARM_MPU_AP_xxx. | | [23:22] | - | Reserved. | | [21:19] | TEX | Type Extension. | | [18] | S | Shareable. | | [17] | C | Cacheable. | | [16] | B | Bufferable. | | [15:8] | SRD | Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled (0) or disabled (1). | [7:6] | - | Reserved. | | [5:1] | SIZE | Indicates the region size. The region size, in bytes, is 2(SIZE+1). SIZE field values less than 4 are reserved, because the smallest supported region size is 32 bytes. | | [0] | ENABLE | 0 - This region is disabled. 1 - This region is enabled. | \var MPU_Type::RBAR_A1 Alias for \ref MPU_Type::RBAR. \var MPU_Type::RASR_A1 Alias for \ref MPU_Type::RASR. \var MPU_Type::RBAR_A2 Alias for \ref MPU_Type::RBAR. \var MPU_Type::RASR_A2 Alias for \ref MPU_Type::RASR. \var MPU_Type::RBAR_A3 Alias for \ref MPU_Type::RBAR. \var MPU_Type::RASR_A3 Alias for \ref MPU_Type::RASR. */