cancel
Showing results for 
Search instead for 
Did you mean: 

Hard fault at misaligned memcpy memset

ingwmeier
Senior
Posted on April 15, 2013 at 16:11

Already posted this on Keil Website, it was tested with STM32F100, therefore:

we made some simple tests with STM32F100 Value Line Eval Board:

//------------------------------------------------------------------------------

// Variables

static unsigned char sDstBuf[1024]; // 1KiB

static unsigned char sSrcBuf[sizeof(sDstBuf)];

printf(''Copying words from misaligned src to aligned dst buffer... '');

memset(sDstBuf, 0xcd, sizeof(sDstBuf));

with optimize Level 3, optimize for time this takes

120usec

with optimize Level 0

155usec

almost the same if memcpy is used:

memcpy(sDstBuf, (const void *)0xcd, sizeof(sDstBuf));

It runs into hard fault, if optimize Level >=1 and optimise for time is not set.

I think this is a compiler error..

We ran into this before with MDK 4.60, now we use 4.70A

Werner

#cross-post #memcpy
16 REPLIES 16
Posted on April 16, 2013 at 09:15

And what is the question?

JW
ingwmeier
Senior
Posted on April 16, 2013 at 09:25

Sorry I try editing, but somehow the Forum does not let me do that..

the offending code is

    for (pDstWord = (unsigned int*) (sDstBuf + 0), // Aligned!

    pSrcWord = (unsigned int*) (sSrcBuf + 1);

        // Misaligned!

        pSrcWord

            < (unsigned int*) (sSrcBuf + sizeof(sSrcBuf) - sizeof(*pSrcWord));

        pSrcWord++)

    {

        *pDstWord = *pSrcWord;

    }

optimize >= 1 for size:

for (pDstWord = (unsigned int*) (sDstBuf + 0), // Aligned! pSrcWord = (unsigned int*) (sSrcBuf + 1); // Misaligned! pSrcWord < (unsigned int*) (sSrcBuf + sizeof(sSrcBuf) - sizeof(*pSrcWord)); pSrcWord++) { *pDstWord = *pSrcWord; } leads to this disassembly part: 0x08002446 CC02 LDM r4!,{r1} ; >>>> after this: Hardfault occurs 0x08002448 6001 STR r1,[r0,#0x00] 372: pSrcWord 373: < (unsigned int*) (sSrcBuf + sizeof(sSrcBuf) - sizeof(*pSrcWord)); 374: pSrcWord++) 375: { 376: *pDstWord = *pSrcWord; 377: } 0x0800244A 42B4 CMP r4,r6 0x0800244C D3FB BCC 0x08002446

Posted on April 16, 2013 at 10:12

Multi-word instructions (here: LDM) must access memory word-aligned, see e.g. description of UNALIGNED bit in UFSR (part of SCB->CFSR).

I can't judge whether this could be called a compiler fault; Keil is to be consulted.

Is this a library memcpy()?

JW

Andrew Neil
Chief II
Posted on April 16, 2013 at 10:24

Cross post:

http://www.keil.com/forum/22856/

flyer31
Senior
Posted on April 16, 2013 at 10:26

You need to set the compiler switch ''--no_unaligned_access'' in Keil.

ARM7 has the principal possibility to support access at 2-Byte addresses - but it is quite stupid, as it is not faster than two 4-Byte (=32-bit aligned) accesses. So you should switch this off in the compiler. (if you want to use it, you have to switch it on in the CPU - see the system ... .c file - best search for the keyword ''aligned'' in the ARM7 TRM / STM32F4 Programming Manual / Cortex M4 TRM).

frankmeyer9
Associate II
Posted on April 16, 2013 at 10:38

I can't judge whether this could be called a compiler fault; Keil is to be consulted.

 

I would judge it as such.

The compiler should not emit such instructions if he can't ensure proper alignment.

And as the address parameters are untyped (void *) and the number of elements to copy in bytes (

http://linux.die.net/man/3/memcpy

), that is definitely not the case, so I view this as incorrect optimisation.

Andrew Neil
Chief II
Posted on April 16, 2013 at 10:43

''The compiler should not emit such instructions if he can't ensure proper alignment''

 

But, in this case, I'm not sure that it can ensure that - given all the casting that's going on (see the Keil cross-post)

''as the address parameters are untyped (void *)''

 

 

Note that the memcpy reference was a red herring - it's not occuring in the memcpy!

frankmeyer9
Associate II
Posted on April 16, 2013 at 11:17

Note that the memcpy reference was a red herring - it's not occuring in the memcpy!

 

You are right, that would be a different case than.

Forcing word-sized pointers to unaligned addresses is typically ''one's own fault''.

Posted on April 16, 2013 at 12:16

As far as the compiler is concerned...

C99, 6.3.2.3#5

An integer may be converted to any pointer type. Except as previously specified [this refers to null pointer, JW], the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

#7

A pointer to an object or incomplete type may be converted to a pointer to a different

object or incomplete type. If the resulting pointer is not correctly aligned for the

pointed-to type, the behavior is undefined.

i.e. the compiler is absolutely free to emit the ''offending'' code as the result of dereferencing of cast pointers, even if it IS aware of the unalignment.

JW