-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Visual Studio Code - популярная свободная кроссплатформенная IDE с открытым исходным кодом. Универсальная, легковесная, модульная, гибкая.
Предоставляет множество возможностей: подсветка синтаксиса и ошибок, подсказки и дополнение кода, сборка, отладка, поддержка git и др.
Кроме того, можно расширять функционал за счёт подключения плагинов.
VS Code можно использовать в том числе и для embedded разработки.
- Оглавление
- Установка VS Code
- Сборка проекта
- Конфигурация C/C++
- Отладка проекта
- Запуск OpenOCD + Hardware (task)
- Запуск OpenOCD + Spike (фоновые task-процессы)
- Остановить все task-процессы
Сам VS Code можно установить из deb-пакета.
Установка плагина из .vsix архива:
Ctrl+Shift+P -> Install From VSIX
Сборка с существующим готовым makefile:
В tasks.json добавить task-и:
{
"label": "Makefile",
"type": "shell",
"group": "build",
"command": "make",
"problemMatcher": [
"$gcc"
],
},
{
"label": "Makefile clean",
"type": "shell",
"group": "build",
"command": "make",
"args": ["clean"],
}
Запустить сборку: Ctrl+Shift+B
Можно дополнительно установить плагин "Makefile Tools". С ним запуск make немного удобнее, но сам makefile всё равно должен быть в проекте.
Ссылки Makefile Tools:
Конфигурация находится в файле c_cpp_properties.json. Там настраивается платформа, компилятор, стандарт, Includes, Define, IntelliSense и др. Эта конфигурация (файл c_cpp_properties.json) опциональна.
Открыть конфигурацию:
Ctrl+Shift+P -> C/C++: Edit configurations (UI)
или
Ctrl+Shift+P -> C/C++: Edit configurations (JSON)
Можно прописать актуальный "compilerPath", а остальное оставить как есть.
IntelliSense можно настроить под конкретную платформу, которая не обязательно совпадает с host-платформой. Но похоже, платформы RISC-V пока нет.
Ссылки C/C++ configuration:
- Using C++ on Linux in VS Code
- c_cpp_properties.json reference
- Customizing default settings
- IntelliSense for cross-compiling
- Visual Studio Code C++ Extention: Cross Compilation IntelliSence Configurations
- How to manually configure Visual Studio Code for Debugging on PC
- Variables Reference
Необходимые плагины:
- cpptools (C/C++)
- Native Debug
Debug-конфигурации настраиваются в файле launch.json.
(Плагин Native Debug тоже должен быть установлен и включен)
Взаимодействие между IDE и GDB осуществляется по GDB-MI интерфейсу - "MIMode": "gdb".
Сначала, как обычно нужно запустить OpenOCD. Затем к нему должен подключиться GDB.
Запустить OpenOCD можно двумя способами:
1 способ
Средствами плагина cpptools (более правильный способ)
С помощью настроек в launch.json:
"debugServerPath": "/home/user/tools_riscv/riscv-openocd-0.10.0-2020.12.1-x86_64-linux-ubuntu14/bin/openocd",
"debugServerArgs": "-f /home/user/workspace/riscpoa.cfg",
"miDebuggerServerAddress": "localhost:3333",
Но так не работает! Ошибка при запуске OpenOCD:
Unable to start debugging. Debug server process failed to initialize.
Или
Unable to start debugging. No process is associated with this object.
Выглядит так: Запускается OpenOCD и ждёт на порту :3333, но GDB почему-то не пытается подключаться, затем срабатывает таймаут VSCode. Как будто процесс уже занят OpenOCD, а для OpenOCD и GDB нужны разные процессы.
...
1: (280) STDERR: Info : starting gdb server for riscv.cpu.0 on 3333
1: (280) STDERR: Info : Listening on port 3333 for gdb connections
...Ждёт подключения GDB...
1: (10245) <-logout
1: (10337) Send Event AD7MessageEvent
Это можно увидеть, если включить логгирование:
"logging": {"trace": true, "engineLogging": true, "exceptions": true},
Проблема описана тут:
- MS Code: Launching server using command ms-vscode.cpptools-1.0.1/bin/cpptools failed. #6192
- c++ - "Unable to start debugging. No process is associated with this object."
- Unable to start debugging cpp with vscode. #1262
- Unable to start debugging. Failed to initialize debugger terminal. #409
2 способ
Отдельный task (более простой способ)
В tasks.json делается отдельный task: "startOpenocdHW" или "startOpenocdSpike".
А в launch.json делается настройка:
"preLaunchTask": "startOpenocdHW"
или
"preLaunchTask": "startOpenocdSpike"
Но при этом "miDebuggerServerAddress": "localhost:3333" должно быть убрано.
При этом OpenOCD запускается в VSCode-терминале. Но, после того, как GDB-client остановлен (stop), OpenOCD остается запущенным.
Стартовые команды GDB-клиента можно задать с помощью "setupCommands". Можно использовать и команды для GDB-консоли, и команды в MI-формате.
Конфигурация для плагина cpptools (C/C++) в launch.json:
{
//"preLaunchTask": "startOpenocdHW",
"preLaunchTask": "startOpenocdSpike",
"name": "cpptools Debug",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/Debug/${workspaceFolderBasename}.elf",
"MIMode": "gdb",
"miDebuggerPath": "/home/user/eclipse_4.4.1/TOOLS/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gdb",
"miDebuggerArgs": "${workspaceFolder}/Debug/${workspaceFolderBasename}.elf --silent",
"stopAtEntry": true,
"stopAtConnect": true,
"postDebugTask": "Termitate all tasks",
"setupCommands": [
{
"description": "Enable pretty-printing for GDB",
"text": "-enable-pretty-printing",
"ignoreFailures": false
},
{
"description": "...",
"text": "-target-select remote localhost:3333",
"ignoreFailures": false
},
{
"description": "...",
"text": "monitor reset halt",
"ignoreFailures": false
},
{
"description": "...",
"text": "load",
"ignoreFailures": false
},
{
"description": "break main",
"text": "break main",
"ignoreFailures": false
},
]
}
После подключения и запуска GDB, внизу во вкладке DEBUG CONSOLE доступна GDB-консоль. Видимо это не CLI CGB console, а MI-GDB. Перед каждой командой GDB-консоли нужно использовать "-exec", что неудобно. Пример: -exec p/x $pc
Дизассемблер:
Контекстное меню -> Open Disassembly View
Непонятно как смотреть память (скорее всего никак).
Registers:
Отображаются GPR, FP, CSR.
fp-регистры отображаются также неправильно, как в eclipse, потому что это вопрос к GDB. Но в регистры почему-то нельзя писать вручную - ошибка "cannot be assigned to".
Если ставить breakpoint в GDB-консоли, то он не появляется в окне Breakpoints.
Отображаются шагание по asm-коду, но breakpoint-ы на asm-коде вручную не ставятся.
Не работает прерывание программы, когда программа исполняется в крутилке!
(Плагин cpptools тоже должен быть установлен и включен)
Тут не предусмотрено возможности запустить GDB-server (OpenOCD) средствами самого плагина, поэтому OpenOCD запускается с помощью настройки "preLaunchTask": "startOpenocd..." через task.
При этом OpenOCD запускается в VSCode-терминале. Но, после того, как GDB-client остановлен (stop/disconnect), OpenOCD остается запущенным.
В остальном всё получилось подключить по-штатному.
Конфигурация для плагина Native Debug в launch.json:
{
//"preLaunchTask": "startOpenocdHW",
"preLaunchTask": "startOpenocdSpike",
"name": "Native Debug",
"type": "gdb",
"request": "attach",
"gdbpath": "/home/user/eclipse_4.4.1/TOOLS/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gdb",
"debugger_args": ["--silent"],
"cwd": "${workspaceRoot}",
"executable": "${workspaceFolder}/Debug/${workspaceFolderBasename}.elf",
"remote": true,
"target": "localhost:3333",
"postDebugTask": "Termitate all tasks",
"autorun": [
"monitor reset halt",
"load",
"break main",
]
}
Непонятно как смотреть регистры.
Непонятно как смотреть дизассемблер и память (скорее всего никак).
Во вкладке DEBUG CONSOLE доступна GDB-консоль. Она работает нормально, без "-exec".
Отображаются шагание по asm-коду.
Нормально работает прерывание программы, когда программа исполняется в крутилке.
Проблемы с breakpoint:
Если ставить breakpoint в GDB-консоли, то он не появляется в окне Breakpoints.
В Си-коде breakpoint-ы ставятся вручную только если включен плагин cpptools.
В asm-коде breakpoint-ы вручную не ставятся вообще.
- How to attach to remote gdb with vscode?
- Running gdbserver as a preLaunchTask - need to press start/stop button several times #898
- Using C++ on Linux in VS Code
- Debugging in Visual Studio Code
- Debug C++ in Visual Studio Code
- Configuring C/C++ debugging
- Variables Reference
В tasks.json делается отдельный task: "startOpenocdHW".
А в launch.json делается настройка:
"preLaunchTask": "startOpenocdHW"
Task в tasks.json для запуска OpenOCD+Hardware:
{
"label": "startOpenocdHW",
"type": "shell",
"isBackground": true,
"command": "/home/user/eclipse_4.4.1/TOOLS/riscv-openocd-0.10.0-2020.12.1-x86_64-linux-ubuntu14/bin/openocd",
"args": ["-f", "${workspaceFolder}/scripts/riscpoa.cfg"],
}
Для работы с симулятором Spike нужно чтобы были одновременно запущены процессы Spike и OpenOCD.
Чтобы запускать несколько task-ов нужно использовать настройки "dependsOn" и "dependsOrder". "dependsOn" содержит список task-ов, от которых зависит текущий task. "dependsOrder" содержит способ выполнения task-ов - последовательно или параллельно.
При запуске нескольких фоновых task-процессов каждый такой task обязательно должен иметь "problemMatcher", чтобы можно было отследить, когда он "выполнится" - то есть когда изменяться вывод в терминал.
Простейший "problemMatcher":
"problemMatcher": {
"pattern":[
{
"regexp": ".",
"file": 1,
"location": 2,
"message": 3,
}
],
"background": {
"activeOnStart": false,
"beginsPattern": ".",
"endsPattern": ".",
},
}
Запуск Spike и OpenOCD:
Spike и OpenOCD оба запускаются фоново.
Есть три task-а: "startOpenocdSpike", "_startSpike" и "_startOpenocdSpike".
"startOpenocdSpike" - головной task, зависит от task-ов "_startSpike" и "_startOpenocdSpike", и запускается в launch.json из "preLaunchTask".
Task-и в tasks.json для запуска OpenOCD+Spike:
{
"label": "_startSpike",
"type": "shell",
"isBackground": true,
"options": {
"env": {
"LD_LIBRARY_PATH": "/home/user/eclipse_4.4.1/TOOLS/riscv_tui_12.12.18/lib/"
}
},
"command": "/home/user/eclipse_4.4.1/TOOLS/riscv_tui_12.12.18/bin/spike",
"args": ["--rbb-port=9824", "-m0xc000000:0x90000000", "-H", "${workspaceFolder}/Debug/${workspaceFolderBasename}.elf"],
"problemMatcher": {
"pattern":[
{
"regexp": ".",
"file": 1,
"location": 2,
"message": 3,
}
],
"background": {
"activeOnStart": false,
"beginsPattern": ".",
"endsPattern": ".",
},
},
},
{
"label": "_startOpenocdSpike",
"type": "shell",
"isBackground": true,
"command": "/home/user/eclipse_4.4.1/TOOLS/riscv-openocd-0.10.0-2020.12.1-x86_64-linux-ubuntu14/bin/openocd",
"args": ["-f", "${workspaceFolder}/scripts/spike.cfg"],
"problemMatcher": {
"pattern":[
{
"regexp": ".",
"file": 1,
"location": 2,
"message": 3,
}
],
"background": {
"activeOnStart": false,
"beginsPattern": ".",
"endsPattern": ".",
},
},
},
{
"label": "startOpenocdSpike",
"type": "shell",
"isBackground": true,
"command": "echo Start Spike and OpenOCD",
"dependsOn": ["_startSpike", "_startOpenocdSpike"],
"dependsOrder": "sequence",
"problemMatcher": {
"pattern":[
{
"regexp": ".",
"file": 1,
"location": 2,
"message": 3,
}
],
"background": {
"activeOnStart": false,
"beginsPattern": ".",
"endsPattern": ".",
},
},
}
Ссылки tasks:
- Tasks in Visual Studio Code
- Tasks in Visual Studio Code
- Support using background tasks in dependsOn #70283
- Tasks Appendix
- How to run multiple tasks in VS Code on build?
- Visual Studio Code: running preLaunchTask with multiple tasks
- How to make vscode not wait for finishing a preLaunchTask?
(Подходит и для OpenOCD - при работе с hardware, и для OpenOCD+Spike - при работе с симулятором Spike)
При завершении debug-сессии, после того, как GDB-client остановлен (stop/disconnect), task-процессы OpenOCD (при работе с hardware) или OpenOCD+Spike (при работе с симулятором Spike) остаются запущеными.
Их можно останавливать руками в терминале по Ctrl+C, но это не очень удобно.
Можно автоматически убивать эти task-процессы по завершению Debug-сессии (stop/disconnect) - по "postDebugTask".
Чтобы убить все task-процессы нужно выполнить внутреннюю VSCode команду "command:workbench.action.tasks.terminate" с аргументом "terminateAll".
В tasks.json добавить отдельный task:
{
"label": "Termitate all tasks",
"type": "shell",
"command": "echo ${input:terminate}",
}
Также в tasks.json добавить секцию "inputs":
"inputs": [
{
"id": "terminate",
"type": "command",
"command": "workbench.action.tasks.terminate",
"args": "terminateAll"
}
]
А в launch.json сделать настройку:
"postDebugTask": "Termitate all tasks"
Похоже, что такое сочетание task+input - единственный способ выполнить внутреннюю VSCode команду "command:..." (не shell-команду) из task.
Visual Studio Code Variables Reference