Проект и общая библиотека
В первом уроке мы настроили сборку CMake и подключение CMSIS. Для мигания светодиодом используем отдельный проект f401_led_blink из репозитория курса. Повторять работу мастера создания проекта не потребуется.
Папка Libraries находится на одном уровне с папками проектов. Внутри неё лежит одна копия STM32CubeF4, к которой обращаются оба проекта и смогут обращаться следующие. CMSIS не нужно копировать в каждый новый проект.
Stm32Course2026/
├── Libraries/
│ └── STM32CubeF4/
│ └── Drivers/
│ └── CMSIS/
│ ├── Core/Include/
│ └── Device/ST/STM32F4xx/
├── f401_swd_debug/
└── f401_led_blink/
├── CMakeLists.txt
├── CMakePresets.json
├── Startup/startup_stm32f401retx.s
└── Sources/main.cpp
STM32CubeF4 записан в репозитории курса как подмодуль Git. Каталог CMSIS Device внутри него тоже является подмодулем. Если репозиторий ещё не получен, откройте PowerShell в выбранном родительском каталоге и выполните:
git clone https://github.com/Annihilatorrr/Stm32Course2026.git
cd .\Stm32Course2026
git submodule update --init Libraries/STM32CubeF4
git -C Libraries/STM32CubeF4 submodule update --init Drivers/CMSIS/Device/ST/STM32F4xx
Если репозиторий уже клонирован, выполните две последние команды из его корня. Они загружают только нужные для этого урока подмодули. Проверьте, что файлы CMSIS появились:
Test-Path .\Libraries\STM32CubeF4\Drivers\CMSIS\Core\Include
Test-Path .\Libraries\STM32CubeF4\Drivers\CMSIS\Device\ST\STM32F4xx\Include
Test-Path .\Libraries\STM32CubeF4\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c
Каждая проверка должна вывести True. Если одна из них вывела False, вернитесь к командам инициализации подмодулей и убедитесь, что выполняете их из каталога Stm32Course2026.
Импорт проекта в STM32CubeIDE 2.2.0
Откройте File → STM32 Project Create/Import → Import STM32 Project → STM32 CMake Project. На странице Project with existing CMake sources введите в поле Project name имя f401_led_blink. Оставьте включёнными Use default location и Use default build directory: остальные пути мастер заполнит автоматически. Нажмите Next. На странице Configure default tool-chain settings for the project оставьте Toolchain: MCU ARM GCC, нажмите Select... рядом с полем MCU и выберите STM32F401RETx. Завершите импорт. Проект f401_led_blink появится в Project Explorer.
Проект уже содержит исходники, CMake-пресеты Debug и Release, startup-файл и скрипт компоновщика. Файлы CMSIS остаются в общей папке Libraries, поэтому для успешной сборки важна показанная выше структура каталогов.
Как CMake находит CMSIS
В f401_led_blink/CMakeLists.txt корень библиотеки вычисляется относительно самого CMake-файла:
get_filename_component(STM32CUBEF4_ROOT
"${CMAKE_CURRENT_LIST_DIR}/../Libraries/STM32CubeF4" ABSOLUTE)
CMAKE_CURRENT_LIST_DIR указывает на f401_led_blink, а .. возвращает нас в корень репозитория. Оттуда CMake переходит в общую папку Libraries/STM32CubeF4. В проекте используются два каталога заголовков и один исходник CMSIS Device:
${STM32CUBEF4_ROOT}/Drivers/CMSIS/Core/Include
${STM32CUBEF4_ROOT}/Drivers/CMSIS/Device/ST/STM32F4xx/Include
${STM32CUBEF4_ROOT}/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
В PROJECT_DEFINES задано STM32F401xE, чтобы заголовки CMSIS выбрали определения нужного микроконтроллера. Все эти пути уже есть в проекте: править CMake перед сборкой не требуется.
Светодиод LD2 и вывод PA5
На NUCLEO-F401RE пользовательский светодиод LD2 связан с выводом PA5. Высокий уровень на выводе включает светодиод, низкий выключает.
Тактирование — это подача регулярных импульсов, по которым работает блок микроконтроллера. После сброса тактирование порта GPIOA отключено: прежде чем настраивать PA5, программа включает его битом GPIOAEN в RCC->AHB1ENR, а затем выбирает режим выхода в GPIOA->MODER.
Сама система после сброса использует внутренний генератор HSI с номинальной частотой 16 МГц. В этом проекте источник и делители системной частоты не меняем; их настройку разберём позже. Включение тактирования GPIOA лишь разрешает работу порта, не повышая частоту процессора.
Регистр GPIOA->BSRR позволяет установить или сбросить уровень вывода записью: GPIO_BSRR_BS5 включает LD2, GPIO_BSRR_BR5 выключает его. Перед переключением PA5 в режим выхода программа записывает низкий уровень, чтобы светодиод не включился в момент настройки.
Мигание в основном цикле
В f401_led_blink/Sources/main.cpp после подключения заголовка CMSIS задана короткая пауза, а в main() последовательно настраивается GPIOA и повторяется включение и выключение LD2:
#include <cstdint>
#include "stm32f4xx.h"
namespace {
constexpr std::uint32_t kDelayIterations = 2'000'000U;
void delay()
{
for (std::uint32_t i = 0; i < kDelayIterations; ++i) {
__NOP();
}
}
} // namespace
int main()
{
RCC->AHB1ENR = RCC->AHB1ENR | RCC_AHB1ENR_GPIOAEN;
(void)RCC->AHB1ENR;
GPIOA->BSRR = GPIO_BSRR_BR5;
GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODER5) | GPIO_MODER_MODER5_0;
for (;;) {
GPIOA->BSRR = GPIO_BSRR_BS5;
delay();
GPIOA->BSRR = GPIO_BSRR_BR5;
delay();
}
}
Чтение RCC->AHB1ENR после включения тактирования отделяет эту запись от первого обращения к GPIOA. Выражение с GPIO_MODER_MODER5 очищает оба бита режима PA5, а GPIO_MODER_MODER5_0 выбирает обычный цифровой выход. Бесконечный цикл включает светодиод, ждёт, выключает его и снова ждёт.
Сборка в STM32CubeIDE
В Project Explorer выберите f401_led_blink и конфигурацию сборки Debug. Затем запустите Project → Build Project. После сборки должен появиться файл f401_led_blink/Debug/f401_led_blink.elf. Это прошивка с отладочной информацией; одна сборка ещё не записывает её во Flash платы.
Если CMake сообщает, что не найдены заголовки или system_stm32f4xx.c, проверьте результаты Test-Path и расположение папки Libraries. Если CubeIDE не находит компилятор, проверьте настройку MCU Toolchain импортированного проекта.
Запуск и проверка на плате
Подключите NUCLEO-F401RE через USB-разъём встроенного ST-LINK. В Project Explorer откройте для проекта Debug As → Debug Configurations..., выберите STM32 C/C++ Application и создайте конфигурацию f401_led_blink Debug.
- На вкладке Main выберите проект
f401_led_blinkи приложениеDebug/f401_led_blink.elf. - На вкладке Debugger выберите встроенный ST-LINK и интерфейс SWD.
- На вкладке Startup проверьте, что для нужного ELF включены Download и Load symbols. Для пошаговой проверки включите Set breakpoint at: main.
- Нажмите Apply, затем Debug. Если выполнение остановилось на
main(), нажмите Resume или F8.
LD2 должен попеременно загораться и гаснуть. Чтобы в дальнейшем записывать прошивку и запускать её без остановки в main(), откройте Run As → Run Configurations... и запустите ту же конфигурацию через Run. Перед новым запуском после правок в main.cpp снова выполните Build Project.
Исходный код
GitHub: Stm32Course2026. Проект этого урока — f401_led_blink, путь: Stm32Course2026/f401_led_blink.