newlib init_array содержит только 0xffffffff с RTEMS

Пытаюсь портировать RTEMS на SAME54P20A. Мне удалось сделать базовый BSP, который компилируется, и базовое приложение. Я компилирую приложение, используя

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

Но при запуске приложения на таргете кажется, что оно никогда не попадает в задачу приложения. Я определил проблему, пройдясь по ассемблерному коду. Во время __libc_init_array не выполняется вызов ни одной из существующих функций.

Вот сборка для функции:

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

При достижении адреса 0x6b14 регистр r3 содержит 0xffffffff, что в конечном итоге вызывает сброс платы.

Вот состояния регистров:

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    

Я не могу понять причину этого.

Вот код приложения:

/*
 * 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 (после комментария Tom V) Регистр r3 загружается строкой

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

Таким образом, он загружается литералом по адресу 0x8914, который (из дампа):

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

Если я не ошибаюсь, разве r3 не должен принимать значение 0x3e9?


person Lucas    schedule 10.02.2021    source источник
comment
Вы пропустили важную часть дизассемблирования: ffffffff был загружен из r5, а r5 загружается из литерала по адресу 6b28, но вы не включили 6b28. Я предполагаю, что, скорее всего, происходит перемещение того, что находится по этому адресу, поэтому вам нужно использовать objdump для библиотечного объекта, чтобы найти, какой символ он использует.   -  person Tom V    schedule 10.02.2021
comment
Истинный. Я пропустил строку, когда делал копию, извините. Я отредактировал сообщение, чтобы добавить его. Я плохо разбираюсь в ассемблере, не могли бы вы помочь мне понять, что делает инструкция? Что касается документации ARM, я понимаю, что она выполняет И с кодом условия EQUAL. Это делается побитово и между всеми аргументами инструкции и сравнивается с 0?   -  person Lucas    schedule 10.02.2021
comment
@Tom V Не обращай внимания на мой последний комментарий. Я понял, что вы имели в виду, но все еще не могу понять, что происходит. Смотрите мою правку.   -  person Lucas    schedule 10.02.2021
comment
Andeq — отвлекающий маневр. Это просто дизассемблированные данные, как если бы это был код, когда это не так. Это число 0x8914. Он загружает слово из 0x00008914 и вызывает его как указатель на функцию. Похоже, слово по адресу 8914 должно быть 0x000003e9. Это означает, что значение r3 должно быть 0x000003e9, что означает, что функция будет вызываться по адресу 0x000003e8 (разница в 1 предназначена для взаимодействия). Если r3 действительно имеет 0xffffffff по адресу 0x6b10, то я подозреваю, что содержимое вашей флешки отличается от вашего дизассемблированного образа.   -  person Tom V    schedule 10.02.2021
comment
Только что проверил, действительно есть функция по адресу 0x000003e8, которая должна вызываться. Gdb говорит мне, что по адресу 0x00008914 находится 0xffffffff. Шестнадцатеричный файл, полученный в результате чтения на флэш-памяти, подтверждает это. Так что вы правы в точку. Следующий вопрос: как может флэшка не содержать ту же информацию, что и дамп?   -  person Lucas    schedule 11.02.2021
comment
Я собираюсь скопировать то, что мы нашли, в ответ, потому что решить всю проблему в комментариях немного неуправляемо. Не могли бы вы отметить ответ, а затем, возможно, задать новый вопрос?   -  person Tom V    schedule 11.02.2021


Ответы (2)


Значение r3 загружается из адреса литерала 0x6b28.

Литерал — это адрес 0x00008914. То, что находится по адресу 0x00008914 в вашей разборке, это слово 0x000003e9. Это означает, что значение r3 должно быть 0x000003e9, и функция должна вызываться по адресу 0x000003e8 (разница в 1 заключается в том, что это адрес взаимодействия, 1 в LSB означает, что цель использует набор инструкций thumb).

Если ваш отладчик показывает, что значение r3, которое вызывается, равно 0xffffffff, то значение в памяти не соответствует вашему дампу дизассемблирования.

Если эта память представляет собой флэш-ПЗУ, значит, что-то не так с процессом статической компоновки или скриптом компоновки. Перемещение может быть не применено к запрограммированному вами образу, но каким-то образом применяется в вашем дампе.

Если эта память является ОЗУ, возможно, что-то перезаписало это значение. Если вы используете компоновщик времени выполнения (необычно для микроконтроллера), то, возможно, он никогда не применял перемещение в первую очередь.

person Tom V    schedule 11.02.2021
comment
@lucas Можете ли вы проверить содержимое шестнадцатеричного файла *, который вы загружаете во флэш-память, что он включает пробел около 0x8914 и что есть 0x000003e9, пожалуйста? - person the busybee; 11.02.2021
comment
@the busybee Что вы имеете в виду под тем, что он включает пространство около 0x8914? Шестнадцатеричный файл, используемый для программирования флэш-памяти, имел 0xffffffff по адресу 0x8914. В любом случае вопрос решен. Я добавил переключатель --strip-unneeded в команду objcopy. - person Lucas; 12.02.2021
comment
@ Лукас Точно, я имел в виду это. Анализ TomV правильный и описывает ситуацию, но я думаю, что реальный ответ - это вариант objcopy. Это следует добавить к его ответу, или вы можете написать свой собственный. - person the busybee; 12.02.2021

В дополнение к анализу Tom V:

Проблема заключалась в том, что некоторые нежелательные разделы сохранялись при создании файла .hex. Решение состоит в том, чтобы добавить переключатель --strip-unneeded в команду objcopy.

person Lucas    schedule 13.02.2021