In the first of a three part series, Joseph Yiu, author of “The definitive guide to the ARM Cortex-M0,” provides some basic guidelines for porting your code base from other 8/16 bit MCUs to ARM and between various ARM processors starting here with the ARM 7TDMI and Cortex-M0.
As software reuse becomes more common, software porting is becoming a more common task or embedded software developers. In this three part series, we will look into differences between various common ARM processors for microcontrollers and what areas in a program need to be modified when porting software between them.
This series will conclude with issues relating to the software porting of software from 8-bit and 16-bit architectures.
Some of the ARM processors used in a range of microcontroller products is shown in Table 21.1 below.
Table 21.1: Commonly Used ARM Processors on MCUs
The main differences between the Cortex-M processors are illustrated in Figure 21.1. In this series we will cover the detailed differences between the Cortex-M0 and some of these processors.
Figure 21.1: The Cortex-M processor family(To view larger image, click here).
Differences between the ARM7TDMl and the Cortex-M0
There are a large number of differences between the ARM7TDMI and the Cortex-M0.
Operation Mode. The ARM7TDMI has a number of operation modes, whereas the Cortex-M0 only has two modes, as described in Table 21.2 below.
Table 21.2: ARM7TDM1/Cortex-M0 Operation Modes Comparison
Some of the exception models from the ARM7TDMI are combined in Handler mode in the Cortex-M0 with different exception types. Consider the example presented in Table 21.3 below. The reduction of operation modes simplifies Cortex-M0 programming.
Table 21.3: Exception Comparison between the ARM7TDMl and the Cortex-M0
Registers. The ARM7TDMI has a register bank with banked registers based on current operation mode. In Cortex-M0, only the SP is banked (Figure 21.2 below). And in most simple applications without an OS, only the MSP is required.
There are some differences between the CPSR (Current Program Status Register) in the ARM7TDMl and the xPSR in the Cortex-M0. For instance, the mode bits in CPSR are removed, replaced by IPSR, and interrupt masking bit 1-bit is replaced by the PRIMASK register, which is separate from the xPSR.
Figure 21.2. Register bank differences between ARM7TDMI and Cortex-M0 (To view larger image click here).
Despite the differences between the register banks, the programmer’s model or RO to R15 remains the same. As a result, Thumb instruction codes on the ARM7TDMI can be reused on the Cortex-M0, simplifying software porting.
Instruction Set. The ARM7TDMI supports the ARM instructions (32-bit) and Thumb instructions (16-bit) in ARM architecture v4T. The Cortex-M0 supports Thumb instructions in ARMv6-M, which is a superset of the Thumb instructions supported by the ARM7TDMI. However, the Cortex-M0 does not support ARM instructions. Therefore, applications for the ARM7TDMI must be modified when porting to Cortex-M0.
Interrupts. The ARM7TDMI supports an IRQ interrupt input and a Fast Interrupt (FIQ) input. Normally a separate interrupt controller is required in an ARM7TDMI microcontroller to allow multiple interrupt sources to share the IRQ and FIQ inputs.
Because the FIQ has more banked registers and its vector is located at the end of the vector table, it can work faster by reducing the register stacking required, and the FIQ handler can be placed at the end of vector table to avoid branch penalty.
Unlike the ARM7TDMI, the Cortex-M0 has a built-in interrupt controller called NVIC with up to 32 interrupt inputs. Each interrupt can be programmed at one of the four available priority levels. There is no need to separate interrupts into IRQ and FIQ, because the stacking of registers is handled automatically by hardware.
In addition, the vector table in the Cortex-M0 stores the starting address of each interrupt service routine, while in the ARM7TDMI the vector table holds instructions (usually branch instructions that branch to interrupt service routines).
When the ARM7TDMI receives an interrupt request, the interrupt service routine starts in ARM state (using ARM instruction). Additional assembly wrapper code is also required to support nested interrupts. In the Cortex-M0, there is no need to use assembly wrappers for normal interrupt processing.