Search code examples
ccmakestm32

Linking problem of weak functions in stm32 using CMake


Environment:

  • Win10
  • STM32CubeMX 6.8.1
  • Clion 2022.3.2
  • gcc-arm-none-eabi-10.3
  • CMake 3.26.1

Hello. I am trying the freertos in stm32.

I enabled freertos in cubemx, then change the default task to TaskMain and ask it to generate the start function "as weak".

I add all the code that CubeMX generated to a library target. And I add another main.cpp to an executable target as user codes and link to the library target.

In my main.cpp, I redefined the weak function.

#include "cmsis_os.h"
#include "gpio.h"

void TaskMain(void* args) {
    UNUSED(args);
    while (true) {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
        osDelay(1000);
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
        osDelay(1000);
    }
}

But the program will not run into the TaskMain function in main.cpp. It stucks in the endless loop in the weak function infreertos.c.

Someone said that cut the declaration of the function in freertos.c and paste it into main.h under Exported functions prototypes and include main.h in main.cpp could soulve the problem. But why?


Solution

  • C++ does name mangling. The most frequent place to run into similar problem on STM32 is with IRQ handlers. If you have a weak while(1) IRQ handler in .c, and you define another IRQ handler with the same name in .cpp, it will not work, because on the linking stage the names of the weak and "strong" function are not the same anymore. Your situation seems similar.

    The solution is to force a function not to have a mangled name.

    #include "cmsis_os.h"
    #include "gpio.h"
    
    
    void TaskMain(void* args) asm("TaskMain");
    void TaskMain(void* args) {
        UNUSED(args);
        while (true) {
            HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
            osDelay(1000);
            HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
            osDelay(1000);
        }
    }