STM32 GNU ARM 链接器:未定义对 function() 与 eclipse 的引用
STM32 GNU ARM Linker: undefined reference to function() with eclipse
我目前正在用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);
}
这是我的包含结构:
主要->
- 包括"WS2812.h" ->
- 包括stm32f1xx_hal_tim.h
stm32f1xx_hal_tim.h在STM32F1xxHAL_DRIVER->inc中,也放在include路径中
我在project properties->C/C++ Build->Settings中也添加了include路径
- GNU ARM 交叉汇编程序
- GNU ARM Cross C 编译器
- GNU ARM 交叉 C++ 编译器
我在互联网上搜索发现这是一个链接器问题,链接器无法找到正确的链接源。
我在网上找到并尝试过的:
将内容stm32f1xx_hal_tim.h和WS2812.h的文件夹添加到项目属性-> C/C++构建-> GNU ARM Cross C++链接器->库- > (-L)
将内容stm32f1xx_hal_tim.c和WS2812.c的文件夹添加到项目属性-> C/C++构建-> GNU ARM Cross C++链接器->库- > (-L)
勾选"stm32f1xx_hal_tim.h" -> 属性->Exclude resource from build 未勾选(网上有人解决了这个问题)
在链接器选项中添加了“--specs=nano.specs”
以上都不能解决问题
有人建议修改makefile。但是项目是自动生成makefile的,不知从何下手
如有高人指点或解决,不胜感激
更新 1:
感谢 Jacek Şlimok 的投入。
我不知道,我还需要为 .c 文件做 "exclude from build"。然后我检查文件浏览器。 .c 文件不检查此配置。你是说这样吗?
excluded from Build
stm32f1xx_hal_tim.c在project->Driver->STM32F1xxHAL_Driver->Src
下
目前问题未解决
我注意到的另一件事是,Eclipse 以不同的方式读取我的 stm32f1xx_hal_tim.c。当我在 Eclipse 中打开 stm32f1xx_hal_tim.c 时,它只是给我一个平面文本,就像在普通记事本中一样:
stm32f1xx_hal_tim.c
但是 stm32f1xx_hal_gpio.c 等其他 .c 文件看起来正常。
stm32f1xx_hal_gpio.c
它们在同一个文件夹中。我不知道这种差异来自哪里以及为什么。这与我的问题有关吗?
更新2
@Jacek Şlimok,我发现了为什么日食将 stm32f1xx_hal_tim.c 视为平面文本。我不小心在Preference-> Editor中打开了Scalability设置,stm32f1xx_hal_tim.c文件比较大,161kB。在我将它改回默认值后,Eclipse 正常显示该文件。但是链接器问题仍然存在...
在 main.c 中,我还使用了 stm32f1xx_hal_gpio.h/.c 中的 HAL_GPIO_TogglePin()。链接器不会抱怨这一点。目前我无法分辨这两个文件(stm32f1xx_hal_gpio 和 stm32f1xx_hal_tim)之间的区别,它们位于同一个文件夹中,并且包含的内容也相同。但是我可以使用 GPIO 的功能而不是定时器。
但是可以肯定的是:
我可以在 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中的警告很少,但并不重要。
更新4:
感谢 Jacek Şlimok 的输入:
我发现 stm32f1xx_hal_tim.c 的功能在文件浏览器中显示为灰色。
functions seems like not usable
但是stm32f1xx_hal_gpio.c中的函数显示为黑色
function in gpio.c are usable
现在区别已经存在了,只需要找出原因。
提前致谢。
最好的问候。
做 #include stm32f1xx_hal_tim.h
是不够的 - 它只会让你的编译器不抱怨,linker 仍然会有问题。也没有为 linker 添加搜索路径——这个你主要在你有静态预编译库时使用,你使用 -l
选项显式 link。 HAL 不是静态库,而是您自己编译的库。
要解决您的问题,请确保您编译了相应的源文件 - 在本例中为 stm32f1xx_hal_tim.c
文件,稍后将对其进行 link 编辑。您提到您使用 Eclipse,默认情况下它会生成一个 Makefile,使您在项目中编译的所有源文件也被 linked。所以你主要应该检查stm32f1xx_hal_tim.c
是否正在编译。一种方法是在 Project Explorer 中找到该文件,右键单击它并 select Resource Configurations -> Exclude from Build...
。确保它没有被选中。如果是,很可能整个目录都被排除在构建之外,而它不应该被排除。
另一种可能性是给定函数未在任何编译的源文件中定义或函数签名(名称、return 类型和参数类型)不匹配。
还有另一种可能性(在这种情况下被证明是问题的根源)是文件的一部分可能由于 #if
/#ifdef
预处理器指令而无法编译.在 OP 的情况下,这是由 HAL_TIM_MODULE_ENABLED
未定义引起的。
这与链接器问题无关,而是与预处理器有关。
正如我提到的,我正在基于一个项目构建此代码,该项目是从 cubeMX 生成的。在之前的项目中,没有使用或配置定时器。比我开始写定时器配置。我忘记了取消注释 stm32f1xx_hal_conf.h 中的#define HAL_TIM_MODULE_ENABLED。预处理器阻止了 stm32f1xx_hal_tim.c 中的所有实现。
这就是为什么eclipse将stm32f1xx_hal_tim.c中的所有函数显示为灰色,无法引用的原因。
无论如何,感谢 Jacek Şlimok 的努力!
同意 Jacek Slimok 的观点,前阵子遇到过这个问题,但出于某种原因,我一直忘记如何解决它。如果变得烦人,每次都在谷歌上搜索相同的解决方案。
直接跳到解决方案
因此,您按下 ctrl+space,自动完成功能会找到您要调用的函数。
然而在构建中,错误显示为 "undefined reference to YOUR_FUNCTION_NAME".
因此,您编译依赖项成为目标文件,但 link 目标文件形成编译器生成的可执行文件 "firmware"。
在 main 中调用的 "undefined reference" 函数应该来自 link 用户无法找到的目标文件。
Eclipse 具有一项功能,允许您将某些文件排除在 "built" 目标文件之外。因此 linker 无法找到该依赖项。
解法:
这适用于 Eclipse 中添加的文件夹或单个文件。
因此,您创建了 .c 和 .h 文件,有时您将它们集中在添加到 eclipse 的文件夹中。
右键单击添加的文件夹并点击属性。
在左侧菜单 select "Settings" 下 "C/C++ Build"。
在右侧,取消选中 "Exclude resource from build"。
Link到下图。
Eclipse 中的文件夹属性 window:
希望这对大家有帮助,还有几天后我忘记的我自己。你能想象当我在这个 post 上看到我的名字时的震惊吗?
我目前正在用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);
}
这是我的包含结构:
主要->
- 包括"WS2812.h" ->
- 包括stm32f1xx_hal_tim.h
stm32f1xx_hal_tim.h在STM32F1xxHAL_DRIVER->inc中,也放在include路径中
我在project properties->C/C++ Build->Settings中也添加了include路径
- GNU ARM 交叉汇编程序
- GNU ARM Cross C 编译器
- GNU ARM 交叉 C++ 编译器
我在互联网上搜索发现这是一个链接器问题,链接器无法找到正确的链接源。
我在网上找到并尝试过的:
将内容stm32f1xx_hal_tim.h和WS2812.h的文件夹添加到项目属性-> C/C++构建-> GNU ARM Cross C++链接器->库- > (-L)
将内容stm32f1xx_hal_tim.c和WS2812.c的文件夹添加到项目属性-> C/C++构建-> GNU ARM Cross C++链接器->库- > (-L)
勾选"stm32f1xx_hal_tim.h" -> 属性->Exclude resource from build 未勾选(网上有人解决了这个问题)
在链接器选项中添加了“--specs=nano.specs”
以上都不能解决问题
有人建议修改makefile。但是项目是自动生成makefile的,不知从何下手
如有高人指点或解决,不胜感激
更新 1:
感谢 Jacek Şlimok 的投入。
我不知道,我还需要为 .c 文件做 "exclude from build"。然后我检查文件浏览器。 .c 文件不检查此配置。你是说这样吗? excluded from Build
stm32f1xx_hal_tim.c在project->Driver->STM32F1xxHAL_Driver->Src
下目前问题未解决
我注意到的另一件事是,Eclipse 以不同的方式读取我的 stm32f1xx_hal_tim.c。当我在 Eclipse 中打开 stm32f1xx_hal_tim.c 时,它只是给我一个平面文本,就像在普通记事本中一样:
stm32f1xx_hal_tim.c
但是 stm32f1xx_hal_gpio.c 等其他 .c 文件看起来正常。 stm32f1xx_hal_gpio.c
它们在同一个文件夹中。我不知道这种差异来自哪里以及为什么。这与我的问题有关吗?
更新2
@Jacek Şlimok,我发现了为什么日食将 stm32f1xx_hal_tim.c 视为平面文本。我不小心在Preference-> Editor中打开了Scalability设置,stm32f1xx_hal_tim.c文件比较大,161kB。在我将它改回默认值后,Eclipse 正常显示该文件。但是链接器问题仍然存在...
在 main.c 中,我还使用了 stm32f1xx_hal_gpio.h/.c 中的 HAL_GPIO_TogglePin()。链接器不会抱怨这一点。目前我无法分辨这两个文件(stm32f1xx_hal_gpio 和 stm32f1xx_hal_tim)之间的区别,它们位于同一个文件夹中,并且包含的内容也相同。但是我可以使用 GPIO 的功能而不是定时器。
但是可以肯定的是: 我可以在 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中的警告很少,但并不重要。
更新4:
感谢 Jacek Şlimok 的输入:
我发现 stm32f1xx_hal_tim.c 的功能在文件浏览器中显示为灰色。
functions seems like not usable
但是stm32f1xx_hal_gpio.c中的函数显示为黑色
function in gpio.c are usable
现在区别已经存在了,只需要找出原因。
提前致谢。 最好的问候。
做 #include stm32f1xx_hal_tim.h
是不够的 - 它只会让你的编译器不抱怨,linker 仍然会有问题。也没有为 linker 添加搜索路径——这个你主要在你有静态预编译库时使用,你使用 -l
选项显式 link。 HAL 不是静态库,而是您自己编译的库。
要解决您的问题,请确保您编译了相应的源文件 - 在本例中为 stm32f1xx_hal_tim.c
文件,稍后将对其进行 link 编辑。您提到您使用 Eclipse,默认情况下它会生成一个 Makefile,使您在项目中编译的所有源文件也被 linked。所以你主要应该检查stm32f1xx_hal_tim.c
是否正在编译。一种方法是在 Project Explorer 中找到该文件,右键单击它并 select Resource Configurations -> Exclude from Build...
。确保它没有被选中。如果是,很可能整个目录都被排除在构建之外,而它不应该被排除。
另一种可能性是给定函数未在任何编译的源文件中定义或函数签名(名称、return 类型和参数类型)不匹配。
还有另一种可能性(在这种情况下被证明是问题的根源)是文件的一部分可能由于 #if
/#ifdef
预处理器指令而无法编译.在 OP 的情况下,这是由 HAL_TIM_MODULE_ENABLED
未定义引起的。
这与链接器问题无关,而是与预处理器有关。
正如我提到的,我正在基于一个项目构建此代码,该项目是从 cubeMX 生成的。在之前的项目中,没有使用或配置定时器。比我开始写定时器配置。我忘记了取消注释 stm32f1xx_hal_conf.h 中的#define HAL_TIM_MODULE_ENABLED。预处理器阻止了 stm32f1xx_hal_tim.c 中的所有实现。
这就是为什么eclipse将stm32f1xx_hal_tim.c中的所有函数显示为灰色,无法引用的原因。
无论如何,感谢 Jacek Şlimok 的努力!
同意 Jacek Slimok 的观点,前阵子遇到过这个问题,但出于某种原因,我一直忘记如何解决它。如果变得烦人,每次都在谷歌上搜索相同的解决方案。
直接跳到解决方案 因此,您按下 ctrl+space,自动完成功能会找到您要调用的函数。 然而在构建中,错误显示为 "undefined reference to YOUR_FUNCTION_NAME".
因此,您编译依赖项成为目标文件,但 link 目标文件形成编译器生成的可执行文件 "firmware"。
在 main 中调用的 "undefined reference" 函数应该来自 link 用户无法找到的目标文件。
Eclipse 具有一项功能,允许您将某些文件排除在 "built" 目标文件之外。因此 linker 无法找到该依赖项。
解法: 这适用于 Eclipse 中添加的文件夹或单个文件。 因此,您创建了 .c 和 .h 文件,有时您将它们集中在添加到 eclipse 的文件夹中。
右键单击添加的文件夹并点击属性。 在左侧菜单 select "Settings" 下 "C/C++ Build"。 在右侧,取消选中 "Exclude resource from build"。 Link到下图。
Eclipse 中的文件夹属性 window:
希望这对大家有帮助,还有几天后我忘记的我自己。你能想象当我在这个 post 上看到我的名字时的震惊吗?