Настройка VSCode для программирования stm32 в Linux и не только в Linux

Kate

Administrator
Команда форума
Собственно идея написать эту статью как памятку себе любимому, ну может ещё кому пригодится пришла в голову год назад, после того как убил немало времени на это нехитрое занятие. Недавно оказалось, что проблема актуальна по сей день. Почему-то ни один из найденных вариантов сам по себе не помогает и данная статься является результатом обработки всей найденной информации. При решении вопроса, больше всего бесило - возьмите мой проект и будет вам счастье, а проекта там уже и нет... Такой подход я плохо переношу, поэтому и сам делать так не буду.

Всё ниже описанное является следствием моего личного опыта, и ни на какую истинность не претендует. Все советы рассчитаны не людей только решившихся на переход с AVR на STM32

Вопросы типа почему Linux, VSCode и прочее, думаю, освещения не требуют. Считаю, что все заинтересованные в вопросе, на эти мелочи давно нашли СВОЙ ответ. Однако отмечу, в Винде всё это тоже работает, проверено, и проекты спокойно переживают миграцию между машинами.

Пожалуй начнём!

Этап установки VSCode опущу, этого добра настролько навалом, что даже чересчур. Скажу только, что минимально нужно поставить модули C/C++ от Microsoft (считаю, что плагин от крупного автора имеет больше шансов на долгую жизнь), Cortex-Debug от marus25 (альтернатив пока нет) и Makefile Tools от Microsoft (анализирует Makefile и сам настраивает IntelliSense, давно ждал такую штуку, было хоть сам пиши).

Самый простой способ получить заготовку проекта - собрать его в CubeMX. Процесс интуитивно понятный, сотни раз описанный в сети, поэтому отвлекаться на него не буду. Отмечу пару важных моментов.

Нужно не забыть в настройках порта разрешить отладочную шину​

abb6dc31c01c3d82413968f9272555b3.png

Очень песпонтовая ошибка. По умолчанию все выводы переводятся на вход и после первой прошивки у Вас отваливается программатор. Так как у всех начинающих программатор - китайский минимальный клон, то никакого сброса для STM32 там нет и что дальше делать не всем понятно.

Решение довольно простое - нужно исправить досадную ошибку и запустить процесс программирования или стирания удерживая кнопку сброса. Когда программа будет выполнять повторы подключения, отпустить сброс. Получиться может не с первого раза, но обязательно получится. Ещё на днях подсказали способ - переключить джамперы загрузки на положение отличное от Flash, что бы не дать запуститься нашей косячной программе и переписать камень из такого положения (сам не пробовал).

Как и у меня в своё время, у большинства начинающих в распоряжении так называемая Синяя Пилюля, поэтому давайте включим выход к которому подключен светодиод (PC13).

e4acb199f39222d7c3b927dfd0cc84ab.png

Так как светодиод через резистор подключен к питанию, то вывод настроим в режим Open-Drain, хотя от Push-Pull хуже не будет.

Настройку тактировки мне приводить лень, пхать сюда огромную бессмысленную картинку не виду смысла, а от уменьшеной смысла ещё меньше. К тому же CubeMX предлагает сам настроить все коэффициенты, да и для ручного режима всё более чем интуитивно понятно.

Поэтому завершаем работу с CubeMX задав имя проекта и обязательно переключив *Toolchain/IDE* на *Makefile*

ac0b2ad7a87d918cc369412ccf3b4bf9.png

После генерации проекта, в целевом каталоге получаем вот такой набор файлов.

17a23cf01d0e24ec8a53a093775ab8c8.png

Всё бы хорошо, но для отладки нам необходим SVD-файл, в нём информация для отладчика, необходимая для человеческого отображения регистров периферии, ядра и т.п.

Где взять этот файл? С одной стороны всё довольно быстро ищется, но не всегда это будут свежие версии. Лучше всего взять с сайта ST. Идём на st.com, дальше Products -> Microcontrollers & Microprocessors и ищем там свой проц. В нашем случае STM32 32-bit Arm Cortex MCUs -> STM32 Mainstream MCUs -> STM32F1 Series -> STM32F103

311defef92a8b2c59645acbb4d1b5c47.png

Тут можно найти всю возможную документацию по процессору, но сейчас нас интересует вкладка CAD Resources. На ней находим HW Model, CAD Libraries & SVD -> System View Description. Скачиваем найденый архив. Для ленивых ссылка на страницу. В архиве найдёте несколько svd-файлов. Нас сейчас интересует - STM32F103.svd. Не долго думая кидаем его в папку с проектом.

Пришло время запустить VSCode!!! Лично я предпочитаю в нужном каталоге дать команду code ., а там каждому своё... Программа спросит, доверяете ли вы авторам этого каталога, придётся сказать, что доверяете. Makefile Tool проанализирует Makefile, о чём выдаст много текста в панели, и настроит IntelliSense. Ещё не так давно приходилось его настраивать вручную, не сложно, но не интересно.

Не забываем сохранить Рабочую Область!!!

Теперь немного дополняем Makefile - добавляем ещё одну цель prog

prog: $(BUILD_DIR)/$(TARGET).elf
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program build/$(TARGET).elf verify exit reset"
Небольшое пояснение. Скрипты interface/stlink-v2.cfg и target/stm32f1x.cfg позволяют openocd узнать через какой адаптер и с кем он должен работать. Сами скрипты распологаются в каталоге scripts с установленным openocd (для Винды) или в каталоге /usr/share/openocd в Linux. Приведённый пример работает для китайского клона ST-Link v2 и Синей Пилюли. Если у Вас другой программатор или камень, то необходимые файлы найдёте в тех же каталогах.

