*
*Home|Chinese|Japanese*About ARM|Forums|Events|News|Employment|Contact Us|Investors*
dotted rule
*ARM - the architecture for the digital worldARM - the architecture for the digital world
search
*
*
***
*MARKETS:PRODUCTS & SOLUTIONS:CONNECTED COMMUNITY:TECHNICAL SUPPORT:DOCUMENTATION*
*
technical support
*
*
****
*.Technical Support
*
*
*>>Home Page*
*
*.Obtaining Support*
*
*.FAQs*
*
**Development Tool FAQs*
**IP FAQs*
**Embedded Software FAQs*
**Artisan Physical IP FAQs (Login Required)*
*
*.Downloads*
*
*.Documentation*
*
*.Training*
*
*.Where To Buy*
*
*.Keil MCU Tools*
*
*.What's New*
*
*.ARM Newsgroups*
*
*.Active Assist On-site Services*
*
*
*
technical support FAQsask ARM*
*

Technical Support Search
*     (Advanced Search)
  FAQs   Documentation   Downloads   Forums

*

 
downarrowCan the compiler generate LDRD/STRD instructions to access 64-bit peripherals?
Applies to: Assembler, Compilers, Linker, RealView Development Suite (RVDS) 3.0, RealView Development Suite (RVDS) 3.1, RealView Development Suite (RVDS) 3.1 Professional

Architecture v5TE and later processors provide LDRD and STRD instructions to load/store 64-bit data, e.g. to access 64-bit peripherals.  These behave similarly to LDM/STM of two registers.

On processors with 32-bit buses (such as ARM926EJ-S), LDRD/STRD (and LDM/STM of two regs) access data using two word-sized bus accesses, which may potentially be interrupted by another bus master, so cannot be guaranteed atomic. On processors with 64-bit buses (such as ARM11), these instructions are atomic.

Unfortunately, there is an issue with the RVCT 3.x compilers whereby they are not always able to generate an LDRD/STRD (or LDM/STM) instruction when expected, e.g., accessing a 64-bit peripheral.

For example, the following piece of code stores the 64-bit value 0x0123456789ABCDEF to address 0xA0000000:

void perip_64bitaccess(void)
{
  unsigned long long value = 0x0123456789ABCDEF;
  *((volatile unsigned long long*) (0xA0000000)) = value;
}

You might expect this code built with the following command line options to generate a double word store (STRD) instruction or a store multiple (STM) instruction:

armcc -c foo.c --cpu 6 -o foo.o
fromelf -c foo.o

However, at present, the 3.x compilers may generate two STR instructions instead.

To workaround this issue with RVCT 3.0 you could simply write the LDRD/STRD instructions in assembly language and build the code using the ARM assembler. The RVCT 3.0 linker is able to inline such small instruction sequences.   However, unfortunately the RVCT 3.1 linker is unable to inline LDRD/STRD instructions, but can inline the equivalent LDM/STM of two registers.

A workaround for both RVCT 3.x compilers is to write LDM/STM (of two reg) instructions in embedded assembler and pass the linker command line option --inline to ensure that the embedded assembly function is inlined by the linker, for example:

__asm void stm_llout(unsigned long long* addr, unsigned long long value)
{
  STM r0, {r2,r3}
  BX LR
}

__asm unsigned long long ldm_llin(unsigned long long* addr)
{
  LDM r0, {r0,r1}
  BX LR
}

unsigned long long perip_64bitaccess(void)
{
  unsigned long long ullvalue = ldm_llin((unsigned long long*)0x40004000);
  stm_llout((unsigned long long*)0x40000000, ullvalue);
  return ullvalue;
}

built with:

armcc -c foo.c --cpu 6 -o foo.o
armlink foo.o --inline -o foo.axf
fromelf -c foo.axf

generates inlined LDM/STM instructions. 






back to top

*
**
*4 dots*Other ARM Websites
*
shadow *LEGAL STATEMENTshadow