С прошлого раза применения Visual Studio 2015 для написания прошивки и отладки под SoC прошло немало времени. 2017-я версия заметно обновилась, появилось много удобных фич, нововведений для C# 8.0, и, что также важно, обросла плюшками для эмбеддерского применения.
Сразу отмечу, что этот материал подходит для версии Visual Studio 2017 не ниже v15.6.7, я же использовал v15.7.1 вначале и далее обновился до v15.7.3 при написании материала.
Проект для примера
Для примера возьмём проект RTL00_WEB. Я сделал его форк — RTL00_WEB, тут будут все изменения, а также правки мелких ошибок оригинального проекта. На основе этой прошивки я покажу, что нужно сделать, чтобы его можно было открыть в Visual Studio 2017 как workspace-проект (привет Eclipse! хотя, честно говоря, мне такой подход не очень нравится, но он быстр и в целом достаточно удобен, привыкнуть можно), скомпилировать в WSL (при желании можно использовать и нативные средства для Windows) и запустить отладку.
WSL и gcc-arm-none-eabi
Предполагается, что у вас уже установлен и обновлён WSL. Для компиляции проектов потребуются скачивание и распаковка GNU Arm Embedded Toolchain. Итак, находясь в папке пользователя (при запуске ubuntu), скачиваем в её корень последнюю (на момент написания статьи) версию командой:
$ wget -c https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2017q4/gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2
Примечание: Ссылку к архиву других версий самостоятельно вытягиваем\копируем со страницы GNU Arm Embedded Toolchain.
Распаковываем:
$ tar jxf gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2
Теперь можно удалить ненужный архив:
$ rm gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2
Вот и всё, подготовка WSL на этом закончена.
Подготовка проекта
Все изменения для открытия проекта в Visual Studio 2017 будут в виде добавления файлов с настройками и командами. Незначительные отличия в других файлах в основном нацелены на исправление ошибок или просто изменение параметров исходного проекта.
Итак, по порядку. В корне проекта обязательно должен быть файл CppProperties.json, он отвечает за основные настройки проекта, пример с поясняющими комментариями:
{ "configurations": [ { // Указываем настройки среды (важно для IntelliSense) "inheritEnvironments": [ "linux-gcc-arm" ], "name": "firmware", // Здесь указываем директории, которые будут парситься "includePath": [ // Двойная звёздочка в конце пути - парсить всё рекурсивно "${workspaceRoot}\\USDK\\component\\**", "${workspaceRoot}\\project\\src\\**", "${workspaceRoot}\\project\\inc\\**" ], // Различные объявления и настройки для проекта, которые будут учитываться IntelliSense "defines": [ "CONFIG_PLATFORM_8195A", "ARDUINO_SDK", "F_CPU=166666666L", "M3", "GCC_ARMCM3" ], // Режим работы IntelliSense - ставим GCC для АРМов "intelliSenseMode": "linux-gcc-arm", "browse": { "path": [ "${workspaceRoot}" ], "limitSymbolsToIncludedHeaders": false, "databaseFilename": "" } } ], // Различные объявления путей к тулчейну или J-Link, действуют на все задачи "environments": [ { "BUILDTOOLS": "\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Linux\\GNU MCU Eclipse\\Build Tools\\2.9-20170629-1013\"", "GCCARMTOOLS": "\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Linux\\gcc_arm\"", "JLINKPATH": "C:\\Data\\JLink_V632a", "BASHPATH": "C:\\Windows\\sysnative", "PATH": "${env.BUILDTOOLS};${env.JLINKPATH};${env.BASHPATH};${env.BUILDTOOLS}\\bin;${env.GCCARMTOOLS};${env.GCCARMTOOLS}\\bin;${env.PATH}" } ] }
Далее есть два пути:
- Первый: открыть папку в Visual Studio из меню File — > Open -> Folder… (Ctrl+Shift+Alt+O):
Или, находясь в директории проекта, ПКМ на пустом месте и в контекстном меню выбираем Open in Visual Studio:
И создать шаблоны необходимых файлов .vs\Launch.vs.json и .vs\Tasks.vs.json из контекстного меню, пункты Debug and Launch Settings (ПКМ на бинарном файле) и Configure Tasks (ПКМ на Makefile или любом не компилируемом файле), а далее откорректировать их содержимое (кликабельно):
- Второй крайне простой: скопировать папку .vs из другого проекта (из которой нужны только вышеуказанные 2 файла, другие, находящиеся там файлы и папки генерируются и при копировании папки .vs их лучше удалять!) и внести коррективы.
Итак, неважно, каким путём созданы эти файлы, теперь разберём их содержание. Файл Launch.vs.json отвечает за отладку, пример его настройки с комментариями:
{ "version": "0.2.1", "defaults": {}, "configurations": [ { // Указываем тип отладки и файлы прошивки "type": "cppdbg", "name": "ram_all.bin", "project": "build\\bin\\ram_all.bin", "cwd": "${workspaceRoot}", "program": "${workspaceRoot}\\build\\obj\\build.axf", "MIMode": "gdb", "externalConsole": true, "inheritEnvironments": [ "gcc_arm" ], // Путь к отладчику, указан идущий в комплекте с Visual Studio "miDebuggerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Linux\\gcc_arm\\bin\\arm-none-eabi-gdb.exe", "setupCommands": [ { "text": "-environment-cd ${workspaceRoot}/build/obj" }, { // Настройки запуска arm-none-eabi-gdb "text": "-file-exec-and-symbols build.axf", "description": "load file", "ignoreFailures": false }, { "text": "-enable-pretty-printing", "ignoreFailures": true } ], // Настройки подключения к GDB серверу "visualizerFile": "${debugInfo.linuxNatvisPath}", "miDebuggerServerAddress": "localhost:2331"//, // Настройки авто запуска GDB сервера //"debugServerPath": "C:\\Data\\JLink_V632a\\JLinkGDBServer.exe", //"debugServerArgs": "-select USB -device Cortex-M4 -if SWD -speed 1000 -ir", //"serverLaunchTimeout": 3000 } ] }
Примечание: как можно заметить, настройки автоматического запуска GDB сервера закомментированы, т. к. сервер запускается, но к нему отладчик не подключается. Выяснить причину этого я пока не смог (буду рад, если напишете, в чем проблема в комментариях). Поэтому я просто запускаю GDB сервер из батника JLink-GDBServerM3.bat.
И второй файл Tasks.vs.json отвечает за все возможные задачи, которые будут отображаться для привязанного к задаче файла. Вот так это выглядит в контекстном меню:
Содержание файла для проекта RTL00_WEB с комментариями:
{ // Перечисление задач для всех файлов "version": "0.2.1", "tasks": [ // Задачи по сборке проекта // Пример объявления задачи как стандартной для сборки проекта { "taskName": "Build", "appliesTo": "Makefile", "contextType": "build", // Это важное отличие от других задач "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s -j 10 all'" ] }, // Пример объявления задачи как стандартной для очистки проекта { "taskName": "Clean", "appliesTo": "Makefile", "contextType": "clean", // Это важное отличие от других задач "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s clean'" ] }, // Задачи для J-Link GDB Server // Не работает, VS ожидает завершения JLinkGDBServer /*{ "taskName": "Start GDB Server", "appliesTo": "Makefile", "type": "launch", "command": "${env.COMSPEC}", "args": [ "JLinkGDBServer.exe -select USB -device Cortex-M3 -if SWD -speed 1000 -ir" ] },*/ // Задачи для J-Link { "taskName": "Restart SoC", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s reset'" ] }, { "taskName": "Run in RAM", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s runram'" ] }, { "taskName": "Run in SDRAM", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s runsdram'" ] }, { "taskName": "Read Flash", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "JLink.exe -Device Cortex-M3 -If SWD -Speed 1000 USDK\\flasher\\RTL_FFlash.JLinkScript" ] }, { "taskName": "Write OTA", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s flash_OTA'" ] }, { "taskName": "Write Boot", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s flash_boot'" ] }, { "taskName": "Write Flash_All", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ "bash -l -c 'make -s flash_burn'" ] }, { "taskName": "Make and Write WEBFS", "appliesTo": "Makefile", "type": "default", "command": "${env.COMSPEC}", "args": [ //"bash wsl_flash_webfs.sh", "bash -l -c 'make -s flash_webfs'" ] } ] }
Примечание: как можно заметить, задача запуска GDB сервера закомментированна, т. к. сервер запускается, но Visual Studio ожидает завершения его работы и не даёт исполнять другие задачи. Как изменить логику запуска задачи, я не нашёл (буду рад, если напишете решение в комментариях).
Компиляция
С этим вообще вопросов не должно возникнуть… только если в WSL забыли Pyton установить или пути неверно прописали где-либо. Важный момент, кроме настройки WSL, — при установке Visual Studio 2017 обязательно требуется установить как основной компонент «Разработка для Linux на C++«, так и дополнительные «Инструменты Visual C++ для CMake и Linux» и «Разработка для встроенных платформ и Интернета вещей» (выделено красным на скриншоте ниже):
Компиляция аналогична любым другим проектам — вызываем из контекстного меню на Makefile соответствующий пункт:
Наблюдаем за компиляцией, если есть ошибки — переходы к ошибочному месту в файле (в Visual Studio 2015 с этим была проблема, т. к. изначально она не заточена под такого рода проекты) работают — двойной клик по первой строке ошибки с именем файла:
А если глянуть в диспетчер задач, то можно увидеть силу сборки нативными средствами Linux — CPU используется максимально:
Многопоточная сборка проекта за секунды. Вот практически и всё, после компиляции уже прошиваем модуль и радуемся. :)
Прошивка, отладка
На основе модуля RTL-00 вкратце опишу процесс прошивки и отладки. Вначале смотрим на распиновку модуля:
Здесь, кроме питания, нас интересуют выводы GPIOE3 (SWDIO), GPIOE4 (SWCLK) и CHIP_EN (nRESET). Подключаем их к соответствующим выводам J-Link, я проверил работу с прошитым в J-Link опенсорс отладчиком x-Link. Для стабильной работы на nRESET добавлена подтяжка 10 кОм к питанию только (+3.3 В). Вот так это выглядит на столе (подтяжка с задней стороны модуля, SMD резистором):
Запускаем GDB сервер, к которому сможет обращаться как WSL, так и отладчик Visual Studio с помощью батника JLink-GDBServerM3.bat, подключение к модулю происходит успешно:
Переключаемся опять к Visual Studio, теперь прошиваем модуль задачей из контекстного меню на Makefile. Всё проходит успешно:
Аналогично можно сразу же зашить WEB образ диска. Вот и всё, модуль автоматически стартанёт залитую в него прошивку.
Для отладки также должен быть запущен заранее GDB сервер. Выбран Startup File командой из контекстного меню на бинарном файле (а также необходимо перепроверить параметры в файле Launch.vs.json, к примеру, значение параметра «name«: «ram_all.bin» должно совпадать с именем выбранного файла):
И если никаких ошибок не допустили, то сама отладка начинается простым нажатием на кнопку Start (F5) или из меню Debug -> Start:
Подключение к GDB серверу:
И вуаля, остановка на бряке с просмотром значений структуры настроек в текущем потоке FreeRTOS:
Кликабельно:
Дополнительные вещи можно посмотреть в Debug вкладке меню.
Вывод
Явно проделана большая работа с Visual Studio 2017 для работы с непрофильными проектами Visual Studio (Visual C++, C# и т. д.), стало значительно проще открывать и конфигурировать проекты embedd, MCU или SoC, как в данном случае, более того, использовать нативные средства Linux из WSL для компиляции проекта с максимальной эффективностью без сторонних платных расширений как VisualGDB. Меня это очень порадовало, и, надеюсь, Visual Studio 2017 будет дальше развиваться в этом направлении.
Единственное, чего не хватает пока на эту тему — различных примеров. Есть пара мануалов для открытия и настройки экспортированного проекта Mbed и всё, остальное по крупицам надо собирать и доходить самому.
К слову, из удобных, небольших встроенных фич — Team Explorer, если у вас проект привязан к GitHub, то можно не выходя из Visual Studio 2017 запушить изменения вашего проекта на гит:
На этом всё, спасибо, что прочитали! ;)
Ссылки
- RTL00_WEB — форк оригинального проекта, готовый для работе в Visual Studio 2017;
- Debugging an embedded ARM device in Visual Studio — официальный, краткий мануал для сборки MBED прошивки;
- ARM GCC Cross Compilation in Visual Studio — официальный, расширенный мануал для сборки MBED прошивки;
- Customizing your Environment with Visual C++ and Open Folder — описание содержания файлов CppProperties.json, Launch.vs.json и Tasks.vs.json;
- Configuring launch.json for C/C++ debugging — хоть и для Visual Studio Code, но тоже может пригодится при написании Launch.vs.json;
- Using Visual Studio Code for ARM — зарубежный блог со статьями для Visual Studio Code, мало ли, может пригодиться.