The Cortex-M0 and Cortex-M0+ are two microcontroller cores from ARM aimed at low-cost and low-power embedded applications. While they share architectural similarities, there are some key differences that can impact code compatibility when migrating between the two cores.
Introduction to Cortex-M0 and M0+
The Cortex-M0 is a 32-bit ARM processor core launched in 2009 for microcontroller applications. It is optimized for low-cost and low-power embedded systems with memory sizes between 16-256KB. The M0 has a 3-stage pipeline, no cache, and supports the ARMv6-M instruction set architecture.
The Cortex-M0+ launched in 2012 builds on the M0 design with microarchitectural enhancements for better performance and power efficiency. It adds a single-cycle I/O port, more debugging features, and support for higher clock frequencies up to 50 MHz. The M0+ is upwards compatible with the M0 instruction set.
While the M0 and M0+ are highly compatible in terms of their instruction set architecture, there are some microarchitectural differences that can impact performance, timing, and ultimately code portability between the two cores:
- The M0+ has a third execution stage in its pipeline for better performance. This can change timings for code execution sequences.
- The M0+ includes architectural updates like tightly-integrated sleep modes, single-cycle I/O, and memory-mapped debug components that are not present on the M0.
- The M0+ supports higher max clock frequencies up to 50MHz versus 24MHz on the M0. This can impact timings and delays.
- The M0+ includes additional debugging features like breakpoint registers, data watchpoint registers, and Micro Trace Buffer (MTB) for more robust debugging.
- The M0+ has updates to system control block registers, SysTick timer, and NVIC modules compared to the M0.
These microarchitectural differences mean that while application code will be compatible, any timing-sensitive code or direct hardware access will need to be reviewed for portability across cores.
Instruction Set Architecture Compatibility
From an instruction set architecture (ISA) standpoint, the Cortex-M0+ is fully upwards compatible with the Cortex-M0 ISA. All M0 instructions are supported in the M0+ with the same encoding, behavior, and effects on the system state.
Key areas of ISA compatibility include:
- Support for the Thumb-2 instruction set used in ARMv6-M
- Compatible 32-bit registers, exceptions, interrupts, and processor modes
- Fully compatible memory model with bit-banding support
- Uses the same Supervisor Call (SVC) interface for system calls
- Same mechanisms for managing stacks, subroutines, and function calls
This upwards compatibility enables easy porting of application code between the two cores. Developers can re-use their firmware codebases across M0 and M0+ based microcontrollers with minimal changes.
Key Code Compatibility Issues
While application code will port easily between the M0 and M0+ cores, developers should be aware of these possible issues impacting timing or hardware interaction code:
- Code relying on specific timings or number of cycles to execute may need to be tweaked for the different pipeline length.
- Any direct manipulation of or dependence on core registers like the program status register values may require checking for compatibility as some bits differ between M0 and M0+.
- Low-power mode management code will need adaptation since the M0+ has additional sleep modes not present on the M0.
- Direct access to certain system control registers will need to be checked for addressing differences or feature availability.
- Debugging code and exception handlers may need to be tailored to account for differences in breakpoint registers and other debugging features.
- Code utilizing Systick timer, SysTick, or NVIC modules will need to adapt to the new implementations of these components.
In general, any code that relies on specific instruction timings, directly manipulates CPU registers or memory-mapped system control registers, or tries to access hardware modules or debugging capabilities will require thorough validation when moving between M0 and M0+ cores.
Porting Code from M0 to M0+
For porting code from Cortex-M0 to M0+, here are some best practices to enable a smooth transition:
- Recompile all code using the M0+ toolchain – this will catch some compatibility issues with new compiler versions.
- Load the M0+ startup code and CMSIS libraries – provides necessary support functions.
- Adapt any timing dependent code to account for M0+ pipeline differences.
- Validate any direct manipulation of CPU registers or memory-mapped registers.
- Update low-power mode handling for new M0+ sleep modes.
- Migrate any debugging code and exception handlers to utilize M0+ features.
- Verify any use of Systick timers, SysTick, NVIC, and other hardware modules.
- Consider simplifying HAL and hardware abstraction layers to improve portability.
- Perform extensive testing on actual M0+ hardware to validate timing and peripherals.
With upfront validation of the key compatibility issues, most code can be reused on the M0+ with minimal changes. This enables developers to easily leverage the benefits of the M0+ like better performance and power savings.
The Cortex-M0 and M0+ deliver highly compatible 32-bit performance for small embedded applications. While their microarchitectures differ, the instruction set architecture is upwards compatible. This enables easy firmware migration with validation for timing-sensitive and hardware-specific code.
Overall, the M0+ builds on the M0 with an efficient 3-stage pipeline, improved power management, and enhanced debugging. With some incremental firmware adaptation, developers can easily move to M0+ and take advantage of its benefits while re-using most existing code.