Предотвратить GCC LTO от удаления функции
Я работаю с GCC-ARM-Embedded и FreeRTOS.
FreeRTOS имеет функцию vTaskSwitchContext()
который используется только в некотором встроенном коде ассемблера.
Проблема в том, что когда я использую LTO, GCC не учитывает встроенный код ассемблера и думает, что функция не используется, поэтому удаляет его. После этого компоновщик завершается ошибкой, поскольку вызов функции в встроенном коде ассемблера не может быть разрешен.
Я бы подала заявку __attribute__((used))
но я не хочу касаться кода FreeRTOS (он генерируется STM32CubeMX).
Я попытался вставить это в мой код, но на самом деле GCC достаточно умен, чтобы не позволить этому работать:
if(false)
vTaskSwitchContext();
Есть ли какой-нибудь способ сказать GCC в другом исходном файле или через параметр, что эту функцию не следует удалять?
пример
// file1.c
void vTaskSwitchContext( void )
{
...
}
// file2.c
void xPortPendSVHandler( void )
{
__asm volatile
(
...
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
...
);
}
4 ответа
Попробуйте вызвать функцию из отдельной функции, которая помечена used
,
void dummyFunction(void) __attribute__((used));
// Never called.
void dummyFunction(void) {
vTaskSwitchContext();
}
Можете добавить -Wl,--undefined=vTaskSwitchContext
на ваш LDFLAGS
,
По какой-то причине решение, которое предложил Дитрих, у меня не сработало. Я использую Infineon DAVE 4 (в основном eclipse с модным плагином генерации кода для их линейки микроконтроллеров XMC), что может быть причиной того, что это не сработало. Мне пришлось позвонитьvTaskSwitchContext()
после vTaskStartScheduler()
:
int main(){
initializationCode();
vTaskStartScheduler();
//Code never reaches here
vTaskSwitchContext();
}
Если ваша версия FreeRTOS уже использует макрос для
vTaskSwitchContext()
вы можете определить
portDONT_DISCARD
в своем собственном
portmacro.h
#define portDONT_DISCARD __attribute__((used))
По сути, бэкпорт https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/07e672c448e2a4ea56ae793f1c6dae26d908b16e