The STR (store register) instructions in Arm Cortex-M processors are used to store data from a register to memory. They allow transferring a word (32 bits) or halfword (16 bits) from a register to a memory location. STR instructions are an essential part of programming on Cortex-M as they enable variables and data to be stored in memory for later use.
STR Format
The basic format of the STR instruction is: STR{condition} {Rt}, [Rn, #offset]
Where:
- STR is the mnemonic for the store register instruction
- {condition} is an optional condition code like EQ, NE, etc.
- {Rt} is the source register containing the data to store
- {Rn} is the base register containing the start address
- {offset} is an optional offset from the base register
This stores the word in source register Rt to the memory address calculated as [Rn + offset].
STR Examples
Here are some examples of STR instructions: STR R1, [R2] // Store R1 to address contained in R2 STR R5, [R3, #8] // Store R5 to address in R3 offset by 8 bytes STRNE R0, [R1, R4] // Store R0 to R1+R4 only if Z flag is not set
Store Register Halfword (STRH)
To store a halfword (16 bits) use the STRH instruction. The syntax is: STRH{condition} Rt, [Rn, #offset]
This will zero-extend the contents of Rt and store the lower 16 bits to the memory address. STRH R1, [R2, #2] // Store lower 16 bits of R1 to address in R2 offset by 2
Addressing Modes
STR supports several addressing modes to calculate the memory address:
- Offset – Add offset to base register Rn
- Pre-indexed – Add offset to Rn, store data, then update Rn
- Post-indexed – Store data to Rn, then add offset to Rn
STR R1, [R2, #8]! // Pre-indexed addressing STR R1, [R2], #8 // Post-indexed addressing
Store Multiple Registers
To store multiple registers to memory use the STM (store multiple) instruction: STM{condition} Rn{!}, {Rlist}{^}
This stores the registers in Rlist to memory starting at the address in Rn. The ! indicates pre-indexed addressing. The ^ indicates packing the registers starting from the lowest number. STM R5!, {R1,R3,R5} // Store R1, R3, R5 and update R5 STMIB R6, {R2-R8}^ // Store R2-R8 packed to address in R6
Store Exclusive
The STREX instruction performs an exclusive store to memory. This is used along with LDREX for atomic read-modify-write operations: STREX{condition} Rd, Rt, [Rn]
STREX stores the value in Rt to memory if no other processor has accessed the location since the LDREX. It returns 0 on success and non-zero on failure.
Conditional Execution
STR instructions can be conditionally executed based on the status flags: STRNE R1, [R2] // Store if Z flag is not set STRMI R3, [R4] // Store if N flag is set
This avoids storing the data if the condition is false.
Memory Ordering
By default, STR has relaxed memory ordering semantics. This means other processors may observe the effects of the STR out of order. To enforce stricter ordering: STR R1, [R2, #8] // Relaxed (default) STR R1, [R2, #8] // Acquire semantics STR R1, [R2, #8] // Release semantics STR R1, [R2, #8] // Ordered semantics
Acquire semantics ensure any loads after the STR observe its effect. Release semantics ensure any loads before the STR complete first. Ordered ensures both acquire and release.
Usage in C
In C code, STR instructions are generated by the compiler when storing variables to memory: int x = 10; // x stored to memory with STR int arr[10]; arr[5] = x; // STR to store x to array element
The compiler handles selecting registers, offsets and addressing modes automatically.
Interaction with Memory
STR interacts with the processor’s memory system in various ways:
- Writes data to cache and memory system
- May cause cache miss and main memory access
- Can invalidate cache lines
- Causes memory barriers depending on ordering
- Executes only when privileges allow access
This affects performance and coordination between cores. Optimizing memory access patterns is key to performance.
Exceptions
STR can cause the following exceptions:
- MemManage fault – On MPU or MMU configuration errors
- Bus fault – On external memory errors
- Alignment fault – Unaligned halfword/word access
- Usage fault – Coprocessor access, divide by zero
These are handled by the processor’s exception mechanism. The fault status registers indicate the source and type of fault.
Context Switching
STR is commonly used when context switching between threads or processes: // Save process registers STM SP!, {R4-R11,LR} // Restore process registers LDM SP!, {R4-R11,LR}
This allows the state of a process to be saved and restored when switching tasks.
Interacting with Peripherals
STR can be used to interact with peripheral devices: // Store data to be transmitted over UART STR R1, [UART_TXDATA] // Store value to control PWM peripheral STR R2, [PWM_DUTYCYCLE]
Device driver code uses STR extensively to configure peripherals.
Debugging
When debugging:
- STR appears in disassembly listing
- Registers and memory can be inspected
- Memory accesses can be watched
- Breakpoints can be set on STR instructions
This helps analyze problems with incorrect data storage.
Performance
STR performance depends on:
- Memory technology (flash vs RAM)
- Memory bus width (8-bit vs 32-bit)
- Use of cache
- Access patterns and order
- Memory contention from other operations
Measuring actual runtime STR performance helps optimize memory access.
Code Density
On Cortex-M, STR takes 2-4 bytes depending on addressing mode. This affects code size: STR R1, [R2] // 2 bytes STR R1, [R2, #10] // 4 bytes
Pre-indexed and post-indexed modes take 4 bytes. Offset mode takes 2 bytes. Compact code optimizes frequent STRs.
Power Consumption
Factors affecting STR power consumption:
- Memory technology
- Bus utilization
- Uncached accesses
- Access order and locality
- Wait states on memory
Memory optimizations and flash accelerators reduce STR energy per access.
Alternatives
Other instructions with similar functionality:
- STRB – Store byte
- STRD – Store dual word
- PUSH – Store to stack
- STM – Store multiple
STR has tradeoffs vs:
- LDR – Loads memory into register
- MOV – Copies data between registers
Which is optimal depends on access patterns.
Summary
Key points about STR in Arm Cortex-M:
- Fundamental instruction to store registers to memory
- Supports word, halfword, and byte accesses
- Multiple addressing modes to calculate target address
- Can conditionally execute based on status flags
- Affects performance, code density, and power
- Used heavily by compilers and for interacting with memory and peripherals
Understanding STR is essential to programming ARM Cortex-M efficiently.