Сценарий компоновщика: вставьте абсолютный адрес функции в сгенерированный код

У меня есть вопрос, связанный с линкером gcc.

Я работаю со встроенными компонентами (PIC32), но компилятор и компоновщик PIC32 основан на gcc, поэтому основные вещи должны быть общими для "обычного" компоновщика gcc и компоновщика PIC32.

Чтобы сэкономить место на флэш-памяти (которого часто не хватает на микроконтроллерах), мне нужно поместить несколько крупных функций в загрузчик, и приложение должно вызывать эти функции только указателями.

Итак, мне нужно создать векторную таблицу в сгенерированном коде.

Я пытаюсь получить абсолютный адрес функции и записать его в сгенерированный код, но все еще получаю ошибки.

В приведенном ниже примере я пытаюсь получить адрес функции _formatted_write,

Код:

.user_addr_table _USER_ADDR_TABLE_ADDR :
{
   KEEP(*(.user_addr_table))
   LONG((ABSOLUTE(_formatted_write))); /* _formatted_write is a name of my function */
} > user_addr_table

Линкер возвращает ошибку: "unresolvable symbol '_formatted_write' referenced in expression".

Я заметил, что если я пишу мусор вместо _formatted_writeтогда возвращается ошибкаundefined symbol .....", так, _formatted_write известен линкером.

Это заставляет меня думать, что я должен выполнить некоторые дополнительные шаги, чтобы сделать его "разрешимым". Но до сих пор не знаю, как это сделать.

2 ответа

Я нашел способ использовать указатели функций, т.е.

void (*formatted_write)( int a, char * b, struct mystruct c );

затем в коде где-то при загрузке задайте адрес этой функции, т.е.

formatted_write = 0xa0000;

затем вы можете вызвать свою функцию, используя обычное соглашение.

Кроме того, вы можете использовать флаг -Wl,- just-symbols=symbols.txt при компиляции. Вы можете установить адрес ваших символов следующим образом:

formatted_write = 0xa0000;

Для случая, когда у кого-то есть такая же проблема (как у меня несколько часов назад), есть еще лучшее решение:

Пусть "bootloader.out" будет бинарным загрузчиком. Тогда мы можем генерировать с

nm -g bootloader.out | grep '^[0-9,a-e]\{8\} T' | awk '{printf "PROVIDE(%s = 0x%s);\n",$3,$1}' > bootloader.inc

файл, который мы можем включить в скрипт компоновщика приложения с

INCLUDE bootloader.inc

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

Другие вопросы по тегам