Для сборки проекта, использующего воможности автоматической генерации кода HAL для указанного (или большинства других) микроконтроллеров следует выполнить такие шаги:
CMAKE_TOOLCHAIN_FILE
для обеспечения возможностей кросс-платфрменной компиляции
Для любого начинающего, первое погружение в технологию всегда сложно. И я не исключение.
Когда я решил использовать микроконтроллеры семейства arm в первый раз, то поразился, насколько разительна разница между самими микроконтроллерами и стеком программных технологий над ними. Совершенство микроконтроллеров полностью перекрывается страшно питекантропскими подходами для обеспечения удобства работы с ними.
Большинство комментариев от “сообщества”, которые мне удалось собрать относились к двум одинаково тупым (с моей дилетантской точки зрения) позициям:
И лишь небольшая часть людей относится взвешено и без фанатизма к проблеме, не переоценивает ценность всех этих “знаний” и, к сожалению, чаще всего не пишет никуда.
По-моему мнению, истина где-то там. Даташиты — это всегда прекрасно и читать их необходимо. Также здорово, когда средство разработки обеспечивает тебе самое главное: возможность быстрого и эфективного рефакторинга. Все эти блокноты с кнопками, вимы и прочие скрипты — это из 80-90 годов прошлого века. Заниматься этим может либо гений (я вполне допускаю это), либо идиот.
Всё это фигня, которая не относится к теме. Если мне будет интересно, то напишу позже свой анализ всей этой ситуации и причины появления автогенерации HAL для микроконтроллеров ST.
Cmake далеко не предел моих мечтаний. Жутко имплицитная штука. Работать с ней противно и я был вынужден делать это просто для сборки под CLion, который мне обоснованно нравится. Intellij (долгих им лета), одна из немногих российских компаний, которая за последние 15 лет вызывала у меня только гордость. Талантливые ребята, гениальные продукты.
По-моему мнению, как средство сборки, QBS от QtCreator лучше (a как среда разработки CLion совершенне, даже с несовершенным cmake). Лучше QBS ситема сборки тем, что это, по всей видимости, QBS это не набор “magic words”, а обычный JavaScript и он прозрачнее и предсказуемее, расширяемее и более отлаживаемый, чем cmake. В целом-же, вынужден констатировать, что за последние 30 лет мало что поменялось: сборка C, C++ и ASM это по-прежнему адская боль. Makefiles и прочий дремучий изврат оставляю на “профессионалов”. Им оно как-то сподручнее ковыряться в этом всём. В vim-е.
arm-none-eabi-gcc
для своей платформы
Загружаете STM32CubeMX. Запускаете. Генерируете.
На что обратить внимание НОВИЧКАМ:
Потом дуем в меню Project→Settings... и выбираем для кого компилируем. Берите SW4STM32. По-большому счёту, почти без разницы. Всё равно всё выпилим.
Всё объяснять нет никакого смысла. CubeMX реально понятен. По-крайней мере мне так кажется.
Закончив играться, жмём Project→Generate Code.
Тут всё понятно. Удаляем лишние файлы. На что обратить внимание:
STM32F103C8Tx_FLASH.ld
. ЕГО ОСТАВЛЯЕМ!
Drivers
, Inc
, Src
.
Отслальное:
“...резать к чёртовой матери не дожидаясь перетонита!” (С)
CMAKE_TOOLCHAIN_FILE
Когда создатели cmake создали и наслаждались своим творением, они думали об удобстве создания, сборки ПО на определённой платформе.
О кросс-компиляции они точно не думали. Поэтому всё, что касается кросс-компиляции было вкручено потом и на костылях. Главный такой костыль — файл, который они называют CMAKE_TOOLCHAIN_FILE
c расширением .cmake
, который указывается в качестве параметра, определяемого, когда cmake только стартует. Определяется в CLion он вот так:
Файл называется (в моём случае) STM32F103C8T6.cmake
и представляет собой приблизительно вот это:
STM32F103C8T6.cmake
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR cortex-m3)
# Find the cross compiler
find_program(ARM_CC arm-none-eabi-gcc
${TOOLCHAIN_DIR}/bin)
find_program(ARM_CXX arm-none-eabi-g++
${TOOLCHAIN_DIR}/bin)
find_program(ARM_OBJCOPY arm-none-eabi-objcopy
${TOOLCHAIN_DIR}/bin)
find_program(ARM_SIZE_TOOL arm-none-eabi-size
${TOOLCHAIN_DIR}/bin)
find_program(ARM_AS arm-none-eabi-as
${TOOLCHAIN_DIR}/bin)
CMAKE_FORCE_C_COMPILER(${ARM_CC} GNU)
CMAKE_FORCE_CXX_COMPILER(${ARM_CXX} GNU)
set(COMMON_FLAGS
"-fno-common -ffunction-sections -fdata-sections")
set(CMAKE_ASM_FLAGS
${CMAKE_ASM_FLAGS} "-mcpu=cortex-m3 -mthumb")
if (CMAKE_SYSTEM_PROCESSOR STREQUAL cortex-m3)
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS}
"-mcpu=cortex-m3 -mthumb -mthumb-interwork -msoft-float")
else ()
message(WARNING
Processor not recognised in toolchain file,
compiler flags not configured.)
endif ()
set(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/STM32F103C8Tx_FLASH.ld)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-gc-sections -T ${LINKER_SCRIPT}")
# fix long strings (CMake appends semicolons)
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")
set(BUILD_SHARED_LIBS OFF)
и позволяет собрать на текущей платформе код для другой-целевой. Короче — кросс-компиляция.
обратить внимание
TOOLCHAIN_DIR
)
Теперь мы определяем файл, который будет заниматься сборкой:
CMakeLists.txt
Его листинг для моего случая представлен ниже:
project(STM23F103C8T6 C CXX ASM)
cmake_minimum_required(VERSION 3.5.0)
set(CMAKE_VERBOSE_MAKEFILE ON)
add_definitions(-DSTM32F103x6)
file(GLOB_RECURSE USER_SOURCES Src/*.c)
file(GLOB_RECURSE HAL_SOURCES Drivers/STM32F1xx_HAL_Driver/Src/*.c)
add_library(CMSIS)
target_sources(CMSIS
PUBLIC
${PROJECT_SOURCE_DIR}/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c
${PROJECT_SOURCE_DIR}/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/startup_stm32f103xb.s)
include_directories(
Drivers/CMSIS/Device/ST/STM32F1xx/Include
Drivers/CMSIS/Include
Drivers/STM32F1xx_HAL_Driver/Inc
Inc)
add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${HAL_SOURCES} ${LINKER_SCRIPT})
target_link_libraries(${PROJECT_NAME}.elf CMSIS)
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})
Обратить внимание
add_definitions(-DSTM32F103x6)
— найдите соответствующий вашему uK дефинишен в заголовочном файле Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h
_start
. Его компиляция и компиляция ещё одного шаблонного файла объединены в малюсенькую библиотеку CMSIS.
Вроде всё. Если Вы всё сделали внимательно, то у вас после BuildAll должен получиться “папка”, с результатами компиляции.
Прошивка, отладка и т.п. будет дальше. Дальше будут и размышления, зачем нам нужен HAL, если есть регистры, зачем нам нужен рефакторинг, когда есть мозги и прочие темы. И так больше чем планировал нынче получилось.