Skip to main content
ingwmeier
Senior
April 15, 2013
Question

Hard fault at misaligned memcpy memset

  • April 15, 2013
  • 16 replies
  • 3614 views
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
    This topic has been closed for replies.

    16 replies

    waclawek.jan
    Super User
    April 16, 2013
    Posted on April 16, 2013 at 09:15

    And what is the question?

    JW
    ingwmeier
    ingwmeierAuthor
    Senior
    April 16, 2013
    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

    waclawek.jan
    Super User
    April 16, 2013
    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
    Super User
    April 16, 2013
    Posted on April 16, 2013 at 10:24

    Cross post:

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

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    flyer31
    Senior
    April 16, 2013
    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 III
    April 16, 2013
    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
    Super User
    April 16, 2013
    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!

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    frankmeyer9
    Associate III
    April 16, 2013
    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''.

    waclawek.jan
    Super User
    April 16, 2013
    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

    ingwmeier
    ingwmeierAuthor
    Senior
    April 16, 2013
    Posted on April 16, 2013 at 14:06

    Thanks all, I gave the details to Keil, we actually wanted to check with this example, what happens when there is unaligned access.

    I had an issue with memcpy, where it copied stored information either from ram or flash to a structure a while ago, from one source it was ok but from the other it ran into the same Hardfault. I can't examine this anymore. This was the reason why I jumped to a wrong conclusion in the first place.

    Again thank you all.

    I had difficulties with accessing this Forum, therefore the crosspost on the Keil website was answered before.

    Werner