STM32 GNU ARM链接器:带有eclipse

时间:2018-06-05 22:25:08

标签: eclipse linker arm gnu stm32

我目前正在使用Eclipse学习STM32F103。我在链接器阶段遇到问题,我遇到链接器错误:未定义引用`HAL_TIM_Base_Init'

Building target: TimerTest.elf
Invoking: GNU ARM Cross C++ Linker
arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall -Wextra  -g3 -T "C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\SW4STM32\WS2812_TimerTest\STM32F103C8Tx_FLASH.ld" -Xlinker --gc-sections -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Src" -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Drivers\STM32F1xx_HAL_Driver\Src" -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Drivers\STM32F1xx_HAL_Driver\Inc" -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Inc" -Wl,-Map,"TimerTest.map" -Xlinker --cref --specs=nano.specs -o "TimerTest.elf"  ./Src/WS2812.o ./Src/main.o ./Src/stm32f1xx_hal_msp.o ./Src/stm32f1xx_hal_tim.o ./Src/stm32f1xx_it.o ./Src/system_stm32f1xx.o ./Src/usb_device.o ./Src/usbd_cdc_if.o ./Src/usbd_conf.o ./Src/usbd_desc.o  ./SW4STM32/startup_stm32f103xb.o  ./Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.o ./Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.o ./Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.o  ./Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.o  ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.o   
./Src/WS2812.o: In function `WS2812Init':
C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Debug/../Src/WS2812.c:30: undefined reference to `HAL_TIM_Base_Init'
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:64: TimerTest.elf] Error 1

这是我的代码:

的main.c

#include "main.h"

#include "WS2812.h"

#include "stm32f1xx_hal.h"
#include "usb_device.h"

int main(void)
{

  WS2812Init();

  while (1)
  {

  }

}

WS2812.h:

#ifndef INC_WS2812_H_
#define INC_WS2812_H_

#include <stm32f1xx_hal_gpio.h>     // use gpio output
#include <stm32f1xx_hal_rcc.h>
#include <stm32f1xx_hal_tim.h>      // use timer

// adopt gpio port & pin for following section
#define WS2812_GPIO_PORT    GPIOB
#define WS2812_GPIO_PIN     GPIO_PIN_12

#define ENABLE_GPIO_RCC()   do{\
                                if(!__HAL_RCC_GPIOB_IS_CLK_ENABLED())\
                                    __HAL_RCC_GPIOB_CLK_ENABLE();\
                            }while(0U)

static GPIO_InitTypeDef SW2812Pin = {
        .Pin = WS2812_GPIO_PIN,
        .Speed = GPIO_SPEED_FREQ_LOW,
        .Mode = GPIO_MODE_OUTPUT_PP
};
#define SYS_CLOCK

// adopt timer configuration for following section
#define WS2812_SELECTED_TIMER TIM4

static TIM_HandleTypeDef ws2812TimerConfig;

void WS2812Init(void);

#endif /* INC_WS2812_H_ */

WS2812.c:

#include "WS2812.h"

void WS2812Init(void)
{

    // init GPIO as output
    ENABLE_GPIO_RCC();
    HAL_GPIO_WritePin(WS2812_GPIO_PORT, WS2812_GPIO_PIN, GPIO_PIN_RESET);
    HAL_GPIO_Init(WS2812_GPIO_PORT, &SW2812Pin);

    // init timer
    uint16_t targetFrequency = 1000; // 1kHz
    const uint16_t preScaler = 360;
    const uint16_t period = SystemCoreClock / (preScaler*targetFrequency);
    // clear status register
    __HAL_RCC_TIM4_CLK_ENABLE();

    ws2812TimerConfig.Instance = WS2812_SELECTED_TIMER;
    ws2812TimerConfig.Init.Prescaler = preScaler - 1;
    ws2812TimerConfig.Init.Period = period;
    ws2812TimerConfig.Init.CounterMode = TIM_COUNTERMODE_UP;

    HAL_TIM_Base_Init(&ws2812TimerConfig); // <- linker can not find this function

    __HAL_TIM_ENABLE(&ws2812TimerConfig);

}

这是我的包含结构:

main-&GT;

  • 包括“WS2812.h” - &gt;
    • 包括stm32f1xx_hal_tim.h

stm32f1xx_hal_tim.h位于STM32F1xxHAL_DRIVER-&gt; inc中,它也放在包含路径中。

我还在项目属性中添加了包含路径 - > C / C ++ Build-&gt; Settings 为了

  • GNU ARM Cross Assembler
  • GNU ARM Cross C编译器
  • GNU ARM Cross C ++编译器

我在互联网上搜索发现这是一个链接器问题,链接器无法找到正确的链接源。

我在互联网上发现并尝试过:

  • 将内容stm32f1xx_hal_tim.h和WS2812.h的文件夹添加到项目属性 - > C / C ++ Build - &gt; GNU ARM Cross C ++链接器 - &gt;图书馆 - &gt; (-L)

  • 将内容stm32f1xx_hal_tim.c和WS2812.c的文件夹添加到项目属性 - &gt; C / C ++ Build - &gt; GNU ARM Cross C ++链接器 - &gt;图书馆 - &gt; (-L)

  • 选中“stm32f1xx_hal_tim.h” - &gt;财产而&GT;未选中从构建中排除资源(互联网中的某些人通过此解决了问题)

  • 在链接器选项中添加了“--specs = nano.specs”

以上所有都无法解决问题。

有些人建议修改makefile。但是项目会自动生成makefile,所以我不知道从哪里开始。

如果有人可以提供提示或解决方案,那将非常感激。

更新1:

感谢JacekŚlimok的意见。

我不知道,我还需要为.c文件执行“从构建中排除”。我检查文件浏览器。 .c文件不会检入此配置。你的意思是这样的吗? excluded from Build

stm32f1xx_hal_tim.c在project-&gt; Driver-&gt; STM32F1xxHAL_Driver-&gt; Src

此时此问题仍未解决。

我注意到的另一件事是,Eclipse以不同的方式读取了我的stm32f1xx_hal_tim.c。当我在Eclipse中打开stm32f1xx_hal_tim.c时,它只给我一个像普通记事本一样的平面文本:

stm32f1xx_hal_tim.c

但是像stm32f1xx_hal_gpio.c这样的其他.c文件看起来很正常。 stm32f1xx_hal_gpio.c

它们位于同一个文件夹中。我不知道这种差异来自何处和原因。这是否与我的问题有关。

UPDATE2

@JacekŚlimok,我发现为什么eclipse将stm32f1xx_hal_tim.c视为平面文本。我不小心打开了Preference中的Scalability设置 - &gt;编辑器,stm32f1xx_hal_tim.c文件大小相对较大,为161kB。将其更改回默认值后,Eclipse会将文件显示为正常。但链接器问题仍然存在......

在main.c中我还使用了stm32f1xx_hal_gpio.h / .c中的HAL_GPIO_TogglePin()。链接器不会抱怨这一点。目前我无法区分这两个文件(stm32f1xx_hal_gpio和stm32f1xx_hal_tim)之间的区别。它们位于同一个文件夹中,并且包含相同的文件。但我可以使用GPIO的功能而不是Timer。

但有一点可以肯定: 我可以在stm32f1xx_hal_tim.h中使用宏,所以这是一个链接器问题。

我根据另一个项目启动这个项目,该项目是从STM32CubeMX生成的。为了练习定时器功能,我给它添加了定时器配置,这是我遇到链接器问题的一点。

我希望这些信息可以带来更多提示。

更新3

我尝试单独构建.c文件

对于stm32f1xx_hal.h.c:

00:09:16 **** Building Selected Files of configuration Release for project TimerTest ****
Info: Internal Builder is used for build
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wall -Wextra -g -DSTM32F103xB -DHSE_VALUE=8000000 "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Device\\ST\\STM32F1xx\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\STM32F1xx_HAL_Driver\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Class\\CDC\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Core\\Inc" -std=gnu11 -c -o "Drivers\\STM32F1xx_HAL_Driver\\Src\\stm32f1xx_hal_tim.o" "..\\Drivers\\STM32F1xx_HAL_Driver\\Src\\stm32f1xx_hal_tim.c" 

00:09:17 Build Finished (took 285ms)

对于WS2812.c:

00:11:23 **** Building Selected Files of configuration Release for project TimerTest ****
Info: Internal Builder is used for build
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wall -Wextra -g -DSTM32F103xB -DHSE_VALUE=8000000 "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Device\\ST\\STM32F1xx\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\STM32F1xx_HAL_Driver\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Class\\CDC\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Core\\Inc" -std=gnu11 -c -o "Src\\WS2812.o" "..\\Src\\WS2812.c" 

00:11:23 Build Finished (took 275ms)

对于Main.c:

00:12:02 **** Building Selected Files of configuration Release for project TimerTest ****
Info: Internal Builder is used for build
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wall -Wextra -g -DSTM32F103xB -DHSE_VALUE=8000000 "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Device\\ST\\STM32F1xx\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\STM32F1xx_HAL_Driver\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Class\\CDC\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Core\\Inc" -std=gnu11 -c -o "Src\\main.o" "..\\Src\\main.c" 
..\Src\main.c: In function '_Error_Handler':
..\Src\main.c:268:27: warning: unused parameter 'file' [-Wunused-parameter]
 void _Error_Handler(char *file, int line)
                           ^~~~
..\Src\main.c:268:37: warning: unused parameter 'line' [-Wunused-parameter]
 void _Error_Handler(char *file, int line)
                                     ^~~~
In file included from ..\Src\main.c:55:0:
At top level:
C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Inc/WS2812.h:36:26: warning: 'ws2812TimerConfig' defined but not used [-Wunused-variable]
 static TIM_HandleTypeDef ws2812TimerConfig;
                          ^~~~~~~~~~~~~~~~~
C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Inc/WS2812.h:26:25: warning: 'SW2812Pin' defined but not used [-Wunused-variable]
 static GPIO_InitTypeDef SW2812Pin = {
                         ^~~~~~~~~

00:12:02 Build Finished (took 272ms)

main.c中几乎没有警告,但它们并不重要。

UPDATE4:

感谢JacekŚlimok的意见:

我发现stm32f1xx_hal_tim.c的功能在文件浏览器中显示为灰色。

functions seems like not usable

但是stm32f1xx_hal_gpio.c中的函数显示出稳固的黑色。

function in gpio.c are usable

现在存在差异,只需找出原因。

提前致谢。 最好的问候。

3 个答案:

答案 0 :(得分:2)

执行#include stm32f1xx_hal_tim.h是不够的 - 它只会导致编译器不要抱怨,链接器仍会出现问题。也没有为链接器添加搜索路径 - 主要是当您使用静态预编译库并使用-l选项明确链接时。 HAL不是静态库,而是您自己编译的库。

要解决您的问题,请确保编译相应的源文件 - 在本例中为stm32f1xx_hal_tim.c文件,并且稍后将其链接。您提到您使用Eclipse,并且默认情况下它会生成一个Makefile,该文件会导致您在项目中编译的所有源文件也被链接。因此,您主要应检查是否正在编译stm32f1xx_hal_tim.c。一种方法是在Project Explorer中找到该文件,右键单击它并选择Resource Configurations -> Exclude from Build...。确保没有选中它。如果是,则可能是整个目录从构建中排除,它不应该是。

另一种可能性是,在编译的任何源文件中或函数签名(名称,返回类型和参数类型)不匹配时,不会定义函数。

另一种可能性(在这种情况下证明是问题的根源)是由于#if / #ifdef预处理器指令,可能无法编译文件的一部分。在OP的情况下,这是由HAL_TIM_MODULE_ENABLED未定义引起的。

答案 1 :(得分:0)

它与链接器问题无关,而是预处理器。

正如我所提到的,我正在基于一个从cubeMX生成的项目构建此代码。在上一个项目中,没有使用或配置计时器。比我开始编写定时器配置。我忘记的是取消注释stm32f1xx_hal_conf.h中的#define HAL_TIM_MODULE_ENABLED。这阻止了预处理器在stm32f1xx_hal_tim.c中的所有实现。

这就是为什么eclipse将stm32f1xx_hal_tim.c中的所有函数显示为灰色并且无法被引用的原因。

无论如何,感谢JacekŚlimok的努力!

答案 2 :(得分:0)

同意Jacek Slimok,不久前遇到了这个问题,由于某种原因,我一直忘记如何解决它。每次烦人时都要使用相同的解决方案。

只需跳至解决方案 因此,您按下ctrl + space并自动完成功能可以找到您要调用的函数。 但是在构建过程中,错误会显示为“未定义的对YOUR_FUNCTION_NAME的引用”。

因此,您将依赖项编译为目标文件,但将目标文件链接以形成由编译器生成的可执行“固件”。

main中调用的“未定义引用”功能应该来自链接器无法找到的目标文件。

Eclipse具有一项功能,允许您从“构建”到目标文件中排除某些文件。因此,链接器无法找到该依赖项。

解决方案: 这适用于Eclipse中添加的文件夹或单个文件。 因此,您拥有创建的.c和.h文件,有时将它们放在添加到eclipse的文件夹中。

右键单击添加的文件夹,然后单击属性。 在左侧菜单中,选择“ C / C ++ Build”下的“ Settings”。 在右侧,取消选中“从构建中排除资源”。 链接到下面的图片。

Eclipse中的“文件夹属性”窗口:

Folder Properties window in Eclipse

希望能在几天之内帮助所有人和我自己。当我在此帖子上看到我的名字时,您能想象一下震惊吗?