Understanding MPU_RASR Configuration for Bootloader Protection on Cortex-M4
The Memory Protection Unit (MPU) in ARM Cortex-M4 processors is a critical component for enforcing memory access rules and ensuring system security. Proper configuration of the MPU requires a deep understanding of the Region Attribute and Size Register (MPU_RASR), particularly the TEX (Type Extension), C (Cacheable), B (Bufferable), and S (Shareable) bits. Misconfiguring these bits can lead to unintended memory access behaviors, system instability, or security vulnerabilities. In this guide, we will explore the correct configuration of MPU_RASR for protecting a bootloader region in ROM memory (0x0000 – 0x8000) on an LPC4078 microcontroller with a Cortex-M4 core.
The primary challenge lies in determining the appropriate values for TEX, C, B, and S bits, as these collectively define the memory attributes and access behavior. Additionally, the Access Permission (AP) and Execute Never (XN) bits must be configured to ensure the bootloader region is read-only and executable. This guide will provide a detailed breakdown of the configuration process, including the rationale behind each setting and potential pitfalls.
Memory Attribute Encoding: TEX, C, B, and S Bits
The TEX, C, B, and S bits in the MPU_RASR register define the memory attributes for the protected region. These bits are interdependent and must be configured as a group to achieve the desired memory behavior. The Cortex-M4 architecture defines specific encoding schemes for these bits, which determine whether the memory region is treated as Strongly-ordered, Device, or Normal memory. Each type has distinct characteristics that influence how the processor interacts with the memory.
For a bootloader region in ROM, the memory is typically non-writable and non-bufferable. However, the cacheability and shareability attributes depend on the system design and usage context. The TEX bits (Type Extension) provide additional granularity for memory types, while the C (Cacheable) and B (Bufferable) bits control caching and buffering behavior. The S (Shareable) bit determines whether the memory region is shared between multiple bus masters, such as DMA controllers or other processors.
The following table summarizes the encoding of TEX, C, B, and S bits for common memory types:
TEX | C | B | S | Memory Type | Description |
---|---|---|---|---|---|
000 | 0 | 0 | 0 | Strongly-ordered | Non-cacheable, non-bufferable, and shareable. Used for critical peripherals. |
000 | 0 | 0 | 1 | Device | Non-cacheable, non-bufferable, and non-shareable. Used for memory-mapped I/O. |
000 | 1 | 0 | 0 | Normal, non-cacheable | Non-cacheable, non-bufferable, and non-shareable. Used for ROM or flash. |
000 | 1 | 0 | 1 | Normal, cacheable | Cacheable, non-bufferable, and shareable. Used for frequently accessed data. |
001 | 0 | 1 | 0 | Normal, write-through | Cacheable, bufferable, and non-shareable. Used for write-through caching. |
001 | 1 | 1 | 0 | Normal, write-back | Cacheable, bufferable, and non-shareable. Used for write-back caching. |
For a bootloader region in ROM, the memory type is typically Normal, non-cacheable (TEX=000, C=1, B=0, S=0). This configuration ensures that the memory is non-writable, non-bufferable, and non-shareable, which aligns with the read-only nature of ROM. However, if the bootloader region is shared with other bus masters, such as a DMA controller, the S bit should be set to 1 to indicate shareability.
Access Permissions and Execute Never Configuration
The Access Permission (AP) and Execute Never (XN) bits in the MPU_RASR register control the accessibility and executability of the protected memory region. For a bootloader region, the primary goal is to prevent unauthorized writes while allowing read access and instruction fetches. The AP bits define the access permissions for privileged and unprivileged software, while the XN bit determines whether instruction fetches are allowed.
The AP bits are encoded as follows:
AP[2:0] | Privileged Access | Unprivileged Access |
---|---|---|
000 | No access | No access |
001 | Read-only | No access |
010 | Read-only | Read-only |
011 | Read-write | No access |
100 | Read-write | Read-only |
101 | Read-write | Read-write |
110 | Read-only | Read-only |
111 | Read-only | Read-only |
For a bootloader region, the AP bits should be set to 011 (Read-only for privileged and unprivileged software) to prevent writes while allowing reads. The XN bit should be set to 0 to enable instruction fetches, as the bootloader region typically contains the vector table and executable code.
Implementing MPU_RASR Configuration for Bootloader Protection
To implement the MPU_RASR configuration for bootloader protection, follow these steps:
- Enable the MPU Region: Set the ENABLE bit to 1 to activate the MPU region.
- Define the Region Size: Set the SIZE field to 14 (32 KB) to cover the bootloader region (0x0000 – 0x8000).
- Configure Memory Attributes: Set TEX=000, C=1, B=0, and S=0 to define the memory type as Normal, non-cacheable.
- Set Access Permissions: Set AP=011 to allow read-only access for both privileged and unprivileged software.
- Enable Instruction Fetches: Set XN=0 to allow instruction fetches from the bootloader region.
- Disable Sub-region Division: Set SRD=0 to ensure the entire bootloader region is protected as a single unit.
The following code snippet demonstrates the MPU_RASR configuration for the bootloader region:
#define MPU_RASR_ENABLE (1 << 0)
#define MPU_RASR_SIZE_32KB (14 << 1)
#define MPU_RASR_SRD_DISABLE (0 << 8)
#define MPU_RASR_TEX_NORMAL (0 << 12)
#define MPU_RASR_C_CACHEABLE (1 << 17)
#define MPU_RASR_B_NONBUFFER (0 << 16)
#define MPU_RASR_S_NONSHARE (0 << 18)
#define MPU_RASR_AP_READONLY (3 << 24)
#define MPU_RASR_XN_ENABLE (0 << 28)
uint32_t mpu_rasr = MPU_RASR_ENABLE | MPU_RASR_SIZE_32KB | MPU_RASR_SRD_DISABLE |
MPU_RASR_TEX_NORMAL | MPU_RASR_C_CACHEABLE | MPU_RASR_B_NONBUFFER |
MPU_RASR_S_NONSHARE | MPU_RASR_AP_READONLY | MPU_RASR_XN_ENABLE;
By following these steps and using the provided configuration, you can effectively protect the bootloader region from unauthorized writes while ensuring proper system functionality. This configuration is tailored for the LPC4078 microcontroller but can be adapted for other Cortex-M4-based systems with similar requirements.