Создание проекта в STM32CubeIDE

В STM32CubeIDE 2.2.0 откройте File → STM32 Project Create/Import → Create New STM32 Project → STM32 CMake Project. В мастере выберите микроконтроллер STM32F401RETx и тип проекта Executable. Назовите проект FirstProject. Укажите родительский каталог для проектов: IDE создаст внутри него папку с именем проекта.

Создание CMake-проекта для микроконтроллера STM32F401RETx.

STM32F401RETx обозначает семейство и корпус микроконтроллера, установленного на NUCLEO-F401RE. На этом шаге мы выбираем чип, для которого компилятор и компоновщик подготовят прошивку. Сам проект пока ничего не делает с выводами платы.

Файлы, созданные мастером

ФайлНазначение
CMakeLists.txt Перечисляет исходники, заголовочные пути, определения и параметры сборки.
CMakePresets.json Хранит настройки сборок Debug и Release.
cubeide-gcc.cmake Выбирает компиляторы arm-none-eabi-gcc и arm-none-eabi-g++.
Startup/startup_stm32f401retx.s Содержит таблицу векторов и код, запускаемый после сброса.
STM32F401RETX_FLASH.ld Размещает код и данные во Flash и RAM микроконтроллера.
Sources/main.c Исходная точка прикладной программы; позже переименуем файл в main.cpp.

Startup-файл и скрипт компоновщика остаются частью проекта при переходе на C++. Компилятор собирает исходники в объектные файлы, а компоновщик по правилам .ld создаёт прошивку в формате ELF. Вкладка CMake управляет составом этой прошивки.

Подключение CMSIS

Для обращения к регистрам по именам нужны две части CMSIS. CMSIS Core описывает ядро Cortex-M4, а CMSIS Device содержит определения для STM32F401, включая RCC и GPIOA. Добавим нужные файлы в сам проект FirstProject.

  1. Мы используем STM32CubeIDE 2.2.0. В этой версии IDE нет встроенного средства для загрузки пакетов STM32Cube, поэтому скачайте архив STM32CubeF4 с сайта ST (кнопка Get latest) и распакуйте его. В распакованном пакете найдите папку STM32Cube_FW_F4_V…/Drivers/CMSIS.
  2. В Project Explorer щёлкните правой кнопкой по FirstProject и выберите New → Folder: создайте папку Drivers. Так же создайте внутри неё папку CMSIS.
  3. В STM32CubeIDE выберите File → Import… → General → File System. В поле исходного каталога укажите папку Drivers/CMSIS внутри распакованного пакета STM32Cube_FW_F4_V…, а в качестве назначения — FirstProject/Drivers/CMSIS.
  4. В дереве импорта отметьте Core/Include, Device/ST/STM32F4xx/Include и файл Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c. Нажмите Finish. Сохраните вложенные каталоги: они нужны для путей в CMakeLists.txt.

Правки в CMakeLists.txt

Мастер уже заполнил списки PROJECT_SOURCES, PROJECT_DEFINES и PROJECT_INCLUDES в CMakeLists.txt. Сохраните их содержимое и добавьте в эти списки файлы CMSIS из папки проекта.

В существующий set(PROJECT_SOURCES ...) перед закрывающей скобкой добавьте строку:

    Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c

В существующий set(PROJECT_INCLUDES ...) перед закрывающей скобкой добавьте две строки:

    Drivers/CMSIS/Core/Include
    Drivers/CMSIS/Device/ST/STM32F4xx/Include

Если system_stm32f4xx.c или указанные каталоги CMSIS уже есть в списках мастера, не добавляйте их повторно. Проверьте также, что в существующем PROJECT_DEFINES есть STM32F401xE; добавьте его только при отсутствии. Пути Drivers/CMSIS/... отсчитываются от каталога FirstProject, где находится CMakeLists.txt. Определение STM32F401xE выбирает в заголовках описание нужного микроконтроллера. Файл system_stm32f4xx.c предоставляет SystemInit(), который вызывает startup-файл.

В этом же шаблоне проверьте согласованность параметров ядра и FPU: для STM32F401 используется Cortex-M4, -mfpu=fpv4-sp-d16 и -mfloat-abi=hard. Одинаковые настройки должны применяться ко всем C и C++ исходникам проекта.

Переход на C++20

Переименуйте Sources/main.c в Sources/main.cpp. В PROJECT_SOURCES замените строку Sources/main.c на Sources/main.cpp. Файлы syscalls.c, sysmem.c и system_stm32f4xx.c остаются исходниками C.

При переименовании удалите из сгенерированного файла блок с предупреждением FPU is not initialized. Startup-файл вызывает SystemInit() из system_stm32f4xx.c до main(); этот код включает FPU. Оставшееся предупреждение при -Werror остановит сборку.

