Как указывает Адам Розенфельд, вам нужно использовать управляющий файл компоновщика, чтобы определить для вас один или несколько символов, которые находятся в точно правильном месте.
Для gcc и binutils вы будете использовать синтаксис сценария компоновщика ld. Обратитесь к руководству ld для всех деталей, которые я здесь опускаю. Это немного непрозрачно, но вы должны потратить некоторое время с ним, если вы собираетесь потратить значительное количество усилий во встроенном мире. Это окупится за вас.
В скрипте компоновщика вы хотите определить символ перед вашим сегментом .text и один после.
Адам упоминает синтаксис PROVIDE()
, который будет работать. Но вам может не понадобиться переносить определение в PROVIDE, если вы можете гарантировать, что ваше имя уникально. Обратите внимание, что это гарантия того, что вы должны быть в состоянии это сделать, иначе вы рискуете сильно запутаться.
В моем сценарии я просто использую что-то вроде:
__SDRAM_CS1 = 0x10000000;
чтобы определить символ с постоянным адресом, который ссылается (в данном случае) на местоположение, мы решили, что контроллер SDRAM отобразит память SDRAM, и в C я объявляю его следующим образом:
extern unsigned char __SDRAM_CS1[];
, чтобы его можно было использовать в коде, который должен знать, где на самом деле находится SDRAM.
Для символа, определяющего конец сегмента .text, в скрипте компоновщика должно быть что-то похожее на следующее
SECTIONS
{
...
.text {
_start_text = .;
*(.text);
...
_end_text = .;
}
...
}
и объявить начальный и конечный символы как
extern unsigned char _start_text[];
extern unsigned char _end_text[];
в C. Тогда начальный адрес просто _start_text
, а длина в байтах текстового сегмента равна _end_text - _start_text
.
Обратите внимание, что я упустил много деталей. Возможно, у вас есть разделы с именами, отличными от .text, которые должны обрабатываться так, как если бы они были в текстовом сегменте. Ярким примером являются данные только для чтения, которые часто можно безопасно размещать в текстовом сегменте, поскольку известно, что это const
, а во встроенной системе вы не захотите копировать их в ценную оперативную память, если в этом нет необходимости. Кроме того, инициализаторы для сегмента данных и внутренние списки конструкторов глобальных объектов расположены рядом с текстовым сегментом.
Включаете ли вы такие вещи в размер изображения - это дизайнерское решение, которое вам нужно принять после понимания того, для чего они используются.