Introduction to
Cortex-M3/M4 M0+ MPU (Memory Protection Unit)
SITE HOME
Scope:
This techerature introduces the MPU, the Memory Protection Unit on
ARM Cortex-M processors.
In previous section(s) we learned about Privilege
Levels on ARM Cortex-M processors. Here, we go a bit beyond
just privilege levels, and explain the role of Memory Protection
Units on ARM Cortex-M processors to implement finer levels of access
control/access protection mechanisms.
The MPU is an optional component on certain ARM Cortex-M processors
(M0+, M3/M4, M7 etc), which a user may use to divide the system
memory in several regions, which each region having different access
rights.
Note: Some other cortex-M processors such
as M33 are not mentioned here, even though they offer an MPU
because these offer an higher level of security under what is
termed as ARM
TrustZone for Cortex-M. The details of these processors
are beyond the scope of this techerature.
The user will typically program the regions of memory to allow an
access originating from the processor to be successful or erroneous
based upon a number of available criteria. For example,
A user may define the region of the memory from 0x4000_0000 to
0x4000_FFFF as a region which is
- Only accessible while the processor code is running in
privileged mode
- Is only Read Only
- Is only Execute-Never
etc.
This is done via MPU programming. Note that the MPU registers are
only available to be read/written while the processor is at
privileged access level. The MPU provides the user sets of registers
for each region of memory. Maximum 8 regions of memories are
permitted. Each 'region' is identified by base address, and size.
Each region can have different 'access rights', and the MPU will
also have to be 'enabled' by writing to 'enable' bit in a given
register.
Once the 'regions' have been defined with required 'access rights'
and the MPU enabled, each transaction from the processor is checked
against the MPU configuration. If the transaction's attribute
matches the 'access rights' of the region, the transaction is
successful, and is produced at the processor's interface, in case of
a mismatch, an exception is generated, and the processor jumps to
the exceptional handler.
MPU is a very powerful component for the programmer. It is used
typically to ensure the system security, as it can disallow the user
mode software (i.e. the software running in unprivileged mode) to
access the critical regions of the memory.
One of the other subtle use of the MPU is to differentiate between
different processes running on the processor. Using the MPU, the
user may give different 'access rights' to different processes
running in the user mode (unprivileged mode). This can help
implement what is called Software
Multi-Tenancy. This is usually done by programming the MPU
just before a new 'Thread' is started on the processor. The
programmer will define specific access rights for each processes
using the MPU programming just before a new 'Thread' or 'Process' is
started on the processor, so that each of these 'threads' have a
different vision of the memory space. Each of this process can then
may have exclusive different regions of memory to their use.
What if you dont use MPU?
Use of MPU is optional. If you dont use the MPU, you still have the
distinction between privilege/unprivileged
accesses from the processor, available to be used. And that is
pretty much that you will be able to do without MPUs, with the Arm
Cortex-M processors which offer privilege/unprivileged
mode of operation, i.e. separation of privileged and unprivileged
access. For certain use-cases, this distinction may just be enough
for your system to provide a basic level of security.
Example use of MPU:
This section provides an example of how to use an MPU. It wont
provide exact write words to MPU registers, but it will give a
detailed explanation of what needs to be done for the MPU to be
effective.
Step 1: Poke the MPU_TYPE register @ 0xE000_ED90 to find out the
number of regions. Bits [15:8] = 0x08 means 8 regions, Bits [15:8] =
0x0 means No MPU, i.e. 0 regions.
Now let us say that you want to define a region of memory from
0x2000_0000 to 0x2001_0000 (64 KB) with the following 'attributes'
- The region is Read-Only
- The region is only be meant for the privileged code.
- The region is Execute-Never, that is it is 'data' region, and
execution of code from this region is not allowed.
Step 2: Enable the MPU by writing to MPU CONTROL Register Bit [0].
Step 3: Setup MPU Region Number Register to indicate which(from
among 8) region you are about to configure.
Step 4: Setup MPU Region using MPU Region/Base Address register.
This will provide the region's Base Address
Step 5: Setup Region size and Attributes using MPU Region Attribute
& Size Register.
-> Bit[28] -> 1 (indicating Execute Never)
-> Bits[26:24] are called AP -> Set these to '101'
indicating 'Read-Only' for Privilege access, and 'No access' for
User/unprivileged access
-> Bits[5:1] -> '01111' -> 64 KB region
-> Bit [0] -> '1'. Enable region.
The above is just some of the steps for making the user understand
the MPU programming theory. IN practice, while writing code, there
may be some more bits needed to be written. A full programing
sequence is being developed, and will be uploaded shortly.
<=
PREV : ARM Cortex-M TrustZone
Next => ARM
Cortex-M SAU (Still Under Construction)
Click Here to Make Comments or ask Questions
SITE HOME