
Всем привет! Из этого руководства вы узнаете, как подключиться для отладки практически к любому ARM-чипу с помощью Arm Development Studio — когда ни J-Link, ни ST-Link сделать этого не могут (по разным причинам).
Этой инструкцией со мной когда-то поделился бывший коллега (за что ему огромное спасибо), и я решил спустя много лет, что такому полезному материалу не место в переписках в Telegram — его нужно публиковать.
Кому будет полезно
Материал пригодится тем, кому в работе или в рамках хобби регулярно приходится отлаживать код на устройствах с китайскими ноунейм-чипами на архитектуре ARM. Если ваш отладчик (J-Link, ST-Link или любой другой) не видит на чипе интерфейсы JTAG или SWD — или видит, но не может или не хочет подключаться — это руководство для вас. Даже если ваш аппаратный отладчик успешно работает со всеми устройствами, уверен, вы узнаете из статьи что-то новое.
JTAG или SWD есть, а подключения нет
Если при подключении по SWD или JTAG вы видите сообщение, похожее на скриншот ниже, или J-Link сообщает, что к условному Cortex-A76 можно подключиться только при помощи J-Link Pro, или дело не идёт дальше получения DPIDR по SWD, — ситуацию можно исправить либо с помощью OpenOCD (не всегда), либо через Arm Development Studio (Arm DS).

Необходимое оборудование
Сразу отмечу: Arm DS не умеет работать с J-Link. Зато поддерживает ST-Link, конвертеры на базе FTDI (например, FT2232HQ) и CMSIS-DAP-отладчики. Вот полный список поддерживаемых типов:

Из перечисленных у меня есть Tigard (для JTAG) и CMSIS-DAP-отладчик, сделанный на базе STM32F103C8T6 BluePill (для SWD). Последний, кстати, лучше не покупать готовым (у меня с такими были проблемы при подключении), а прошить самостоятельно: советую ознакомиться с репозиториями dap42 и dapboot.
Настройка платформы
Открываем Arm DS, выбираем в меню File → New → Other → Configuration Database:

Жмём Next и указываем осмысленное имя для файла базы. В ней будут храниться параметры подключения к нашим устройствам, и позже мы сможем добавлять новые конфигурации:

Нажимаем Finish. После этого в окне Project Explorer разворачиваем созданную базу и выбираем File → New → Other → Platform Configuration, Next:

В окне Create Platform Configuration выбираем пункт Advanced platform detection or manual creation:

Нажимаем Next, затем в окне Platform Information заполняем данные о производителе и названии чипа, жмём Finish:

В результате в Project Explorer (в каталоге Boards) появится ветка с именем производителя и чипа, в которой создастся файл с расширением .sdf, а также откроется окно Platform Configuration Editor:

Подключение Arm DS к отладчику
В появившемся окне в разделе Probe Connection в зависимости от интерфейса выбираем:
JTAG → FTDI MPSSE JTAG,
SWD → CMSIS-DAP.
Для примера я подключаюсь к чипу Atmel ATSAM3X8E на Arduino DUE по JTAG, используя в качестве отладчика Tigard:


На Tigard переключатель ставим в режим JTAG, питание задаём как 3V3. После этого в Arm DS нажимаем кнопку Browse (кстати, использовать этот отладчик с Arm DS в режиме SWD не получится). Если вы работаете с отладчиком на правильном FTDI-контроллере (есть чипы без поддержки MPSSE — например, FT232R, FT232B, FT232L), появится такое окно:

В Tigard применяется двухканальный чип FT2232H, поэтому в окне два варианта. В моём случае правильный канал — Channel B, выделяем его и жмём Select. Затем, в разделе Debug System в поле Clock Speed (Hz) указываем частоту, которую поддерживает ваш FTDI. Например, для FT2232H максимум — 30 МГц (на всякий случай, поле позволяет вводить значение вручную).
Убеждаемся, что отмечены пункты Enumerate APs, Read CoreSight ROM Tables и Read Trace Topology, затем нажимаем Advanced Options и проверяем, чтобы в поле ProbeMode был выбран JTAG. Теперь можно нажать Autodetect Platform. Если подключения не произошло (ошибка Autodetection Failed в окне Console) , пробуем уменьшить частоту или проверяем пайку/провода:

