EDIT: Edited in response to question in comment (1)
I'm trying to work through some examples from Carmine Noviello's book, Mastering STM32. In the chapter introducing timers, I adapted his very first example and am getting an "undefined reference" error for the function HAL_TIM_Base_Init
. I have other errors too, but one at a time...
Expected result: This code should compile, link and create the target, as I have the .h
file containing it in my Eclipse 'Includes Path' and am looking right at it in the header file as an "exported function". As an example, the typedef TIM_Base_InitTypeDef
compiles fine and it is in the same header file as the function that's throwing the error.
Actual result:
Invoking: MCU GCC Linker
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -specs=nosys.specs -specs=nano.specs -T"../STM32L476RGTx_FLASH.ld" -Wl,-Map=output.map -Wl,--gc-sections -o "cubemx.elf" @"objects.list" -lm
Src/main.o: In function `main':
D:\prj\NUCLEO-476RG-03\cubemx\Debug/../Src/main.c:112: undefined reference to `HAL_TIM_Base_Init'
D:\prj\NUCLEO-476RG-03\cubemx\Debug/../Src/main.c:113: undefined reference to `HAL_TIM_Base_Start_IT'
collect2.exe: error: ld returned 1 exit status
makefile:35: recipe for target 'cubemx.elf' failed
make: *** [cubemx.elf] Error 1
I used STM32CubeMX to create the basic clocks and setup GPIO, and all the calls from its generated code of course work fine. But this one function, which I see online in numerous examples of timer setup on the STM32, for some reason cannot compile. I cannot resolve this reference without some insight.
Source code (less the generated CubeMX clock and GPIO code, which is working):
#include "main.h"
#include "stm32l4xx_hal.h"
#include "stm32l4xx_hal_tim.h" // HEADER WITH THE FUNCTION IN IT
TIM_HandleTypeDef htim6;
/* Private function prototypes ---------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void TIM6_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim6);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM6)
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
}
int main(void)
{
HAL_Init();
htim6.Instance = TIM6;
htim6.Init.Prescaler = 47999; //48MHz/48000 = 1000Hz
htim6.Init.Period = 499; //1000HZ / 500 = 2Hz = 0.5s
__HAL_RCC_TIM6_CLK_ENABLE(); //Enable the TIM6 peripheral
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0); //Enable the peripheral IRQ
HAL_NVIC_EnableIRQ(TIM3_IRQn);
HAL_TIM_Base_Init(&htim6); //Configure the timer ERROR
HAL_TIM_Base_Start_IT(&htim6); //Start the timer ERROR
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
}
}
I feel as though if I could resolve this one error I'd have a pattern for resolving others that arise from generated library code from CubeMX under Eclipse and the OpenSTM tools and GCC compiler from AC6.
-
\$\begingroup\$ Is this a compiler or a linker error? Sounds like a linker error, are you linking all the right libraries and object files? Check the link options. \$\endgroup\$user16324– user163242018年01月27日 23:23:20 +00:00Commented Jan 27, 2018 at 23:23
-
\$\begingroup\$ I have all the same folders listed under project -> tool settings -> MCU GCC Linker -> Library Search Path as I do in the Eclipse project includes, and defined in the same order. \$\endgroup\$TomServo– TomServo2018年01月27日 23:44:41 +00:00Commented Jan 27, 2018 at 23:44
-
\$\begingroup\$ @TomServo STM32 HAL is distributed in the the source files, not the compiled libraries. \$\endgroup\$0___________– 0___________2018年01月27日 23:56:06 +00:00Commented Jan 27, 2018 at 23:56
-
\$\begingroup\$ Well you did edit the question, to add "ld returned 1 exit status". So it's a linker error. Fix the linker arguments, you probably need to add the appropriate .o file, or -l option if you compiled the HAL into a library. \$\endgroup\$user16324– user163242018年01月27日 23:58:49 +00:00Commented Jan 27, 2018 at 23:58
-
1\$\begingroup\$ @BrianDrummond he needs to add the source to his project not the .o files as the STM HAL is distributed as the source code files. \$\endgroup\$0___________– 0___________2018年01月28日 00:08:26 +00:00Commented Jan 28, 2018 at 0:08
2 Answers 2
You need to add all used HAL .c files to your project. The easiest way:
Download the CubeMx. Create the project for your micro. Configure the clock. You can also configure another peripherals (including the timers) - but you probably want to learn how to configure them - so do not use the Cube for it.
Next generate the project.
Then in the eclipse : File -> Import enter image description here
Next ->
Browse the directory where you have generated the source code
Select the project. Check Copy project into workspace and Finish
And you are done.
-
1\$\begingroup\$ I did this procedure and also the procedure where I launch Eclipse directly from Cube. Both achieve the same result; neither works to solve my linking problem. \$\endgroup\$TomServo– TomServo2018年01月28日 12:52:45 +00:00Commented Jan 28, 2018 at 12:52
-
\$\begingroup\$ install openStm32 which will install all the handy plugins. Forget the DIY for now \$\endgroup\$0___________– 0___________2018年01月28日 22:12:06 +00:00Commented Jan 28, 2018 at 22:12
-
\$\begingroup\$ I am using openSTM and CubeMX. I am configuring the pins and clocks in CubeMX, then exporting straight into the Eclipse/openSTM project. Same result as your well-documented procedure above. \$\endgroup\$TomServo– TomServo2018年01月29日 15:53:37 +00:00Commented Jan 29, 2018 at 15:53
-
\$\begingroup\$ I do it all the time. Created hundreds of projects. It always works. Can't help you. You have something wrong with your configurations, OS or toolchain. \$\endgroup\$0___________– 0___________2018年01月29日 21:49:19 +00:00Commented Jan 29, 2018 at 21:49
Check in your stm32l4xx_hal_conf.h
that
#define HAL_TIM_MODULE_ENABLED
is not commented out. If it is, you can remove the /* */
manually, or enable a timer in CubeMX, and let it generate the source again. Then you can omit #include "stm32l4xx_hal_tim.h"
from your code, because it will be already included by stm32l4xx_hal.h
.
This preprocessor symbol is checked in stm32l4xx_hal_tim.c
, and if it's not defined, then the file will be compiled to an empty stub. In their infinite wisdom, the software engineers at ST decided that it's not necessary to check these symbol in the headers, so when an unsuspecting user includes them, their code will compile without warnings or errors, because the declarations are there, but fail when linked, because the functions are not there.