Поддержка старого embedded-проекта в VS Code

Как-то раз я начал работать с одним большим проектом для микроконтроллера. Как многие legacy-проекты в embedded, он привязан к старой версии IDE. В моем случае это оказался IAR 7. Эта среда обладает хорошими отладочными средствами, но работать с кодом в ней не очень комфортно: отсутствует много привычных комбинаций клавиш (Ctrl + точка, например), нет темной темы, скромная подсветка синтаксиса.

VS Code с расширениями смотрит на проект из IARVS Code с расширениями смотрит на проект из IAR

Со временем я стал все больше пользоваться VS Code для работы с кодом, а для проверки работоспособности переключался в IAR. Тогда я задумался, можно ли перенести основную работу над проектом в VS Code? Достоинств у редактора много: приятный настраиваемый интерфейс, интегрированный Git, расширения на любой вкус и задачу. Главный нюанс состоял в том, что проект должен собираться компилятором IAR, ибо написан он был строго под него.

Коротко о проекте: он огромен, стар (самое раннее упоминание — 2007 год), в нем много всего привязано к компилятору. Проект написан для серии приборов с небольшим количеством модификаций. Программатор J-Link, микроконтроллеры ARM Cortex-M0 и M4.

План

Какие возможности я хотел получить от новой среды разработки? Для начала:

  • сборка прошивки в VS Code;

  • работа с программатором — очистка чипа, запись готового .hex;

  • отображение ошибок компиляции в проекте.

К чему я стремился из плюсов среды:

  • удобство работы с кодом (подсветка синтаксиса, форматирование);

  • автоматизация рутинных задач через tasks;

  • работа с Git;

  • проверка кода анализатором.

Задачи в VS Code

Небольшой ликбез. Задачи в VS Code — это механизм, который позволяет запускать внешние скрипты и программы прямо из редактора. С их помощью можно автоматизировать некоторые действия, например прошивку микроконтроллера, удаление/создание папок и т. п.

Описываются задачи в файле .VS Code/tasks.json и выглядят примерно так:

{ "label": "Flash: Erase chip", "type": "shell", "command": "JFlash.exe", "args": [ "-openprj${workspaceFolder}\_scripts\J-flash.jflash", "-erasechip", "-exit" ], "group": "build", "presentation": { "reveal": "always", }}

Эта задача запускает SEGGER J-Flash, в нем открывает проект J-flash, стирает чип и закрывает программу. Подробнее про задачи можно почитать в блоге VS Code.

Сборка проекта

Для начала рассмотрим сборку через расширения для VS Code. IAR Build и IAR Debug позволяют перенести работу с прошивкой в VS Code (сборку и отладку), но увы, минимальная поддерживаемая версия IAR — восьмая, так что это не мой вариант.

Чуть более интересный способ — это сборка через IarBuild.exe, поставляемого вместе с IAR. Эта утилита позволяет скомпилировать проект без графической IDE и работает довольно просто. Ее необходимо вызвать, передав ей одну из команд:

  • -make пересобирает, что изменилось;

  • -build — уже полная пересборка проекта;

  • -clean удаляет промежуточные и выходные файлы.

Чтобы запустить сборку проекта, из bat-скрипта вызываем:

"%IAR_DIR%commonbinIarBuild.exe" "%REPO_DIR%name.ewp" -build %CONFIG% -log all

Здесь:

  • IAR_DIR — адрес папки IAR,

  • REPO_DIR — папка с проектом,

  • name.ewp — файл проекта,

  • CONFIG — конфигурация прибора по умолчанию (Release или Debug), а в моем случае еще и конфигурации под каждый вид прибора,

  • log all — вывод сообщений сборки.

Далее в скрипте можно добавить действия с готовой прошивкой — например, прописать заводские настройки или объединить файл с bootloader.

Но вернемся к VS Code. Для компиляции прошивки надо запустить bat-файл, указав необходимую модификацию. Каждой модификации прибора соответствует отдельная конфигурация сборки в IAR. Я создал одноименный список приборов в tasks.json:

"inputs": [{ "id": "device", "type": "pickString", "description": "Выберите прибор для сборки", "options": [ "Device1", "Device2", "Device3" ]}]