В верхнем блоке настроек CMakeLists.txt задайте стандарт C++20, а рядом с существующим CMAKE_C_FLAGS укажите флаги для C++:

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_CXX_FLAGS
    "${MCPU} ${MFPU} ${MFLOAT_ABI} ${RUNTIME_LIBRARY} -mthumb -Wall -Werror")

Первый блок требует именно C++20. Вторая настройка передаёт C++ компилятору параметры ядра, FPU и ABI, уже используемые для C. При сборке main.cpp компилирует arm-none-eabi-g++. Если редактор CubeIDE по-прежнему воспринимает проект только как C, добавьте внутри <natures> файла .project строку <nature>org.eclipse.cdt.core.ccnature</nature>.

Итоговый CMakeLists.txt

После подключения CMSIS и перехода на C++20 файл FirstProject/CMakeLists.txt должен выглядеть так. В нём сохранены параметры и исходники, созданные мастером:

#############################################################################################################################
# file:  CMakeLists.txt
# brief: Template "CMakeLists.txt" for building of executables and static libraries.
#
# usage: Edit "VARIABLES"-section to suit project requirements.
#        For debug build:
#          cmake -DCMAKE_TOOLCHAIN_FILE=cubeide-gcc.cmake  -S ./ -B Debug -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug
#          make -C Debug VERBOSE=1 -j
#        For release build:
#          cmake -DCMAKE_TOOLCHAIN_FILE=cubeide-gcc.cmake  -S ./ -B Release -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
#          make -C Release VERBOSE=1 -j
#############################################################################################################################
cmake_minimum_required(VERSION 3.20)

###################### CONSTANTS ######################################
set (PROJECT_TYPE_EXECUTABLE          "exe")
set (PROJECT_TYPE_STATIC_LIBRARY      "static-lib")
set (MCPU_CORTEX_M0				      "-mcpu=cortex-m0")
set (MCPU_CORTEX_M0PLUS				  "-mcpu=cortex-m0plus")
set (MCPU_CORTEX_M3				      "-mcpu=cortex-m3")
set (MCPU_CORTEX_M4				      "-mcpu=cortex-m4")
set (MCPU_CORTEX_M7				      "-mcpu=cortex-m7")
set (MCPU_CORTEX_M33				  "-mcpu=cortex-m33")
set (MCPU_CORTEX_M55				  "-mcpu=cortex-m55")
set (MCPU_CORTEX_M85				  "-mcpu=cortex-m85")
set (MFPU_FPV4_SP_D16                 "-mfpu=fpv4-sp-d16")
set (MFPU_FPV4                        "-mfpu=vfpv4")
set (MFPU_FPV5_D16                    "-mfpu=fpv5-d16")
set (RUNTIME_LIBRARY_REDUCED_C        "--specs=nano.specs")
set (RUNTIME_LIBRARY_STD_C            "")
set (RUNTIME_LIBRARY_SYSCALLS_MINIMAL "--specs=nosys.specs")
set (RUNTIME_LIBRARY_SYSCALLS_NONE    "")
set (MFLOAT_ABI_SOFTWARE              "-mfloat-abi=soft")
set (MFLOAT_ABI_HARDWARE              "-mfloat-abi=hard")
set (MFLOAT_ABI_MIX                   "-mfloat-abi=softfp")
#######################################################################

###################### VARIABLES ######################################
set (PROJECT_NAME             "FirstProject")
set (PROJECT_TYPE             "exe")
set (LINKER_SCRIPT            "../STM32F401RETX_FLASH.ld")
set (MCPU                     "-mcpu=Cortex-M4")
set (MFPU                 "-mfpu=fpv4-sp-d16")
set (MFLOAT_ABI               "-mfloat-abi=hard")
set (RUNTIME_LIBRARY          "--specs=nano.specs")
set (RUNTIME_LIBRARY_SYSCALLS "--specs=nosys.specs")
set (CMAKE_CXX_STANDARD       20)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_CXX_EXTENSIONS     OFF)

set (PROJECT_SOURCES
    Startup/startup_stm32f401retx.s
    Sources/main.cpp
    Sources/syscalls.c
    Sources/sysmem.c
    Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
)

set (PROJECT_DEFINES
    STM32F401xE
)

set (PROJECT_INCLUDES
    Drivers/CMSIS/Core/Include
    Drivers/CMSIS/Device/ST/STM32F4xx/Include
)

#######################################################################

################## PROJECT SETUP ######################################
project(${PROJECT_NAME})
enable_language(ASM)

