Позиционно-независимый двоичный файл для Atmel SAM Cortex-M0 +

Я пытаюсь создать независимый от позиции двоичный файл для Cortex-M0 +, используя набор инструментов ARM GNU, включенный в Atmel Studio 7 (arm-none-eabi?). Я просмотрел много мест для получения информации о том, как это сделать, но безуспешно. Это упростило бы создание образов для пинг-понга в областях флэш-памяти с низким и высоким значением для обновлений OTA без необходимости знать или заботиться о том, было ли обновление образом пинг или понг для этого устройства.

У меня есть резидент загрузчика 8 КБ по адресу 0x0000, с которым я могу общаться через UART, и который перейдет на 0x6000 (24 КБ) после сброса, если обнаружит там двоичный файл (то есть не стирает флэш-память 0xFFFF). Этот загрузчик SAM-BA позволяет мне выгружать память, стирать и программировать Flash с файлами .bin по указанному адресу.

В проекте приложения (простое мигание светодиода), ничего не делая, кроме добавления -section-start = .text = 0x6000 в командную строку компоновщика, код мигания светодиода работает после того, как загрузчик запрограммировал его на 0x6000. Я также вижу в шестнадцатеричном файле, что он начинается с 0x6000.

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

28e: d001 beq.n 294

И в результате двоичный файл мигания светодиода, который я загружаю на 0x6000, не выполняется, если я специально не скажу компоновщику, чтобы он поместил его в 0x6000, что противоречит цели. Обратите внимание, что я также вижу то, что выглядит как относительные ветки в других частях разборки:

21c: 4b03 ldr r3, [pc, # 12]; (22c)

21e: 58d3 ldr r3, [r2, r3]

220: 9301 str r3, [sp, # 4]

222: 4798 blx r3

SRAM всегда находится по одному и тому же адресу (0x20000000), мне просто нужно иметь возможность изменить положение исполняемого файла. Я не изменял командный файл компоновщика, и в нем нет раздела для .got (например, (.got) или аналогичного).

Может ли кто-нибудь объяснить мне конкретные изменения, которые мне нужно внести в флаги компилятора / ассемблера / компоновщика, чтобы создать независимый от позиции двоичный файл в этой настройке? Спасибо заранее.


person JohnnyC    schedule 21.03.2019    source источник


Ответы (1)


Вам нужно повнимательнее присмотреться к своей разборке. Для 0xd001 я получаю следующее:

 0x00000000:    d001        ..      BEQ      {pc}+0x6 ; 0x6

В вашем случае инструментальная цепочка попыталась быть полезной. Ясно, что 16-битный код операции не может кодировать абсолютный адрес с 32-битным адресным пространством. Итак, вы ближе, чем вы думаете, к решению.

person Sean Houlihane    schedule 21.03.2019
comment
Спасибо, я предположил, что дизассемблер в Studio правильно это декодирует, когда говорит: ‹system_clock_source_get_hz + 0x64›. system_clock_source_get_hz - это функция, из которой я вытащил строку, и мне не приходило в голову, что она может кодировать абсолютный адрес в 16-битном коде операции. Мне нужно еще раз взглянуть на это и посмотреть, есть ли способ отладить это на месте. Кстати, меня интересует, как вы можете отделить строку кода от остального текста вашего ответа. - person JohnnyC; 21.03.2019
comment
Хорошо, прогрессирую. Я вижу, что загрузчик переходит к коду приложения, но я замечаю, что таблица векторов прерываний также больше не имеет абсолютных адресов. Имея только смещения в IVT, код приложения возвращается обратно в загрузчик вместо перехода к main (). Я думаю, что в M0 + есть регистр перемещения векторной таблицы, который должен быть записан загрузчиком, прежде чем он перейдет к базе приложения IVT. - person JohnnyC; 22.03.2019
comment
Становится лучше. VTOR записывается загрузчиком, но это влияет на адрес записи IVT только при возникновении прерывания. Таким образом, ч / б прерывания будут поступать в IVT в нужном месте, но сам вектор является адресом, который не смещен должным образом. Если для приложения установлено значение 0x6000, все записи IVT должны быть 0x6xxx. Но с флагом -fPIC это вместо 0x0xxx, поэтому выполнение случайным образом переносится обратно в загрузчик. Поскольку только загрузчик знает, где находится код приложения, он должен изменять только записи IVT на лету, когда записывает код во Flash. - person JohnnyC; 22.03.2019
comment
Да, вы на правильном пути. Таблица векторов является абсолютным адресом, поэтому в этом случае ее необходимо переписать. Или вы можете предварительно загрузить векторную таблицу, если конечная цель всегда одна и та же. - person Sean Houlihane; 23.03.2019