防止 GCC LTO 删除函数

Prevent GCC LTO from deleting function

我使用 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"
    ...
    );
}

尝试从标记为 used.

的单独函数调用该函数
void dummyFunction(void) __attribute__((used));

// Never called.
void dummyFunction(void) {
    vTaskSwitchContext();
}

您可以将 -Wl,--undefined=vTaskSwitchContext 添加到您的 LDFLAGS

出于某种原因,Dietrich 提出的解决方案对我不起作用。我正在使用 Infineon 的 DAVE 4(基本上是 eclipse,带有用于其 XMC 微控制器系列的精美代码生成插件),这可能是它不起作用的原因。对我来说,我必须在 vTaskStartScheduler():

之后调用 vTaskSwitchContext()
int main(){

    initializationCode();

    vTaskStartScheduler();

    //Code never reaches here
    vTaskSwitchContext();
}

如果您使用的 FreeRTOS 版本已经为 vTaskSwitchContext() 使用了宏 portDONT_DISCARD,您可以在自己的 portmacro.h

中定义 portDONT_DISCARD
#define portDONT_DISCARD __attribute__((used))

本质上是向后移植https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/07e672c448e2a4ea56ae793f1c6dae26d908b16e