STM32 GNU ARM Linker: неопределенная ссылка на функцию () с затмением - PullRequest
0 голосов
/ 06 июня 2018

В настоящее время я изучаю STM32F103 с Eclipse.Я столкнулся с проблемой на этапе компоновки, что я получил ошибку компоновщика: неопределенная ссылка на `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 ->

  • include "WS2812.h" ->
    • include stm32f1xx_hal_tim.h

stm32f1xx_hal_tim.h находится в STM32F1xxHAL_DRIVER-> inc, то естьтакже укажите путь включения.

Я также добавил путь включения в свойствах проекта-> C / C ++ Build-> Настройки для

  • GNU ARM Cross Assembler
  • Компилятор GNU ARM Cross C
  • Компилятор GNU ARM Cross C ++

Я искал в Интернете, обнаружил, что это проблема компоновщика, что компоновщик не может найти правильный источникдля связи.

То, что я нашел в интернете и попробовал:

  • добавил папку, содержимое которой stm32f1xx_hal_tim.h и WS2812.h в свойствах проекта-> Сборка C / C ++ -> GNU ARM Cross C ++ Linker -> Библиотеки -> (-L)

  • добавили папку, в которой содержатся stm32f1xx_hal_tim.c и WS2812.c к свойствам проекта-> Сборка C / C ++ -> GNU ARM Cross C ++ Linker -> Библиотеки -> (-L)

  • Проверено "stm32f1xx_hal_tim.h" -> property->Параметр «Исключить ресурс из сборки» снят (некоторые пользователи в Интернете решили эту проблему)

  • В параметры компоновщика добавлено «--specs = nano.specs»

Все вышеперечисленное не решает проблему.

Некоторые люди предлагают изменить make-файл.Но проект генерирует make-файл автоматически, поэтому я не знаю, с чего начать.

Если кто-то может дать подсказку или решение, это будет очень благодарно.

ОБНОВЛЕНИЕ 1:

Спасибо за вклад Ясека Элимока.

Я не знал этого, мне также нужно сделать «исключить из сборки» для .c файлов.И я проверяю в файловом браузере.Файлы .c не проверяются в этой конфигурации.Вы имеете в виду, как это? исключено из сборки

Файл stm32f1xx_hal_tim.c находится в проекте-> Driver-> STM32F1xxHAL_Driver-> Src

На данный момент проблема остается нерешенной.

Еще одна вещь, которую я заметил, это то, что Eclipse по-другому читает мой stm32f1xx_hal_tim.c.Когда я открываю stm32f1xx_hal_tim.c в Eclipse, он просто дает мне плоский текст, как в обычном блокноте:

stm32f1xx_hal_tim.c

Но другой файл .c, например stm32f1xx_hal_gpio.c выглядит нормально. stm32f1xx_hal_gpio.c

Они находятся в одной папке.Я не знаю, откуда и почему возникла эта разница.Относится ли это к моей проблеме.

Update2

@ Jacek Ślimok, я выяснил, почему затмение видит stm32f1xx_hal_tim.c в виде плоского текста.Я случайно включил параметр Масштабируемость в Предпочтения-> Редактор, файл stm32f1xx_hal_tim.c имеет относительно большой размер файла - 161 КБ.После того как я верну значение по умолчанию, Eclipse покажет файл как обычно.Но проблема компоновщика все еще существует ...

В main.c я также использовал HAL_GPIO_TogglePin () из stm32f1xx_hal_gpio.h / .c.Компоновщик не жалуется на это.В настоящее время я не могу сказать разницу между этими двумя файлами (stm32f1xx_hal_gpio и stm32f1xx_hal_tim). Они находятся в одной папке и также включены в нее.Но я могу использовать функцию для GPIO, а не для таймера.

Но одна вещь может быть уверена: я могу использовать макрос в stm32f1xx_hal_tim.h, так что это проблема компоновщика.

Я запускаю этот проект на основе другого проекта, который был сгенерирован изSTM32CubeMX.Чтобы попрактиковаться в использовании функции таймера, я добавил к ней конфигурацию таймера. В этом и заключается проблема с компоновщиком.

Надеюсь, эта информация может привести к дополнительным подсказкам.

Обновление 3

Я пытался собрать файлы .c отдельно

Для stm32f1xx_hal.hc:

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:

Спасибо за ввод Яцека Элимока:

Я обнаружил, что функции stm32f1xx_hal_tim.c показывают серый цвет в файлебраузер.

функции кажутся непригодными для использования

Но функции в stm32f1xx_hal_gpio.c показывают сплошную блокировку.

функция в gpio.cможно использовать

Теперь разница есть, просто нужно выяснить, почему.

Заранее спасибо.С наилучшими пожеланиями.

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Это связано не с проблемой компоновщика, а с препроцессором.

Как я уже говорил, я строю этот код на основе проекта, который был сгенерирован из cubeMX.В предыдущем проекте таймер не использовался и не настраивался.Чем я начал писать настройки таймера.То, что я забыл, это раскомментировать #define HAL_TIM_MODULE_ENABLED в stm32f1xx_hal_conf.h.Который заблокировал всю реализацию в stm32f1xx_hal_tim.c препроцессором.

Именно поэтому eclipse показывает все функции в stm32f1xx_hal_tim.c в сером цвете и не может ссылаться на них.

Ив любом случае, спасибо усилиям Яцека Элимока!

0 голосов
/ 06 июня 2018

Выполнение #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.В случае ОП это было вызвано тем, что HAL_TIM_MODULE_ENABLED не определено.

...