Вот задача, которая в начале дает выбор модификации, а затем запускает сборку необходимой конфигурации:

{ "label": "IAR: Build Device", "type": "shell", "command": "${workspaceFolder}\build_device.bat", "args": [ "${input:device}" ], "options": { "cwd": "${workspaceFolder}", "shell": { "executable": "cmd.exe", "args": ["/d", "/c"] } }, "group": "build", "problemMatcher": { "owner": "IAR-build", "fileLocation": "absolute", "source": "IAR", "pattern": { "regexp": "^(.+)\((\d+)\)\s*:\s*(Warning|Error)\[[^\]]+\]:\s*(.*)$", "file": 1, "line": 2, "severity": 3, "message": 4 } }}

Тут интересен момент с problemMatcher: при компиляции все ошибки передаются в VS Code и будут отображаться в окне problems. Очень удобно. В панели Problems сразу появилась сотня предупреждений. Добавляются предупреждения и ошибки сборки с указанием места, так что можно все найти и поправить.

Раз уж зашла речь об ошибках, то поговорим и про IntelliSense. По умолчанию VS Code использует IntelliSense из расширения C/C++ для анализа кода, и он поначалу выдавал огромное количество ошибок, так как не мог найти те или иные элементы. Так как меня интересуют только ошибки из IAR, я отключил отображение ошибок от IntelliSense, создав файл settings.json с таким содержанием:

{ "C_Cpp.errorSquiggles": "disabled", "C_Cpp.intelliSenseEngine": "default"}

При этом сам IntelliSense я оставил включенным, поскольку он обеспечивает автодополнение и навигацию по коду. Для корректной работы этих функций необходимо настроить пути к заголовочным файлам. Чтобы не писать их вручную, попросил нейросеть сгенерировать скрипт на Python, который бы создавал файл c_cpp_properties.json со списком путей, импортированных из проекта IAR:

import jsonimport sysimport xml.etree.ElementTree as ETfrom pathlib import PathIAR_DIR = r"F:progIARarm"project = Path(sys.argv[1]).resolve()config_name = sys.argv[2]# Открываем проект и ищем конфигурациюroot = ET.parse(project).getroot()config = next( (c for c in root.findall(".//configuration") if c.findtext("name") == config_name), None)if config is None: sys.exit(f"Configuration not found: {config_name}")# Извлекаем пути заголовочных файловincludes = []for option in config.findall(".//option"): if option.findtext("name") == "CCIncludePath2": for state in option.findall("state"): if state.text: path = state.text.strip() path = path.replace("$PROJ_DIR$", str(project.parent)) path = path.replace("$TOOLKIT_DIR$", IAR_DIR) includes.append(Path(path).resolve().as_posix())# Формируем настройки VS Codedata = { "configurations": [{ "name": config_name, "includePath": list(dict.fromkeys(includes)), "intelliSenseMode": "gcc-arm", "compilerPath": "", "cStandard": "c99", "cppStandard": "c++98" }], "version": 4}# Сохраняем файлoutput = Path(__file__).resolve().parent.parent / ".vscode" / "c_cpp_properties.json"output.parent.mkdir(exist_ok=True)output.write_text(json.dumps(data, indent=4), encoding="utf-8")print(f"Created: {output}")print(f"Include paths: {len(includes)}")

Кнопку сбора прошивки и отображение ошибок разобрали, идем дальше.

Прошивка контроллера

Следующий пункт автоматизации — работа с программатором J-Link через задачи. Для J-Flash я создал проект с моим контроллером, всеми выставленными настройками и написал необходимые мне задачи: одна для прошивки, вторая для стирания чипа. 

