The LDR (LoaD Register) instructions in ARM Cortex-M are used to load data from memory into a register. The Cortex-M processors have several different addressing modes that can be used with the LDR instruction to specify the memory location to load from.
LDR Basics
The basic syntax of the LDR instruction is: LDR Rd, [Rn, #offset]
Where:
- Rd = Destination register to load data into
- Rn = Base register containing the memory address
- offset = An optional offset from the base address in Rn
This loads a 32-bit word from the memory location [Rn + offset] into Rd. Some examples: LDR R1, [R2, #8] ; Load from address in R2 + 8 into R1 LDR R5, [R3] ; Load from address in R3 into R5
Addressing Modes
There are several different addressing modes supported by the Cortex-M LDR instruction:
Offset Addressing
This uses an offset from a base register: LDR R1, [R2, #8]
Loads from the address calculated as R2 + 8. The offset can be positive or negative.
Pre-Indexed Addressing
The base register is updated with the offset before the load: LDR R1, [R2, #8]!
Loads from R2, then R2 is updated to R2 + 8 after the load.
Post-Indexed Addressing
The base register is updated with the offset after the load: LDR R1, [R2], #8
Loads from R2, then R2 is updated to R2 + 8 after the load.
Literal Addressing
A PC-relative literal address encoded in the instruction: LDR R1, [PC, #16]
Loads from the address PC + 16, where PC is the current program counter value.
Load Types
The Cortex-M LDR instruction supports several different data types to load:
- LDR – Load 32-bit word
- LDRB – Load byte
- LDRH – Load 16-bit halfword
- LDRSB – Load and sign extend byte to 32-bits
- LDRSH – Load and sign extend halfword to 32-bits
The appropriate load type must be used depending on the data size at the memory address.
Memory Ordering
The Cortex-M pipeline allows for instructions to be executed out-of-order for performance. However, memory operations like LDR have ordering requirements.
By default, memory operations appear to execute in program order. The LDR reads from memory will not overtake prior STR writes to memory.
Explicit memory barriers can also be inserted if needed using the DSB instruction.
Atomicity
The LDR and STR instructions are atomic for memory regions marked as Normal memory in the MPU. This means the load or store is guaranteed to complete indivisibly without interruption.
For device memory marked as Shareable, atomicity is not guaranteed and interrupts could occur in the middle of an LDR or STR instruction.
Alignment
For performance reasons, it is recommended to align word and halfword reads to addresses divisible by 4 or 2 respectively. However, all Cortex-M LDR instructions can load from any byte aligned address regardless of alignment.
Unaligned LDRs are supported in hardware but take more cycles to complete.
Debug
The LDR instruction can be used to load fromaddresses containing breakpoints or watchpoints. This will cause a debug halt if enabled.
To avoid this, LDREX or LDRT instructions can be used instead for debug-safe loads.
Exceptions
The following exceptions may occur on an LDR instruction:
- MemManage fault – On MPU violation
- Bus fault – On external bus error
- Usage fault – On unaligned access without enable
- Debug halt – On watchpoint match
Priority is given to debug halts and MemManage faults over other faults.
Context Switching
To perform context switches safely in an RTOS:
- Use LDREX/STREX instructions to load from shared resources
- Disable interrupts before the switch
- Store processor registers to stack
- Load new context from stack
- Enable interrupts
This prevents preemption during critical sections around context switches.
Power Management
The LDR instruction does not directly impact processor power states. However, it can be used to load values that trigger power mode changes. For example: LDR R1, [R2] ; Load mode value CMP R1, #LOW ; Compare to threshold BEQ SetLowMode ; If low, switch to low power
The WFI instruction is commonly used after this to wait for an interrupt before restarting execution.
Instruction Timing
The cycles required for an LDR instruction depend on:
- Load width – byte, halfword, word
- Addressing mode
- Alignment
- Wait states configured for the memory region
At maximum speed with zero wait states, word aligned LDR takes:
- 1 cycle for offset addressing
- 2 cycles for pre/post-indexed addressing
- 3 cycles for literal addressing
Unaligned LDR word accesses take additional cycles depending on how unaligned they are.
Consult the Cortex-M Technical Reference Manual for full details on instruction timing.
Usage in Code
Here are some examples of using LDR instructions in Cortex-M code: // Load stack pointer from vector table LDR R0, =0xE000ED08 LDR SP, [R0] // Load PC-relative constant LDR R1, =MY_CONSTANT // Load from peripheral register LDR R2, [RCC_BASE, #CLK_CTRL] // Load byte value LDRB R3, [R4, #8] // Load with post-indexed writeback LDR R5, [R6], #16 // Load and sign extend halfword LDRSH R7, [R8, #2]
Summary
The key points about LDR instructions on Cortex-M are:
- Used to load data from memory into registers
- Several addressing modes supported
- Different load widths for bytes, halfwords and words
- Guaranteed single-copy atomicity in Normal memory
- Unaligned accesses supported but slower
- Ordering, exceptions, and debug capabilities
Consult the reference manual for full details on cycle timings, exceptions, and other behaviors not covered here.
The LDR instruction is a versatile load operation essential for working with data in memory in Cortex-M software.