0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\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\$ – Brian Drummond Jan 27 '18 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 Jan 27 '18 at 23:44
  • \$\begingroup\$ @TomServo STM32 HAL is distributed in the the source files, not the compiled libraries. \$\endgroup\$ – P__J__ Jan 27 '18 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\$ – Brian Drummond Jan 27 '18 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\$ – P__J__ Jan 28 '18 at 0:08
1
\$\begingroup\$

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 ->

enter image description here

Browse the directory where you have generated the source code

enter image description here

Select the project. Check Copy project into workspace and Finish

And you are done.

\$\endgroup\$
  • 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 Jan 28 '18 at 12:52
  • \$\begingroup\$ install openStm32 which will install all the handy plugins. Forget the DIY for now \$\endgroup\$ – P__J__ Jan 28 '18 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 Jan 29 '18 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\$ – P__J__ Jan 29 '18 at 21:49
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.