if (${PROJECT_TYPE} MATCHES ${PROJECT_TYPE_EXECUTABLE})
  add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
  add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${CMAKE_PROJECT_NAME}>)
elseif (${PROJECT_TYPE} MATCHES ${PROJECT_TYPE_STATIC_LIBRARY})
  add_library(${PROJECT_NAME} ${PROJECT_SOURCES})
endif()

add_compile_definitions (${PROJECT_DEFINES})
include_directories (${PROJECT_INCLUDES})

set (CMAKE_EXECUTABLE_SUFFIX ".elf")
set (CMAKE_STATIC_LIBRARY_SUFFIX ".a")
set (CMAKE_C_FLAGS "${MCPU} -std=gnu11 ${MFPU} ${MFLOAT_ABI} ${RUNTIME_LIBRARY} -mthumb -Wall -Werror")
set (CMAKE_CXX_FLAGS "${MCPU} ${MFPU} ${MFLOAT_ABI} ${RUNTIME_LIBRARY} -mthumb -Wall -Werror")
set (CMAKE_EXE_LINKER_FLAGS "-T${LINKER_SCRIPT} ${RUNTIME_LIBRARY_SYSCALLS} -Wl,-Map=test.map -Wl,--gc-sections -static -Wl,--start-group -lc -lm -Wl,--end-group")
set (CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp")

Сборка Debug

Выберите конфигурацию Debug и запустите в STM32CubeIDE Build Project. В результате должен появиться Debug/FirstProject.elf. Это исполняемый файл для микроконтроллера вместе с информацией, по которой отладчик связывает машинные инструкции с исходным кодом.

Здесь main() пока содержит только бесконечный цикл. Сборка подтверждает, что исходники и CMSIS связаны правильно, но сама по себе не записывает программу на плату.

Подключение платы

Подключите NUCLEO-F401RE к компьютеру через разъём встроенного ST-LINK. Отдельный программатор и провода к выводам микроконтроллера для этой платы не требуются: ST-LINK уже соединён с целевым STM32 по интерфейсу SWD. STM32CubeIDE использует это соединение для записи прошивки и отладки.

IMG_4835.jpeg
Разъём ST-LINK на плате NUCLEO-F401RE.

Конфигурация отладки Debug

В Project Explorer щёлкните правой кнопкой мыши по проекту и выберите Debug As → Debug Configurations.... В левой части окна выберите STM32 C/C++ Application и создайте новую конфигурацию кнопкой с изображением чистого листа. Назовите её, например, FirstProject Debug.

  1. На вкладке Main выберите проект FirstProject и приложение Debug/FirstProject.elf. Проверьте, что указан ELF текущей сборки Debug.
  2. На вкладке Debugger выберите встроенный ST-LINK и режим SWD.
  3. На вкладке Startup в таблице Load Image and Symbols найдите строку с нужным ELF. В её столбцах Download и Load symbols должны стоять отметки. Включите Set breakpoint at: main.
  4. На вкладке Common выберите сохранение конфигурации как Shared file в каталоге проекта, чтобы файл .launch можно было хранить вместе с исходниками. Нажмите Apply, затем Debug.
Screenshot 2026-10-25 130220.png
Конфигурация отладки указывает на ELF, собранный из этого проекта.
Screenshot 2026-10-25 130240.png
Отладчик использует встроенный ST-LINK и интерфейс SWD.
Screenshot 2026-10-25 130300.png
Параметры Download, Load symbols и Set breakpoint at: main.

CubeIDE запишет ELF во Flash и подключит отладчик. Если выполнение остановилось в main, исходный файл и текущая строка будут видны в редакторе. Нажмите Resume или F8, чтобы программа продолжила работу. В пустом проекте после этого не будет видимого эффекта на плате: бесконечный цикл пока ничего не делает.

Запуск без отладки (Run)

Для записи прошивки и запуска без пошаговой отладки откройте у проекта Run As → Run Configurations.... В разделе STM32 C/C++ Application выберите уже созданную конфигурацию FirstProject Debug. Убедитесь, что на вкладке Main указан Debug/FirstProject.elf, затем нажмите Run. Отдельную конфигурацию для Run создавать не обязательно: одну конфигурацию можно запускать и кнопкой Debug, и кнопкой Run.

Debug открывает сеанс отладки: можно останавливать программу, смотреть регистры и выполнять код по шагам. Run записывает прошивку и запускает её без остановки в main и пошаговой отладки. Слово Debug в пути к ELF обозначает конфигурацию сборки, а не режим запуска. Отдельная конфигурация запуска понадобится, только если вы захотите использовать другой ELF или другие параметры. При изменении исходников сначала пересоберите Debug, чтобы в обоих случаях использовался новый ELF.