The Cortex MPU
I recently wrote about Ambiq’s new Cortex M4F MCU, which is made using transistors operating in the subthreshold region. Cortex licensees can add ARM’s optional memory protection unit (MPU), and indeed Ambiq chose to do so. In that piece I glibly wondered why they bothered.
Of course they bothered. The real question is why don’t more licensees do so?
Old-timers remember the original 8088/86 architecture. It was an early 16 bit processor. In an attempt to keep some compatibility with 8 bitters, Intel maintained 16-bit index registers. But few users wanted to be stuck with no more than 64 KB of memory, so the company added four “segment” registers. Memory addresses were modified by adding the appropriate segment register, shifted left four bits, to the base address. This expanded the address space to a whopping 1 MB, thought at the time to be more than anyone needed. (The Bill Gates quote that no one needs more than 640 KB is apparently apocryphal).
(As an aside, when I was a student at the University of Maryland in the early 70s the school had a Univac 1108 mainframe. That monster had 1 million 36-bit words of memory… and the memory box cost $1 million, back when a megabuck was a lot of money. The 8086 came out just a handful of years later, in 1978, so a 1 MB limitation was not as shortsighted as may seem to us today.)
The 8086 segmentation worked but was awkward and a constant pain to use. With the introduction of the 386, a true 32 bitter, you’d think Intel would have gone to a flat 4 GB address space. They didn’t, and instead of four segment registers, now the CPU had thousands. How developers roared! In fact, at the very first ESC Andy Grove took questions after his keynote. One manners-challenged attendee rudely asked him why they made such a stupid decision. Groves seemed stunned.
In fact, Intel did the right thing. Though segment registers were now as plentiful as software bugs, they offered exquisitely-fine-grained control over memory accesses. Smart developers divided programs into tasks and other partitions, and used the segment registers to throw exceptions when a program or a task tried to access memory outside of its legal area. With a flat address space a crashing program took the entire machine down. With segmentation it crashed, but other programs kept on going (mostly, as early Windows users learned to their constant annoyance).
The Cortex MPU is much simpler than Intel’s protected mode components. But it does let you partition your code into 8 distinct regions (and each of those can be divided into subregions). Every region can have an access permission attribute (no accesses allowed, read-only, or read/write). Those can be further refined by fetch or no-fetch guards.
With an MPU the developer can have the hardware monitor every memory transaction and throw an exception when something silly happens. Like a wild pointer dereference. A program crash. A bug. All of these are likely to try to access a random spot in memory, and given the ARM’s huge address space, odds are good the access will be outside of the limited memory inside an MCU. The MPU will fire off an exception; a little bit of code can capture that and leave debugging crumbs behind. Or reboot and start over long before a watchdog would fire. Or maybe restart the offending task.
Global variables are a pox on our code, yet are horrifyingly common. There were (are?) over 11,000 in the Camry’s engine control software, which cost the company a fortune in fines and litigation. RTOSes provide safe ways to avoid globals. Mailboxes, queues and the like pass data safely between tasks. Today, some RTOSes support the Cortex MPU. These messaging resources allow intertask communication even when the tasks are separated by MPU mapping. FreeRTOS is one example. Micrium’s uC/OS is another. And uC/OS will shortly be free for “makers” – very small companies and individuals.
The real question isn’t “why did Ambiq include an MPU?” It’s “why would a Cortex vendor NOT include an MPU on those devices that can support it?” (The M0 and M0+ can’t handle an MPU).
Here are some useful resources:
- ARM Application Note 179 is ARM’s take on various aspects of programming the Cortex M3. It has useful info about the MPU but is light on details.
- TI’s Usage of MPU Subregions on the TI Hercules™ ARM® Safety MCUs has good information, and code, about using the MPU’s subregions. I’ve been able to find little of practical use in ARM’s documentation about subregions, so TI’s paper is an important contribution.
- Feabhas has a nice app note about setting up the MPU, with code.
- Joseph Liu’s book The Definitive Guide to the ARM Cortex-M3 has good code examples.
So, if your MCU has an MPU, why wouldn’t you use it in your next design?
Jack G. Ganssle is a lecturer and consultant on embedded development issues. He conducts seminars on embedded systems and helps companies with their embedded challenges, and works as an expert witness on embedded issues. Contact him at firstname.lastname@example.org. His website is www.ganssle.com.