Настройка IDE Clion и Cmake для работы с STM32 и C++

в 14:25, , рубрики: c++, CLion, cmake, stm32, программирование микроконтроллеров

Перед примером моей настройки немного лирики.

Давно хотел попробовать себя в микроконтроллерах, вернее были идеи с их использованием, которые очень хотелось реализовать. Сначала начал с PIC32 — огонь контроллеры. Так получалось, что поначалу и коротил их порты, и с питанием завышал — неубиваемые (не совсем конечно, порт правда однажды сгорел, но сам контроллер продолжал работу). IDE MplabX неплоха, подкупал графический блок с отображением занимаемой RAM/Flash на выбранном МК — удобно, но сам NetBeans как IDE это жесть, ну не удобно ни разу после Idea. Но проблема была не в этом — как потом оказалось, PIC'и тяжело достать, мало кто их возит, а если и возит, то по относительно высокой цене.

Дальше решил копнуть в сторону STM32 — они в больших количествах, за базовую периферию просят не много, но главное — это доставаемость. (Но кодогенератор STM'а хуже Microchip'a — весь файл загажен комментами и функциями, это конечно сильно огорчило. У Microchip'а все сгенеренные функции вынесены в отдельные файлы и main.c практически чист — прелесть).
Теперь об IDE для STM32.

Попробовал хваленый Keil — конечно получше блокнота, но ужасно не удобный (ни нормальных подсказок, ни нормального форматирования, после Idea в общем не то пальто, особенно я так и не понял как создавать пакеты, почему нельзя просто в окошке ткнуть создать пакет и продолжить — матюгаться хочется).

Потом попробовал CooCox — гораздо лучше и приятнее интерфейс, хорошо настраивается форматирование (прям порадовала настройка переноса параметров в методах, да и другие настройки очень кстати), но опять же не хватало многих плюшек от Idea и опять же проблемы с организацией пакетов.

Clion почти та же Idea только для C/C++ и сразу захотелось ее прикрутить, но как оказалось довольно проблематично (особенно для человека, который с плюсами-то не силен, особенно со всякими сборщиками и компиляторами, парой сотен опций компиляции). Начал с блога JetBrains. Довольно подробно описано, но это для прошлых версий STM32CubeMX, в новой немного поменялась структура каталогов, в результате чего я некоторое время не понимал почему не компилится. Потом разобрался — изменил пути, для cortex-m3 убрал параметры -mfpu. Но опять не компилился. Дальше оказалось, что я не тот компилятор установил, вернее просто скачал его, но не указал путь к нему в файле сборки (ну сложновато поздно вечером думать).

Главное в Clion'е поставить галочку в настройках 'Automaticaly Reload Cmake Project on Edit' (Settings -> Build, Execution, Deployment -> Cmake), тогда после правок не нужно ничего очищать вручную.

Еще из изменений — дебаггер, упомянутый в блоге, переименовали в Ozone, его еще не тестил, позже отпишусь.

И последняя проблема, сверлившая мозг. Очень хотелось ООП, но не компилился проект если я добавлял C++ файл, куча ошибок с не найденными функциями (например, _exit, _sbrk и пр.). Здесь проблем было 2:

  • в файле CMakeLists.txt в блоге JetBrains не был выставлен флаг CXX в директиве project (нужен для файлов C++)
  • для исправления ошибок в файле из блога не хватало опций -specs=nosys.specs -specs=nano.specs после опции -gc-sections. Они как раз создают эти прототипы или наоборот игнорят эти методы (тут не могу точно сказать)

После этого проект нормально стал компилиться и размер его стал в пределах нормы (без опции -specs=nano.specs размер был в 10 раз больше для пустого проекта примерно 110 кб., с опцией — 18 кб.)

Итак, что я сделал:

  1. ставим Clion
  2. заходим в настройки (Settings -> Build, Execution, Deployment -> Cmake) и ставим галочку 'Automaticaly Reload Cmake Project on Edit'
  3. здесь же вписываем в поле Cmake options параметр -DCMAKE_TOOLCHAIN_FILE=STM32L1xx.cmake и в поле Generation path ставим build (если поменять, то в файлах CMakeLists.txt и STM32L1xx.cmake нужно его тоже будет поменять)
  4. ставим ARM компилятор (здесь брал)
  5. импортируем проект (который предварительно сгенерировали в STM32CubeMx), говорим, что можно создать CMakeLists.txt
  6. отсюда или из моего репозитория копируем содержимое CMakeLists.txt в созданный в Clion'e и добавляем файл STM32L1xx.cmake (можно обозвать как угодно)
  7. в STM32L1xx.cmake правим имя проекта в директиве project и можно убрать CXX если не нужен C++
  8. заменить в файле CMakeLists.txt в директиве add_definitions(-DSTM32L100xC) на свой контроллер
  9. для надежности можно сделать: Tools -> Cmake -> Reset Cache and Reload project и потом Tools -> Cmake -> Reload Cmake Project
  10. теперь можно сбилдить

Файл CMakeLists.txt

project(Skeleton C CXX ASM)
cmake_minimum_required(VERSION 3.5.0)

add_definitions(-DSTM32L100xC)

set(FREERTOS_DIR Middlewares/Third_Party/FreeRTOS/Source/)

file(GLOB_RECURSE USER_SOURCES "Src/*.c")
file(GLOB_RECURSE HAL_SOURCES "Drivers/STM32L1xx_HAL_Driver/Src/*.c")
file(
    GLOB_RECURSE
    FREERTOS_SOURCES
    "${FREERTOS_DIR}/*.c"
    "${FREERTOS_DIR}/CMSIS_RTOS/*.c"
    "${FREERTOS_DIR}/portable/GCC/ARM_CM3/*.c"
)

add_library(
    CMSIS
    Src/system_stm32l1xx.c
    startup/startup_stm32l100xc.s
)

include_directories(Inc)
include_directories(Src/gps/parser/nmea)
include_directories(Drivers/STM32L1xx_HAL_Driver/Inc)
include_directories(Drivers/CMSIS/Include)
include_directories(Drivers/CMSIS/Device/ST/STM32L1xx/Include)

include_directories(${FREERTOS_DIR})
include_directories(${FREERTOS_DIR}/CMSIS_RTOS)
include_directories(${FREERTOS_DIR}/include)
include_directories(${FREERTOS_DIR}/portable/GCC/ARM_CM3/)
include_directories(${FREERTOS_DIR}/portable/GCC/MemMang)

add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${HAL_SOURCES} ${LINKER_SCRIPT} ${FREERTOS_SOURCES})

