Я работаю над проектом ARM7TDMI с использованием GCC 4.3, и у меня возникли некоторые затруднения с указанием компилятору использовать длинные вызовы в одних случаях, но не в других.
Процесс сборки выполняется arm-eabi-gcc
для создания перемещаемых объектных файлов ELF для каждого исходного файла .c (наиболее подходящие CFLAGS включают -Os -ffunction-section -fdata-section -mthumb -mthumb-interwork
) , а затем связывает их все в исполняемый файл ELF (наиболее подходящие LDFLAGS включают -Wl, - gc-section -Wl, -static -Wl, -n -nostdlib
и настраиваемый скрипт компоновщика). Затем этот ELF-файл преобразуется в необработанный исполняемый файл с помощью arm-eabi-objcopy -O binary
, а пользовательский загрузчик копирует его из ПЗУ в ОЗУ (единое ОЗУ с кодом и данными) при запуске. Итак, все затем выполняется из ОЗУ, .rodata
присутствует в ОЗУ, и все происходит быстро, полностью игнорируя ПЗУ после загрузки.
Сейчас я пытаюсь это изменить, чтобы некоторые отдельные фрагменты РО данные и текст выбранных функций могут находиться только в ПЗУ и при необходимости доступны во время выполнения. Я изменил сценарий компоновщика, чтобы узнать о двух новых разделах ". Flashdata"
и ". Flashtext"
, которые должны быть размещены по фиксированному адресу в ПЗУ. Я также добавил __ attribute __ ((__ section __ (". Flashdata")))
и __ attribute __ ((__ section __ (". Flashtext"), __ long_call __))
по всему коду C по мере необходимости. , и я переделал процесс сборки, так что старый objcopy теперь добавляет -R .flashdata -R .flashtext
, и я делаю вторую objcopy с -j
для каждого из них разделов, затем я объединяю два выходных файла, чтобы загрузчик мог делать правильные вещи и разделы ПЗУ появлялись в ожидаемом месте отображения памяти.
Все это работает нормально - я могу напечатать строки, помеченные в . flashdata
, и я могу вызвать функцию .flashtext
из кода, у которого не хватает ОЗУ (который знает, что нужно использовать длинный вызов из-за атрибута __ long_call __
рядом с ] __ section __ (атрибут ". flashtext")
). Эта основанная на ПЗУ функция может с радостью вызывать другие функции на основе ПЗУ и может возвращаться обратно к вызывающему объекту, основанному на ОЗУ.
Проблема возникает при попытке вызвать из функции на основе ПЗУ в функцию на основе ОЗУ. , который также должен быть долгим. Я не хочу везде использовать длинные вызовы, поэтому я не хочу использовать -mlong_calls в моем CFLAGS. Если я сгруппирую все функции, которые хранятся в ПЗУ, в один rom.c
, я могу создать этот один файл с помощью -mlong-calls
, и все будет работать. Тем не менее, я настоятельно предпочитаю избегать этого и держать функции сгруппированными по назначению, просто помечая несколько здесь и там подходящих для запуска из ПЗУ.
Между прочим, этого было недостаточно в gcc 3.4. Использование -mlong-calls
заставило компилятор задуматься правильно, но он не смог довести дело до конца, потому что был готов выполнять только длинные прыжки со своими помощниками _call_via_rX
... которые все жили в оперативной памяти и могли быть доступны только через долгий звонок. Это было исправлено в компоновщике в gcc 4.0, но не было перенесено ни на что в дереве 3.x .
Так что замечательно, что теперь я вообще могу обращаться к ОЗУ, поскольку я использую gcc 4.3. Было бы даже лучше, если бы я мог как-то пометить код в функциях на основе ПЗУ, чтобы заставить его использовать длинные вызовы. Существует #pragma long_calls
, но он влияет только на объявления, поэтому я мог бы использовать его вместо __ attribute __ ((__ long_call __))
. К сожалению, он не заставляет компилятор волшебным образом использовать длинные вызовы для всех вызовов функций, встречающихся во время его действия.
С организационной точки зрения, группировать весь медленно работающий код в один файл просто неправильно. , вне контекста и отдельно от другого кода в своей общей категории. Скажите, пожалуйста, есть вариант, который я еще не рассматривал. Почему -ffunction-section или просто тот факт, что код находится в разных разделах ( .text
против .flashtext
), не решают мою проблему автоматически?
Кстати, ошибка компоновщика, когда он выясняет, что компилятор использовал короткий вызов, который не оставил достаточно места для управления перемещением: перемещение усечено, чтобы соответствовать: R_ARM_THM_CALL против символа
foo ', определенного в. Раздел text.foo в objs / foo.o (а раздел
.text.foo используется вместо
.text из-за
-ffunction-section` в CFLAGS).