0

I'm trying to port RTEMS on the SAME54P20A. I managed to make a basic BSP that compile and a basic application. I compile the application using

./waf configure --rtems=$HOME/rtems/5 --rtems-bsp=arm/same54p20a
./waf

But when running the application on the target, it seems that it never gets to the application task. I identified the issue by stepping through the assembly code. A call to no existing function is made during __libc_init_array.

Here is the assembly for the function :

00006ae4 <__libc_init_array>:
    6ae4:   b570        push    {r4, r5, r6, lr}
    6ae6:   4e0d        ldr r6, [pc, #52]   ; (6b1c <__libc_init_array+0x38>)
    6ae8:   4d0d        ldr r5, [pc, #52]   ; (6b20 <__libc_init_array+0x3c>)
    6aea:   1b76        subs    r6, r6, r5
    6aec:   10b6        asrs    r6, r6, #2
    6aee:   d006        beq.n   6afe <__libc_init_array+0x1a>
    6af0:   2400        movs    r4, #0
    6af2:   3401        adds    r4, #1
    6af4:   f855 3b04   ldr.w   r3, [r5], #4
    6af8:   4798        blx r3
    6afa:   42a6        cmp r6, r4
    6afc:   d1f9        bne.n   6af2 <__libc_init_array+0xe>
    6afe:   4e09        ldr r6, [pc, #36]   ; (6b24 <__libc_init_array+0x40>)
    6b00:   4d09        ldr r5, [pc, #36]   ; (6b28 <__libc_init_array+0x44>)
    6b02:   1b76        subs    r6, r6, r5
    6b04:   f000 fe46   bl  7794 <_init>
    6b08:   10b6        asrs    r6, r6, #2
    6b0a:   d006        beq.n   6b1a <__libc_init_array+0x36>
    6b0c:   2400        movs    r4, #0
    6b0e:   3401        adds    r4, #1
    6b10:   f855 3b04   ldr.w   r3, [r5], #4
    6b14:   4798        blx r3
    6b16:   42a6        cmp r6, r4
    6b18:   d1f9        bne.n   6b0e <__libc_init_array+0x2a>
    6b1a:   bd70        pop {r4, r5, r6, pc}
    6b1c:   00008914    andeq   r8, r0, r4, lsl r9
    6b20:   00008914    andeq   r8, r0, r4, lsl r9
    6b24:   00008918    andeq   r8, r0, r8, lsl r9
    6b28:   00008914    andeq   r8, r0, r4, lsl r9

When reaching address 0x6b14 the register r3 contains 0xffffffff which eventually trigger a reset of the board.

Here are the registers states :

r0             0x200016c8          536876744                                                            r1             0xa010001           167837697                                                             │
│r2             0x0                 0                                                                    r3             0xffffffff          -1                                                                    │
│r4             0x1                 1                                                                    r5             0x8918              35096                                                                 │
│r6             0x1                 1                                                                    r7             0x0                 0                                                                     │
│r8             0x0                 0                                                                    r9             0x0                 0                                                                     │
│r10            0x0                 0                                                                    r11            0x0                 0                                                                     │
│r12            0x20000400          536871936                                                            sp             0x20005888          0x20005888                                                            │
│lr             0x6b09              27401                                                                pc             0x6b14              0x6b14 <__libc_init_array+48>                                         │
│xPSR           0x1000000           16777216                                                             fpscr          0x0                 0                                                                     │
│msp            0x20004888          0x20004888 <_ISR_Stack_area_begin+4072>                              psp            0x20005888          0x20005888                                                            │
│primask        0x0                 0                                                                    basepri        0x0                 0                                                                     │
│faultmask      0x0                 0                                                                    control        0x2                 2    

I can't figure out the reason of this.

Here is the application code :

/*
 * app.c
 */
#include <rtems.h>
#include <stdlib.h>
#include "bsp/same54p20a.h"
#include "bsp/port.h"


rtems_task Init(
  rtems_task_argument ignored
)
{
  /* Set pin PC21 as output to control LED1 */
  PORT_REGS->GROUP[2].PORT_DIR |= PORT_PC21;
  
  /* Turn on the led */
  PORT_REGS->GROUP[2].PORT_OUTCLR |= PORT_PC21;
  
  exit( 0 );
}
/*
 * init.c
 */

#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER

#define CONFIGURE_MAXIMUM_TASKS 1

#define CONFIGURE_RTEMS_INIT_TASKS_TABLE

#define CONFIGURE_INIT

#include <rtems/confdefs.h>

EDIT (After Tom V comment) Register r3 is loaded by the line

    6b10:   f855 3b04   ldr.w   r3, [r5], #4

So it is loaded with the litteral at address 0x8914 which is (from the dump):

00008914 <__frame_dummy_init_array_entry>:
    8914:   000003e9    andeq   r0, r0, r9, ror #7

If i'm not mistaken, shouldn't r3 take the value 0x3e9 ?

Lucas
  • 65
  • 9
  • You missed an important bit of the disassembly: The ffffffff was loaded from r5, and r5 is loaded from a literal at 6b28, but you haven't included 6b28. I expect it is most likely that there is a relocation on what is is at that address, so you need to use objdump on the library object to find which symbol it is using. – Tom V Feb 10 '21 at 14:46
  • True. I missed a line while doing the copy sorry. I edited the post to add it. I'm not fluent in assembly, could you help me figure what the instruction is doing ? For the ARM documentation, I understand that it is doing a AND with the condition code EQUAL. Is it doing a bitwise and between all the arguments of the instruction and compare it to 0 ? – Lucas Feb 10 '21 at 15:01
  • @Tom V Nevermind my last comment. I got what you meant, but still can't figure out what is happening. See my edit. – Lucas Feb 10 '21 at 15:50
  • The andeq is a red herring. This is just data being disassembled as if it was code when it isn't. This is the number 0x8914. It loads the word from 0x00008914 calls it as a function pointer. It looks like the word at 8914 should be 0x000003e9. This means the value of r3 should be 0x000003e9, which means it would call the function at 0x000003e8 (the difference of 1 is for "interworking"). If r3 really has 0xffffffff at 0x6b10 then I suspect the contents of your flash is different from your disassembled image. – Tom V Feb 10 '21 at 16:41
  • Just checked, there is indeed a function at 0x000003e8 that should be the one called. Gdb tells me that at 0x00008914 there is 0xffffffff. The hex file resulting of a read on the flash confirm this. So you're right on point. Next question would be : how could the flash not contain the same information as the dump ? – Lucas Feb 11 '21 at 08:27
  • I'm going to copy what we've found into an answer because it's a bit unmanageable to address the whole problem in comments. Can you please tick the answer and then maybe ask a new question? – Tom V Feb 11 '21 at 09:48

2 Answers2

1

The value of r3 is loaded from the address in the literal at 0x6b28.

The literal is address 0x00008914. What is at address 0x00008914 in your disassembly is the word 0x000003e9. This means the value of r3 should be 0x000003e9, and it should call the function at 0x000003e8 (the difference of 1 is because this is an interworking address, the 1 in the LSB means that the target uses the thumb instruction set).

If your debbugger shows that the value of r3 that gets called is 0xffffffff, then the value in memory does not match your disassembly dump.

If this memory is flash ROM then something is wrong with your static linking process or your link script. A relocation might not have been applied to the image that you programmed, but then somehow does get applied in your dump.

If this memory is RAM, then maybe something overwrote that value. If you are using a runtime linker (unusual on a microcontroller) then maybe it never applied the relocation in the first place.

Tom V
  • 4,827
  • 2
  • 5
  • 22
  • @lucas Can you check the contents of the hex file **you load into the flash* that it includes the space around 0x8914, and that there is 0x000003e9, please? – the busybee Feb 11 '21 at 11:22
  • @the busybee What do you mean by "that it includes the space around 0x8914" ? The hex file used to program the flash had 0xfffffff at address 0x8914. Anyway, the issue is solved. I added the switch `--strip-unneeded` to the command `objcopy`. – Lucas Feb 12 '21 at 14:44
  • @Lucas Exactly, I meant that. The analysis of TomV is correct and describes the situation, but I think the real answer is the option to `objcopy`. This should be added to his answer or you could write one of your own. – the busybee Feb 12 '21 at 17:45
0

In addition to Tom V analysis :

The issue was that some unwanted sections were keep while creating the .hex file. The solution is to add the switch --strip-unneeded to the command objcopy.

Lucas
  • 65
  • 9