В случае успеха в окне Console появится лог подключения, где последней строкой будет Autodetection Complete:

В левой части окна Platform Configuration Editor появятся обнаруженные Debug Port (DP), доступные Access Point (AP) и другие элементы таблицы Rom Table:

Если некоторые элементы отмечены жёлтым треугольником, возможно, адрес Rom Table выбран неверно. В таком случае выбираем нужный AP (например, CSMEMAP) и в таблице Device Information в поле ROM_TABLE_BASE_ADDRESS вписываем новое значение, например 0x80800000, после чего в контекстном меню AP выбираем пункт Read CoreSight ROM Tables:


Чтобы сформировать и сохранить результаты сканирования, в контекстном меню ранее созданного SDF-файла выбираем Build Platform. В результате появятся файлы dtsl_config_script.py и project_types.xml.
Отладка через JTAG
Для подключения к ARM-чипу необходимо создать отладочное подключение (Debug Connection). Для этого в окне Debug Control выбираем Create a debug connection… или идём в File → New → Hardware Connection:

В появившемся окне New Debug Connection выбираем тип Hardware Connection и жмём Next:

Затем в окне Hardware Connection вписываем имя подключения (например, debug_conn), выбираем пункт Associate debug connection with an existing project, выделяем созданную ранее базу debug_configs и нажимаем Next:

В окне Target Selection выбираем созданного производителя и его чип (в моём случае Atmel → ATSAM3X8E), затем Finish:

После этого откроется окно Edit configuration and launch, где нужно выбрать ядро для отладки (в моём случае единственный вариант — Cortex-M3), в поле Target Connection снова указать FTDI MPSSE JTAG, нажать Browse и выбрать Channel B для Tigard:

Жмём Select, затем — Apply. На вкладке Files можно дополнительно загрузить ELF-файлы с символами или SVD для идентификации регистров:


Вот теперь можно нажимать Debug. В результате в окне Debug Control отобразятся все запущенные ядра. Доступных ядер может быть больше одного, если выбрать SMP-цель для отладки. В этом случае типичным названием для неё будет, например, Cortex-A76x4 SMP:

Если нажать на кнопку паузы (или клавишу F9), появится окно Disassembly с исполняемым в текущий момент кодом, а выполнение на ядре приостановится:

В окне Registers можно увидеть все доступные регистры, включая управляющие, Aarch64 (если применимо) и многие другие:


Как видите, список регистров достаточно объёмный. На этом с отладкой через JTAG закончим и перейдём к SWD.
Отладка через SWD
Для отладки через этот интерфейс я использую ранее упомянутый BluePill с прошивкой dap42 и загрузчиком dapboot. Сборка и прошивка файлов этих проектов в вашу «пилюлю» в статье не рассматривается. Но отмечу, что важно собирать прошивку в режиме HID. После прошивки на BluePill будет задействована следующая распиновка SWD:
SWDIO → PB14,
SWCLK → PB13,
GND → GND.

В качестве тестового устройства использую Raspberry Pi 5 с чипом Broadcom BCM2712. Чтобы включить отладку по SWD на «малине», нужно добавить строку enable_jtag_gpio=1 в файл config.txt раздела /boot.
В большинстве шагов отладка по SWD не отличается от JTAG, поэтому отмечу только разницу. Обратите внимание на скриншот ниже:
выбрана частота 2 МГц,
выбран отладчик CMSIS-DAP с указанием серийного номера.

В ProbeMode выбираем SWD, а в SWJEnable обязательно указываем True:

После нажатия кнопки Autodetect Platform должна появиться длинная портянка доступных ядер, с возможностью отладки как физических ядер (Bare Metal Debug), так и ядра Linux (Linux Kernel and/or Device Driver Debug):

На этом всё. Спасибо за внимание! Надеюсь, статья окажется для вас полезной.
Спойлер
P.S. У нашей исследовательской лаборатории есть телеграм-канал: [@bizone_hwlab](https://t.me/bizone_hwlab), в который мы периодически выкладываем разные интересные штуки, связанные с аппаратной безопасностью. Заходите, всем будем рады:)