{ // прошивка "label": "Flash: artifacts", "type": "shell", "command": "JFlash.exe", "args": [ "-openprj${workspaceFolder}\_scripts\J-flash.jflash", "-open${workspaceFolder}\programm.hex", "-auto", "-exit" ], "group": "build", "problemMatcher": []},{ // стирание "label": "Flash: Erase chip", "type": "shell", "command": "JFlash.exe", "args": [ "-openprj${workspaceFolder}\_scripts\J-flash.jflash", "-erasechip", "-exit" ], "group": "build", "presentation": { "reveal": "always", }}

Все задачи пишут результат своего выполнения в терминал. Можно отдельно прописать, что если задача выполнена успешно, то терминал автоматически закрывается, но мне это показалось неудобным. Отвлечешься и неясно, а запускал ли ты задачу вообще.

Отладка

Внимательный читатель наверняка уже сидит с вопросом: а как же отладка проекта? Ведь написание и сборка проекта — это далеко не всё, проект надо еще и дебажить! Тут, увы, результатами похвастаться не получится: последний камень преткновения перенести не удалось. Расширение для отладки не подошло из-за разницы в версиях IAR. Единственное, чем я пользуюсь, это отладка через UART, а вот за полноценной отладкой приходится идти обратно в IAR.

Полезные расширения

План «минимум» закрыл, собрать прошивку и перепрошить контроллер могу, не выходя из VS Code. Теперь рассмотрим расширения, которые мне помогают в работе:

Code Spell Checker — проверяет правильность написания слов. Бывало, что после запушенного на сервер изменения вы находили опечатку в своем комментарии? С этим расширением таких ситуаций больше не будет. Одна беда: постоянно ругается на опечатки, которые внесли другие программисты в проект. 

Подсвечивает место ошибки, по нажатию «Ctrl + .» показывает варианты замены, по повторному нажатию исправляет на первое значение.

Также есть отдельное окошко, в котором показаны все ошибки в проверенных файлах. Имеется вариант приложения для русского языка.

Trailing Spaces — показывает лишние пробелы, например, в конце строки. Пишем чище.

VS Code-icons — меняет иконки папок и файлов в Explorer, становится визуально проще ориентироваться в проекте.

Serial monitor — позволяет работать с COM-портом в отдельном окошке, я использую его для отладки по UART.

Doxygen Documentation Generator — расширение для генерации шаблона описания функции. Создает ту самую шапку:

/******************************************************************************** * @brief тестирует исправность АЦП * * @param num_channel - номер канала * @return uint16_t значение на канале ********************************************************************************/uint16_t ADC_test (uint8_t num_channel){

Преимущества использования VS Code

Теперь рассмотрю коротко, что я получил, начав работать с кодом в VS Code:

  • Настраиваемую подсветку синтаксиса и темную тему. Честно говоря, даже одного этого было бы достаточно для того, чтобы начать в этом разбираться.

  • Форматирование кода.

  • Удобный поиск по всему проекту.

  • Структура проекта соответствует структуре папок. В IAR расположение файлов в дереве проекта может не иметь ничего общего с реальным расположением.

  • Удобно открывать среду: зашел в папку проекта, нажал правой кнопкой мыши — «открыть с помощью code» — и всё, проект открыт.

  • Можно посмотреть почти любой файл в IDE, разве что с офисными документами не работает.

  • В любом участке проекта я вижу, кто именно и как давно написал тот или иной код. Особенно полезно в работе с командой.

  • Подключил анализатор кода — cppcheck. После анализа он выдал тысячу предупреждений. Конечно, это не все места с ошибками, но рассмотреть стоит. Полезно для поиска потенциальных ошибок.

Выводы

Стал ли я все время работать в VS Code, забыв, как выглядит ярлык IAR? Увы, нет. Бо́льшая часть отладки проекта все так же происходит в IAR. Но вся работа по написанию кода и работа с Git теперь перенесена в приятную среду. Сейчас я не перепроверяю орфографию комментариев, стало заметно легче ориентироваться в коде, а часть задач решается через отладку по UART прямо в VS Code. Считаю, что по большей части моя изначальная задача выполнена.

Далее я попытаюсь прикрутить к проекту хоть какое-нибудь автоматическое тестирование, чтобы меньше работать 😂

Ссылки

  • Задачи в VS Code

  • VS Code как IDE для embedded-разработки — про полноценную работу с МК в VS Code. Подглядел для себя парочку полезных расширений там.

  • Настройка VS Code

Источник: habr.com

0 0 голоса
Рейтинг новости
1
0
Подписаться
Уведомить о
0 комментариев