Running Keil 5.1 on Freescale K64 32MHz crystal.
Trying to copy data into a two-dimensional array. Copying to an array lastRequestedHeader[3][14] from an array requestedPacket[14].
I have no problem copying into lastRequestedHeader[0] because it starts at address 0x20004514 in memory, but copying to lastRequestedHeader[1] gives me an
Stepping through the memcpy call, I see the first two bytes being copied properly in the __aeabi_memcpy function, but then getting into __aeabi_memcpy4 is where my processor stops on an unaligned access fault
Any ideas? Is there another memcpy call that I can substitute into the project?
How are you calling it?
Perhaps if you use the (void *) cast on the address parameters it won't be so quick to promote it to a word aligned version. That, or turn off optimizations, or create your own alignment safe version.
I was calling it directly, no casting. I casted (void *)&lastRequestHeader[1][0] with no luck. I can create my own memcpy which is more flexible, but my expectation was that the basic library call would work.
What data type does your arrays have? One-byte? So index 1 is 14 bytes forward?
Then memcpy() did correct to copy two bytes first and then try to enter a 4-byte copy loop.
Are you sure your problem is an unaligned access?
Or does memcpy() fail because it correctly aligns the destination but fails to notice that the two initial bytes instead makes the source no longer being 32-bit aligned?
In that case, the memcpy() seems to be broken and should be reported to Keil. It's the responsibility of memcpy() to figure out if it can upgrade some of the copy to use larger block sizes but it isn't allowed to goof and perform unaligned accesses.
Do you get the same result if you switch to the more intelligent memmove() that should also support overlapping memory regions?
Yes the data in the lastRequestHeader[] is a byte array (not a structure). The error I'm trapping is a hard fault and the exception is being declared as an unaligned access.
As I step through the assembly code, the pointers (source and dest) are being incremented correctly after the first 2 bytes are copied. The length is also being adjusted accordingly. Looking at the processor registers leaves me to believe that everything is alright.
memmove resulted in the same hard fault as memcpy.
But what was the align of the source and destination pointer after the first two bytes had been copied?
Was the destination now 4-byte aligned but the source pointer not?
At the initial memcpy call:
SRC = 0x20003C94 DST = 0x20004522 len = 0x0000000E Only source is 4-byte aligned.
After the first two bytes, of course, the DST is now 4-byte aligned and the source is not. The call to __aeabi_memcpy4 has R0 = 0x20004524 (destination address) R1 = 0x20003C96 (source address) R2 - 0x0000000C (length)
Then attempting to step into the __aeabi_memcpy4 hits the hard-fault, again with the unaligned access error
So - homework for Keil. They haven't done their homework - memcpy() and memmove() must work on any alignment of source and destination (assuming that there aren't some additional alignment issues for some specific parts of the processor memory region). This is a bit of a student oops if asked to implement an optimized memcpy().
Cortex-M3 and -M4 (architecture ARMv7-M) can do unaligned memory accesses (LDR/STR, LDRH/STRH. etc.). They can also be made to trap by setting CCR.UNALIGN_TRP. By default (unless all code is compiled with --no_unaligned_access) armcc/armlink will assume that unaligned accesses are enabled.
I remember that, for Cortex-M3, However, if you do a "ldm" or "stm" to load or store multiple values (where "multiple" is defined as 1 or more), unaligned addresses are never allowed.
If unaligned accesses are not allowed, then the compiler should handle the placement of variables on aligned addresses. Special care should be taken when dealing with byte arrays...but that should be a compiler/linker/library issue, not a programmer concern
This isn't a case of the compiler leaving variables on aligned or unaligned addreses.
This is about memcpy() being defined to support any alignment of the source and destination data, and the Keil implementation being designed based on false assumptions. memcpy() must always assume that the two pointers are to byte arrays of arbitrary align.
Can you show us the source code of the call to memcpy and the declarations of the variables involved in the call (and any user-defined typedefs/macros used)?