Accessing 64-bit peripherals using Cortex-M processors
Article ID: 103489550
Published date: 19 Oct 2017
Last updated: -
Applies to: Cortex-M
How do you access 64-bit peripherals using Cortex-M processors?
Why are 64-bit peripherals necessary?
In many cases, it is essential to have 64-bit peripherals. For example, a system might require some timers that need to run for a long time. In such cases, the peripheral design must be able to cope with the nature of the bus. Therefore it needs to capture the information to ensure the processor obtains a consistent value. This is not a limitation of Arm systems. Many 8-bit microcontrollers use 16-bit timers and the same issue exists.
Access to 64-bit peripherals
If a pointer to a 64-bit address is marked with the volatile keyword, it guarantees that the C/C++ compiler does not optimize away any code that accesses the location that the pointer points to. However, it does not guarantee the type of instruction that a compiler uses to access the address. A compiler might generate an LDM/ STM or an LDRD/STRD to access the 64-bit peripheral. The compiler might also generate two LDR/ STR instructions to access the 64-bit peripheral, although this is not atomic for any Cortex-M system that uses 32-bit buses.
On Cortex-M0, Cortex-M0+ and Cortex-M1 processors, LDRD/STRD instructions are unavailable, and unless interrupts are disabled, software should not access Device memory using load and store multiple instructions. This is because these operations might be interrupted and restarted.
On Cortex-M3, Cortex-M4, and Cortex-M7 processors, software can access Device memory using load and store multiple instructions if the Interruptible-Continuable Instruction (ICI) field in the APSR is available1. This is because it means that the processor will not repeat the same transfer.
Handling 64-bit accesses
Like Cortex-M0, Cortex-M0+ and Cortex-M1 processors, the Cortex-M3 and Cortex-M4 processors are connected to the memory system through an AHB-Lite interface. Even if the processor is able to prevent 64-bit accesses being restarted, the bus fabric will still break up the accesses because the 32-bit AHB interface only supports atomicity for 8-bit, 16-bit, or 32-bit transfers. Therefore the system needs to provide some other scheme, such as 'doubleword buffering', to handle the 64-bit accesses atomically:
For a 64-bit read operation, the peripheral's programmers' model needs to be designed specially to capture the whole 64-bit value. It needs to provide some way to capture and maintain the second captured half of the 64-bit value, in case the program is interrupted.
For a 64-bit write operation, the peripheral should buffer the data from the first transfer and load the whole 64-bit value into the functional register only when the second word is received. Otherwise the peripheral register will receive each of the 32-bit values at different times, which might result in undesirable behavior.
For both 64-bit reads and writes, the peripheral needs to cope with the situation where the first read or write could repeat because of an interrupt. For example, this might happen when using STRD, or when using STM in an IT block, which makes the ICI field unavailable.
Although the Cortex-M7 processor supports some 64-bit transfers through its AXI bus interface, all accesses that use LDM, STM, LDRD, or STRD instructions to Strongly-ordered or Device memory occur as 32-bit transfers. Therefore, the same design implications described above for Cortex-M3 and Cortex-M4 processors also apply to Cortex-M7 processors.
1 The ICI field is unavailable when LDM/STM:
executes inside an IT block.
loads the same register as the base register.
loads the Program Counter.
Refer to the chapter titled 'Atomicity in the ARM architecture' from the ARMv6-M and ARMv7-M Reference Manual.