0
votes

Hello everyone i have HardFault exception on my cortex m1 many times at the same place. I've got HardFault implementation and i can read stacked registers:

stacked_r0 unsigned int 0x4 (Hex)
stacked_r1 unsigned int 0x60905f98 (Hex)
stacked_r2 unsigned int 0x0 (Hex)
stacked_r3 unsigned int 0x6092304b (Hex)
stacked_r12 unsigned int 0x60922ff8 (Hex)
stacked_lr unsigned int 0x60810be3 (Hex)
stacked_pc unsigned int 0x60810ce2 (Hex)
stacked_psr unsigned int 0x41000000 (Hex)

the operation at stacked PC is: 60810ce2: ldrsh r2, [r3, r2]

why it causes fault?

upd i've rearranged variables and for now it has crashed in memcpy called from freertos code

stacked_r0 unsigned int 0x6090c858 (Hex)
stacked_r1 unsigned int 0x6091f8b4 (Hex)
stacked_r2 unsigned int 0x3c (Hex)
stacked_r3 unsigned int 0x6091f8a4 (Hex)
stacked_r12 unsigned int 0x280 (Hex) stacked_lr unsigned int 0x60827f89 (Hex)
stacked_pc unsigned int 0x6082b0dc (Hex)
stacked_psr unsigned int 0x1000000 (Hex)

6082b0ba: bne.n 0x6082b120

6082b0bc: adds r5, r2, #0

6082b0be: adds r4, r0, #0

6082b0c0: subs r5, #16

6082b0c2: lsrs r5, r5, #4

6082b0c4: adds r5, #1

6082b0c6: lsls r5, r5, #4

6082b0c8: adds r1, r1, r5

6082b0ca: ldr r6, [r3, #0]

6082b0cc: str r6, [r4, #0]

6082b0ce: ldr r6, [r3, #4]

6082b0d0: str r6, [r4, #4]

6082b0d2: ldr r6, [r3, #8]

6082b0d4: str r6, [r4, #8]

6082b0d6: ldr r6, [r3, #12]

6082b0d8: adds r3, #16

6082b0da: str r6, [r4, #12]

6082b0dc: adds r4, #16

1
that is an unaligned access. - old_timer
okay, but why? r3 points at stack - qmor
stack is ram, what does stack have to do with it the lower bits are 0xB or 1011 for ldrsh or ldrh the lower bit has to be a zero for ldr, the lower two have to be zeros for ldrd the lower three have to be zeros. you are trying to do an unaligned halfword access and the processor properly stopped you from doing it. - old_timer
right. i'm using freertos and GCC. It's looks like it's generates code which is not manipulating stack addresses by 8 bytes or not? - qmor
If you want to get into what the compiler is doing you have to provide a simple example function, the compiler and options, and output and go from there. not sure why gcc would be using r3 nor r2 to access the stack, a load has nothing to do with alignment of the stack anyway. - old_timer

1 Answers

1
votes

Simple example of compiler generating alignment using ldrsh:

short more_fun ( short );
short fun ( short a )
{
    unsigned int ra;
    short x[16];
    for(ra=0;ra<16;ra++)
    {
        a+=more_fun(x[ra]);
    }
    return(a);
}

arm-none-eabi-gcc -mthumb -O2 -c so.c -o so.o -march=armv6-m arm-none-eabi-objdump -D so.o

00000000 <fun>:
   0:   b570        push    {r4, r5, r6, lr}
   2:   b088        sub sp, #32
   4:   0004        movs    r4, r0
   6:   466d        mov r5, sp
   8:   ae08        add r6, sp, #32
   a:   2300        movs    r3, #0
   c:   5ee8        ldrsh   r0, [r5, r3]
   e:   f7ff fffe   bl  0 <more_fun>
  12:   3502        adds    r5, #2
  14:   1904        adds    r4, r0, r4
  16:   b224        sxth    r4, r4
  18:   42b5        cmp r5, r6
  1a:   d1f6        bne.n   a <fun+0xa>
  1c:   0020        movs    r0, r4
  1e:   b008        add sp, #32
  20:   bd70        pop {r4, r5, r6, pc}
  22:   46c0        nop         ; (mov r8, r8)

the stack is remaining aligned, the stack manipulation, pushing, popping and stack frame are all multiples of 8 bytes (two words).

The array is on the stack and they use r5 basically as the index into the array, looks like ldrsh requires two registers so they set r3 to zero so they can have a second register. And the key here is they start off aligned, the sp address has at least the lower three bits zeros assuming everyone outside this code has conformed to the convention. Then the code adds 2 to r5 each time through the loop, keeping the pointer to the array aligned on a halfword boundary, lower bit remains zero for the address for every use of ldrsh. No alignment issues.

Please provide a similar exmaple, maybe fragments of code, but certainly the relevant fragments around the unaligned ldrsh.