9

I am porting some software from the gcc-toolchain to the armcc-toolchain (processor stays the same (Cortex-A9)). In the C-code memcpy is used. armcc replaces a call to memcpy by a call to __aeabi_memcpy. The FAQ sais the following about __aeabi_memcpy (How do the ARM Compilers handle memcpy()?):

In many cases, when compiling calls to memcpy(), the ARM C compiler will generate calls to specialized, optimised, library functions instead. Since RVCT 2.1, these specialized functions are part of the ABI for the ARM architecture (AEABI), and include:

__aeabi_memcpy
This function is the same as ANSI C memcpy, except that the return value is void.

But in contrast to gcc, where a call to memcpy works fine in all of my cases, with armcc the call to memcpy respectivly __aeabi_memcpy continuously produces alignment exceptions. Meanwhile I found out, that a call to memcpy can handle calls where source and destination address are not 4-byte aligned, but only if they are both not 4-byte aligned. For example:

    volatile uint32_t len = 10;
    uint8_t* src = (uint8_t*)0x06000002;         // 2-byte aligned
    uint8_t* dst = (uint8_t*)(0x06000002 + 20);  // 2-byte aligned
    memcpy(dst, src, len);

will work. But for example:

    volatile uint32_t len = 10;
    uint8_t* src = (uint8_t*)0x06000002;         // 2-byte aligned
    uint8_t* dst = (uint8_t*)(0x06000002 + 22);  // 4-byte aligned
    memcpy(dst, src, len);

will cause an alignment exception. SInce I am using pointers of type uint8_t* I explicitly tell the compiler that the addresses can have any alignment. But obviously this __aeabi_memcpy can not handle every combination of alignments. How can I solve this problem (preferably without changing all calls to memcpy in the existing code with a user-specific version of memcpy)? Thanks for help.

user3035952
  • 301
  • 5
  • 12
  • Are you sure your code is not producing any undefined b? Can you reproduce this error with a minimal valid example? – this Jul 22 '14 at 09:22
  • Well, I think the two examples are minimal? :D I used those two examples. The first one works fine, the second one causes an alignment exception. – user3035952 Jul 22 '14 at 09:26
  • I also looked at the disassemly of __aeabi_memcpy and I also found the part that causes this problem. But I don't know why it is implemented this way neither how to fix it up for my code ... – user3035952 Jul 22 '14 at 09:28
  • You can always write your own memcpy that copies using char. – this Jul 22 '14 at 09:29
  • Well, if you don't want to change your code, then the only option is to look into the compilation flags in the project settings of your ARM project, and change them. Alternatively, I would guess that there is a special `#pragma` that you can add prior to every call to `memcpy`. – barak manos Jul 22 '14 at 09:29
  • BTW, you can probably fix it by replacing `memcpy` with `memmove` (if you don't mind the performance downgrade). – barak manos Jul 22 '14 at 09:31
  • @user3035952 *I also found the part that causes this problem* could you dump the assembly in your question? – ouah Jul 22 '14 at 09:42

2 Answers2

0

If you don't want to change the code, here are two options:

1) Disable unaligned exceptions on your Cortex-A9. This solves the problem completely, but you may get a performance hit.

2) Patch the library. You can rename the symbol __aeabi_memcpy in the lib file that you're linking with. Then you can implement your own __aeabi_memcpy that detects the alignment bug, handles it with a specialized routine or jumps to the original memcpy function. If you're using linux you don't even need to rename the symbol. The linker allows you to override functions.

Both solutions are kind of dirty, but if you don't want to change the code this is all I can think off.

Oh, and you should file a bug report. The behavior that you've seen is definitely a bug. Memcpy should work fine with any alignment.

Nils Pipenbrinck
  • 83,631
  • 31
  • 151
  • 221
  • In a situation where you get an "unaligned" exception, you would get incorrect behaviour without the exception (because an unaligned access will read four aligned bytes and rearrange their order). Fully agree this is a serious bug in the implementation. It stinks. – gnasher729 Jul 22 '14 at 09:38
  • I think that disabling unaligned exceptions will only conceal the problem, not solve it. – barak manos Jul 22 '14 at 09:44
  • 1
    Thanks. I think gnasher is right regarding disabling unaligned exceptions. Disabling unaligned exceptions will cause incorrect behaviour. The unaligned exceptions are caused for example by an LDR- or STR-instruction that tries to load or store something from an address that does not have the correct alignment, i.e. 4-byte alignment. When I disable this exception they wont pop out anymore, but LDR will probably load 4 byte of data and not just 1 byte respectivly STR will store 4 byte instead of 1 byte, which is not what i wanted, i.e. incorrect behaviour. – user3035952 Jul 22 '14 at 10:02
0

maybe this still helps: the ARM compiler armcc should have an option with which you can tell the compiler not to do unaligned accesses and also not to use builtin libraries that would do that:

--no_unaligned_access

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472k/chr1359124947629.html

Martin Keßler
  • 776
  • 1
  • 7
  • 10