Why certain memory addresses are being accessed multiple times when using Load Multiple or Store Multiple instructions?
Applies to: Cortex-M3, Cortex-M4, Cortex-M7
This Knowledge Article applies to software developers writing code to processors implementing the ARMv7-M architecture, such as Cortex-M3, Cortex-M4 or Cortex-M7.
The user might observe that if a Load Multiple or Store Multiple instruction gets interrupted, in certain cases after returning from the interrupt the processor loads or stores memory addresses that have been already loaded or stored before taking the interrupt.
In case of accessing a Device or Strongly-ordered memory region, this is undesirable and potentially causes erroneous behaviour.
To improve interrupt response and increase processing throughput, the ARMv7-M architecture allows the processor to take an interrupt during the execution of a Load Multiple or Store Multiple instruction, and can either continue or restart the execution of the instruction after returning from the interrupt. The behaviour detailed in the Scenario can occur in certain cases when the Load Multiple or Store Multiple instruction continued after an interrupt, and occurs each time if the Load Multiple or Store Multiple instruction gets restarted.
During the interrupt processing, the Execution Program Status Register's ICI/IT bits hold the continuation state, which makes the processor able to continue the Load Multiple or Store Multiple instruction from the point when it was interrupted. However, the following limitations apply:
- The LDRD, STRD instructions are defined as non-exception-continuable by the ARMv7-M architecture, therefore these instruction are always restarted if interrupted.
- If the floating-point extension is implemented and using floating-point Load Multiple or Store Multiple instructions, the ICI/IT bits encode the number of the lowest-numbered doubleword floating-point extension register that was not completely loaded or stored before taking the exception. This means that if the lower 32 bits of the doubleword register have already been loaded or stored before the interrupt, the same 32 bits are getting accessed again after the interrupt, even though the processor successfully continues the instruction using the ICI/IT bits.
- If the processor executes an IT block, the ICI/IT bits are used to hold the If-Then execution state instead of the continuation state, which prevents the processor from continuing any interrupted Load Multiple or Store Multiple instructions within an IT block.
- If the exception interrupting the Load Multiple or Store Multiple instruction is a a BusFault or MemManage fault, the processor abandons the instruction, and restarts it from the beginning upon returning from the handler.
- If the PC is in the register list of the Load Multiple instruction, it can be continued upon returning from an interrupt. However, as a Load Multiple instruction with the PC in the register list is defined as unordered (i.e. the registers can be loaded in a different order to that implied by the register list), continuing such instruction can result in the same memory location being accessed twice.
- If the base register is in the register list of the Load Multiple instruction, and the interrupt is taken before the base register has been loaded, the Load Multiple instruction can be continued correctly. However, if the interrupt is taken at the point when the base register has already been loaded, after returning from the interrupt the processor loads the base register again.
To avoid the above explained error-prone behaviour, the following rules should be held when accessing Device or Strongly-ordered memory with Load Multiple or Store Multiple instruction:
- Do not use LDRD, STRD instructions.
- If the floating-point extension is implemented, do not use VLDM, VSTM, VPOP or VPUSH instructions.
- Do not use any Load Multiple or Store Multiple instructions in an IT block.
- Do not use Load Multiple instructions with the base register or the PC in the register list.
Rate this article
Disagree? Move your mouse over the bar and click