long_calls между разделами RAM и ROM на голом железе ARM с gcc

Я работаю над проектом 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).

10
задан Eric Angell 21 June 2011 в 22:08
поделиться