Вступление.
В сети появляется всё больше материалов, посвященных применению языка C++ для программирования микроконтроллеров. Являясь сторонником этого направления, хочу поделиться теми знаниями и умениями, которые получил, в виде цикла статей-уроков с рассмотрением вопросов разработки для Stm32 на современном языке C++ с применением разрабатываемой мною библиотеки (или фреймворка) Zhele.
Я не являюсь профессиональным разработчиком в принципе, с электроникой тоже знаком лишь поверхностно. В связи с этим фактом прошу меня извинить за возможные неточности в вопросах, связанных именно с электроникой (например, я абсолютно не различаю определения "передний фронт" и "восходящий фронт", хотя, судя по прочитанным сообщениям на форумах, это как минимум не одно и то же, а как максимум только один вариант в принципе корректен). К сожалению, мои текущие знания не позволяют добавить в материалы качественную теоретическую часть, благо в сети достаточно хороших источников. Из всего, что мне попадалось на русском языке, наибольшим образом мне помогли и понравились статьи на таких ресурсах как microtechincs.ru, hubstub.ru, istarik.ru, microsin.net. Материал изложен подробно, понятно, и, что самое главное, есть примеры кода на чистом CMSIS.
О фреймворке.
Микроконтроллерами начал заниматься исключительно в качестве хобби, никаких реальных проектов и даже задач у меня не было и нет (даже полив цветов мне не нужен ввиду их отсутствия), поэтому мне хотелось и было важно не просто получить какой-то работающий девайс (иначе взял бы Arduino), а научиться писать качественный, красивый и оптимальный код. Попробовал поуправлять светодиодом на CMSIS, SPL, HAL, LL, однако не самые лестные отзывы об этих решениях не давали покоя. Однажды наткнулся на статью "Работа с портами ввода-вывода микроконтроллеров на Си++", предлагаемый автором подход понравился, и я стал пытаться пользоваться его фреймворком mcucpp, построенным полностью на шаблонах C++.
Проект покрывает семейства AVR, ARM, MSP430, содержит в себе много классов для управления периферией, контейнеры, файловую систему, драйверы и многое другое, объем поражает. Но для меня, как новичка, было крайне сложно всё это запустить, так как документации практически нет, примеров нет, а "из коробки" многое не работает. Поэтому я решил продолжить изучение микроконтроллеров путем постепенного приведения в порядок разработок Константина Чижова (автора статьи и проекта mcucpp, если вдруг кто-то решил не переходить по ссылкам), а именно добавлять Doxy-документацию, проверять работоспособность кода, добавлять примеры. Делать это в виде форка было тяжело, поэтому родился новый проект Zhele, гораздо менее амбициозный, предназначен только для Stm32, не содержит пока много чего из оригинального проекта, однако не содержит мелких ошибок, покрыт документацией и тестами, а также движется в направлении универсальности для различных контроллеров Stm32.
Среда разработки.
Много копий сломано в спорах о лучшей IDE, компиляторе, я же считаю, что лучшим решением является то, которое удобно конкретному программисту. Для разработки я использую связку Visual Studio Code + расширение PlatformIO. Далее пошагово приведен процесс установки и создания заготовки проекта:
- Скачать Visual Studio Code с официального сайта и установить.
- Запустить VSCode, нажать Ctr+Shift+X (или нажать на Расширения (Extensions) в панели слева), ввести строку PlatformIO в окно поиска и нажать кнопку Install. Могут возникнуть ошибки, связанные с невозможностью создания виртуального окружения Python, решение проблемы несложно найти в интернете.
- Открыть PIO Home, нажать на Platforms, выбрать Embedded, ввести stm32 и нажать на заголовок ST STM32.
- Нажать Install и дождаться окончания установки.
- Открыть PIO Home Home, нажать New Project, ввести название проекта, целевой контроллер (плату) (в примерах будет использован популярная плата Blue Pill на stm32f103) и выбрать CMSIS в списке Framework. Или можно пропустить шаг создания нового проекта, а скачать готовый по ссылке в конце статьи, распаковать архив и открыть директорию с проектом в редакторе VS Code.
- Так как предполагается использовать возможности современных стандартов C++, в том числе C++20, нужно вручную обновить компилятор. Для этого необходимо загрузить "Arm Embedded Toolchain" с официального сайта. На сайте выбрать gcc-arm-none-eabi-10.3-2021.10-win32.zip.
- Распаковать скачанный архив и скопировать с заменой директорий bin, share, arm-none-eabi и lib в C:\Users\%Username%\platformio\packages\toolchain\gccarmnoneeabi (в некоторых версиях Platofrmio эта директория может иметь другое имя: toolchain\gccarmnoneeabi@VERSION). Внимание! Не удаляйте файлы .piopm и package.json.
- Скопировать директорию Zhele/Zhele из репозитория в директорию lib проекта.
- В директорию src скопировать любой пример или создать новый .cpp файл. Например, файл LedControl.cpp
- Отредактировать файл platformio.ini для целевого устройства. Дополнительно к автоматически сгенерированному содержимому необходимо указать способ загрузки и отладки прошивки, а также добавить несколько флагов компилятора (а именно указать используемый стандарт языка C++, в нашем случае это c++20 и определить идентификатор STM32F1). В моем случае файл содержит следующее:
[env:bluepill_f103c8] platform = ststm32 board = bluepill_f103c8 framework = cmsis debug_tool = stlink upload_port = stlink build_flags = -D STM32F1 -std=c++20 build_unflags = -std=c++11
- Скомпилировать проект, загрузить его на контроллер.
Если проект не собрался, а VSCode отобразил поле ввода в верхней части экрана, перезапустите VS Code и повторите попытку.
Архив с проектом можно загрузить с Яндекс.Диска. Статья в формате PDF доступна также на Яндекс.Диске. На следующем занятии подробно рассмотрим возможности библиотеки в части управления портами ввода-вывода.
Однозначный лайк! Мало статей на эту тему, а тут целый курс, готовая библиотека, все с примерами, здорово одним словом )
Спасибо! Правда, курс еще не целый, что-то впал в прокрастинацию, но это регулярно волнами накатывает, так что продолжу скоро:)
Пришлось повоевать с настройками в platformio.ini. Не прошивал мою кастомную плату. Программатор подключен только через 3,3V, SWCLK, SWDIO, GND. Вот мой вариант, мож кому понадобится.
[env:disco_f030c8]
platform = ststm32
board = disco_f030c8
framework = cmsis
build_flags =
-D STM32F0
-std=c++20
build_unflags =
-std=c++11
debug_tool = stlink
upload_protocol = custom
upload_flags =
-c
SWD
-P
".pio\build\disco_f030c8\firmware.bin"
0x08000000
-Rst
-Run
upload_command = ${platformio.packages_dir}/tool-stm32duino/stlink/ST-LINK_CLI.exe $UPLOAD_FLAGS
Рад, что победили и спасибо за вариант ini-файла, хотя странно, плата в целом-то не должна никак влиять. Вообще уже давно думаю, что завязываться на IDE/расширение для редактора вообще совсем неправильно, надо переезжать на сборку чисто на cmake, загрузку/отладку отдельно.
Да я тоже удивился и долго понять не мог в чем дело. Судя по ошибкам плата не сбрасывалась для запуска прошивки. Подключил к ST-LINK V2 ресет (хотя без него нормально раньше шилась в кубе), ситуация не поменялась. Сделал ресет вручную, вроде что-то пошло, но коряво. В итоге я понял, что стандартные настройки от PlatformIO не работают нормально с моим программатором. Пришлось разбираться как кастомный программатор подключить.