Собственно зачем нужна эта байда? Иногда нужно записать программу в процессор не запуская отладку - просто записать и посмотреть, что произойдёт. Вот за это и отвечает -c "program build/$(TARGET).elf verify exit reset

Следующим этапом я настраиваю git, но это по вкусу. Ну как настраиваю, создаю файл *.gitignore* ну и инициализацию репозиторий. Пример .gitignore

DSP/
Templates/
Examples/
NN/
/build/
*.log
*.d
.mxproject
*.ioc
по списку поясню только каталог build - в него производиться сборка проекта, поэтому что бы не отвлекаться на него и случайно не нагадить в коммит его и игнорим. Логи любит создвать Makefile Tools, они мне тоже ни к чему.

Если очень чешутся руки, то на данном этапе уже можно в терминале VSCode дать команду `make prog`, соберётся Ваш пустой проект и запишется в процессор. Процес сборки будет отобразаться здесь же в терминале, а об успешной записи Вам сообщит openocd примерно вот так

...
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : clock speed 1000 kHz
Info : STLINK V2J37S7 (API v2) VID:pID 0483:3748
Info : Target voltage: 3.169781
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000c74 msp: 0x20005000
** Programming Started **
Info : device id = 0x20036410
Info : flash size = 64kbytes
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked
Желающие почесали руки, продолжаем. В каталоге .vscode проекта нужно создать файл tasks.json примерно такого содержания

{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"group": "build",
"command": "make",
"problemMatcher": []
},
{
"label": "Clean",
"type": "shell",
"group": "build",
"command": "make clean",
"problemMatcher": []
},
{
"label": "Write firmware",
"type": "shell",
"command": "make prog",
"problemMatcher": []
}
]
}
Собственно здесь объявляются три задачи: сборка проекта, очистка рабочего каталога и прошивка контроллера. Можно конечно и здесь расписать все команды с параметрами, раньше так и делал, но потом стало лень дублировать команды, следить что бы они были одинаковыми в Makefile и тут... Ну в общем остановился на таком варианте. Работает же...

Теперь создаём launch.json c вот таким содержимым

{
"version": "0.2.0",
"configurations": [
{
"name": "openocd",
"type": "cortex-debug",
"request": "launch",
"cwd": "${workspaceRoot}",
"servertype": "openocd",
"executable": "./build/Habr.elf",
"svdFile": "STM32F103.svd",
"configFiles": [
"interface/stlink-v2.cfg",
"target/stm32f1x.cfg"
],
"preLaunchTask": "Build"
}
]
}
Страшная штука. Собственно "name" может иметь любое значение, оно влияет только на отображение. Поле "executable" должно иметь значение файла в который собирается ваша программа, с указанием пути от каталога проекта. У Вас оно своё, поэтому вместо Habr должно быть то, чему у вас равно TARGET = в Makefile. В "svdFile" прописываем svd файл нашего процессора. Если вы его положили не в корень проекта, то нужно указать путь от каталога проекта. В "configFiles" указываем те самые скрипты, которые мы добавляли в Makefile для прошивки контроллера. И последний момент "preLaunchTask": "Build" - запуск задачи сборки программы из tasks.json, что бы было чего прошивать и отлаживать.

А теперь момент без которого всё это добро не работает - необходимо сообщить программе, где лежат бинарники openocd и gdb, причём не пути к каталогам с ними, а именно сами программы. Сделать это нужно в глобальном файле settings.json, пока так стабильно работает. Так как сам этот файл слегка закопан, к тому же, в Linux и Windows находится в разных местах, то я для себя нашёл простой способ его открыть. Идём Файл -> Настройки -> Параметры, откроется вкладка с настройками. Далее Текстовый редактор -> Шрифт и ищем надпись Изменить в settings.json. В открывшийся файл нужно добавить следующие строчки

"cortex-debug.armToolchainPath": "usr/bin",
"cortex-debug.openocdPath": "/usr/bin/openocd",
"cortex-debug.gdbPath": "/usr/bin/gdb-multiarch",
"cortex-debug.armToolchainPath" - просто путь к каталогу в котором ваш *arm-none-eabi-gcc*, вот тут просто каталог

"cortex-debug.openocdPath" - полный путь к бинарнику openocd, для винды будет заканчиваться на .exe

"cortex-debug.gdbPath"
- полный путь к бинарнику gdb котрым Вы будете пользоваться

Ну и финишная прямая.

В файле *main.c* чуть-чуть меняем функцию *main()* на вот такое

int main(void)
{
uint32_t tempTick;

HAL_Init();
SystemClock_Config();
MX_GPIO_Init();

__ASM("NOP");
while (1)
{
tempTick = HAL_GetTick();
while (HAL_GetTick() - tempTick < 500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1);
tempTick = HAL_GetTick();
while (HAL_GetTick() - tempTick < 500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);
}
}
Честно говоря страшнее кода придумать с ходу не смог. Хочу просто показать, что ЭТО ВСЁ может жить.

Теперь на __ASM("NOP"); ставим точку останова, переходим "Запуск и Отладка" и запускаем всё это добро, нажав на зелёный треугольничек.

72a1f423a40540a7529f8f3a02ec8574.png

В Терминале побежали надписи процесса компиляции и через пару секунд всё остановиться на вот такой картинке

f4af96ede057acdd757540c1068af026.png

**ПОЗДРАВЛЯЮ, ВЫ В ОТЛАДКЕ!!!**

Можете просто нажать F5 или значёк проигрывания и наслаждаться мигающим светодиодом!

На этом у меня всё! Можно было бы ещё рассказать про настройку IntelliSense, но во-первых такого добра и так навалом, а во-вторых проблема уже частично решается плагином Makefile Tools, хоть пока и неидеально, но для начала хватает.

 
Сверху