target_link_libraries(${PROJECT_NAME}.elf CMSIS)

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.map")
set(HEX_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.bin)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMENT "Building ${HEX_FILE} nBuilding ${BIN_FILE}")

Файл STM32L1xx.cmake:

INCLUDE(CMakeForceCompiler)

SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_VERSION 1)

# Specify the cross compiler. arm-none-eabi-gcc and arm-none-eabi-g++ are full path required
CMAKE_FORCE_C_COMPILER(arm-none-eabi-gcc GNU)
CMAKE_FORCE_CXX_COMPILER(arm-none-eabi-g++ GNU)

SET(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/STM32L100RCTx_FLASH.ld)
SET(COMMON_FLAGS "-mcpu=cortex-m3 -O2 -mthumb -ffunction-sections -fdata-sections -g -fno-common -fmessage-length=0")
SET(CMAKE_CXX_FLAGS_INIT "${COMMON_FLAGS} -std=c++11")
SET(CMAKE_C_FLAGS_INIT "${COMMON_FLAGS} -std=gnu99")
SET(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,-gc-sections -specs=nosys.specs -specs=nano.specs -T ${LINKER_SCRIPT}")

Работать стало приятно, но пока заливаю прошивку через STM'овскую утилиту, позже попробую накрутить OZONE. На вопросы отвечу (если смогу).

Автор: MSerega

Источник

Поделиться

* - обязательные к заполнению поля