MIPSfpga и внутрисхемная отладка

Поставляемые в составе пакета MIPSfpga документация, ПО и конфигурационные файлы предполагают применение Bus Bluster в качестве аппаратного отладчика. Статья содержит инструкции по использованию для этой цели практически любого USB-UART адаптера, построенного на микросхеме FTDI с поддержкой MPSSE (FT232H, FT2232H, FT4232H, FT2232D). Кратко описывается интеграция среды разработки Visual Studio Code и отладчика GNU GDB.

Все конфигурационные файлы, описываемые в статье, а также часть документации доступны на github.

Элементы системы

Основные элементы системы, протоколы их взаимодействия (интерфейсы) с кратким описанием приведены ниже.

MIPSfpga — промышленное процессорное ядро MIPS microAptiv, исходные коды которого доступны под академической лицензий [L1]. MIPSfpga-plus — проект системы на кристалле, построенной на базе ядра MIPSfpga [L2]. В моем случае система развернута на плате Terasic DE10-Lite c ПЛИС Altera MAX10 на борту [L3].

В качестве адаптера (программатора, отладчика) между MIPSfpga-plus и ПК выступает плата Pinboard II [L4] с микросхемой FT2232 [D1] производства компании FTDI [L5]. Физически платы связаны между собой интерфейсами UART и JTAG [L6]. Первый используется для консольного доступа к отлаживаемой системе. Второй — является базовым интерфейсом для отладки с использованием EJTAG [D7]. Разница между JTAG и EJTAG очень хорошо показана в [L7].

Ключевой технологией, которая существенно упрощает построение программаторов и отладчиков на базе микросхем FTDI, является Multi-Protocol Synchronous Serial Engine (MPSSE) [D2, D3, D4]. Поддержка MPSSE является принципиальным моментом для описываемой в статье конфигурации. Получить схожие результаты вы сможете только на USB-адаптерах, построенных на базе следующих микросхем FTDI: FT232H, FT2232H, FT4232H, FT2232D.

На стороне ПК взаимодействие с USB-платой осуществляется: для канала UART — с использованием обычных драйверов от FTDI и любой терминальной программы, для канала MPSSE используются драйвер WinUSB (работа проводилась на Windows — системе).

Для компиляции используются Codescape GNU Tools [D9], для отладки — традиционная связка OpenOCD [L8, D8] и GNU GDB [D5]. Эти программные пакеты входят в состав Codescape MIPS SDK [L12]. Их взаимодействие между собой осуществляется по протоколу gdbserver [L9].

В качестве GUI при отладке применена Visual Studio Code (VSCode) [L10] с установленным расширением vscode-cpptools [L11]. В силу того, что это расширение ориентировано на высокоуровневую разработку (C/C++), в интерфейсе отсутствуют такие представления как просмотр инструкций ассемблера, просмотр памяти, прямой доступ к регистрам.

Кратко об MPSSE и FTDI

MPSSE — это аппаратно реализованный набор примитивных функций, которые существенно упрощают реализацию последовательных интерфейсов (SPI, I2C, JTAG). Например: отправить N бит по фронту тактового сигнала, прочитать M бит по спаду, установить вывод Х в ноль и т.д.

До 2014 года китайцы в существенных масштабах клепали контрафактные микросхемы FTDI, по этой причине USB-UART преобразователи на их основе были одними из самых распространенных на площадках типа ebay или aliexpress. А разработчики — с радостью строили на них свои решения, взять хотя бы ту же поддержку со стороны OpenOCD. Список выпускаемых FTDI микросхем USB-адаптеров приведен ниже, имеющие поддержку MPSSE — отмечены цветом.

В 2014 году компания FTDI выпускает обновленные драйвера, которые отказываются работать с контрафактными устройствами [L13, L14]. Количество предложений на эти USB-UART адаптеры с тех пор несколько сократилось, но они все равно остаются одними из самых распространенных из имеющихся на руках у разработчиков.

Еще FTDI, несмотря на прекрасные чипы, иногда ругают за качество ПО к ним. Возможно, это у меня кривые руки, но изрядно намучившись в свое время с работой с libMPSSE из под .NET, я написал свой аналог этой библиотеки на C# [L15].

Если кто-то из читателей знает адекватную альтернативу для чипов FTDI, недорогую и при этом корректно поддерживаемую OpenOCD — буду благодарен за информацию.

 

Схема USB-модуля

Ниже представлен фрагмент схемы отладочной платы Pinboard II, в вашем случае схема модуля может отличаться. Основным определяющим для нас параметром является возможность прямого доступа к портам микросхемы: для работы достаточно одного свободного MPSSE канала (для TCK, TDI, TDO, TMS) + 1 GPIO выход для сигнала сброса (SRSTn). Для второго канала микросхемы функциональность MPSSE обязательной не является, его при этом удобно использовать для UART взаимодействия с отлаживаемой системой.

Выводы микросхемы FTDI напрямую подключаются к портам ПЛИС. Строго говоря, это является нарушением [D7, D6], т.к. предполагается, что там должны быть установлены pull-up, pull-down или последовательно включенные резисторы. У меня все работает без них: внимательно проверяйте настройку портов на вход-выход, проверьте ограничение максимального тока на задействованных для EJTAG портах ПЛИС.

Напряжение на выводах адаптера установлено в 3.3V. В случае Pinboard II для выбора этого напряжения предусмотрен отдельный джампер (VCCIO_PWR_SEL). Для других плат — ориентируйтесь на их схемы и настройки ПЛИС, в отдельных случаях может потребоваться доработка адаптера (что проще) и/или схема преобразования уровней [L16] (что сложнее и может привести к помехам или снижению скорости).

 

Типовое подключение EJTAG

Типовая схема подключения по EJTAG интерфейсу получена из [D6]. Опциональные входы DINT и TRSTn в рассматриваемой конфигурации не используются. Соответствие остальных — приведено в таблице.

 

Таблица подключения USB-модуля к ПЛИС:

 

Конфигурационные файлы

mipsfpga_ftdi.cfg

  • основной и единственный конфигурационный файл для OpenOCD;
  • условно может быть разделен на 2 части: одна описывает соединение программатора и целевой системы (interface part), вторая — настройки, специфические для отлаживаемого ядра (target part). Внутри каталога OpenOCD они обычно размещаются в разных папках, здесь — для упрощения объединены в один.

c_cpp_properties.json

  • файл конфигурации расширения vscode-cpptools;
  • содержит информацию о местонахождении заголовочных файлов, необходимую для упрощения навигации по исходникам и работе функции автозавершения в окне редактора VSCode.

launch.json

  • конфигурационный файл VSCode, содержащий настройки запуска отлаживаемой программы;
  • в данном случае описывает два профиля запуска: «MIPS Load» — загрузить прошивку в память системы, после чего приступить к отладке; «MIPS Attach» — подключиться к уже прошитой системе.

 

Первичная настройка

  • подключить USB-модуль к ПК;
  • дождаться, пока установятся драйвера FTDI, используя программу Zadig, выполнить смену драйвера на канале с MPSSE на WinUSB;
  • скопировать конфигурационный файл mipsfpga_ftdi.cfg в каталог с OpenOCD;
  • в случае, если ваша схема подключения по каким-то причинам отличается от приведенной в таблице, необходимо пересчитать параметры инициализации OpenOCD, в частности, аргументы команд ftdi_layout_init и ftdi_layout_signal. Рассмотрим порядок их получения для приведенной выше таблицы подключения:

ftdi_layout_init 0x0018 0x081b

0x0018 — установить 1 как начальное значение на портах ADBUS3 и ADBUS4 (биты 3 и 4 соответственно);

0x081b — настроить порты ADBUS0,1,3,4, ACBUS3 на выход (биты 0-3,4, 11).

Соответствие выводов конкретным битам приведено в разделе 2.1 аппноты [D3].

Для команды ftdi_layout_signal логика та же, совпадающие аргументы параметров -data и -oe (output enable) означают, что подключение производится напрямую, без какого-либо буфера. Использование -ndata — позволяет инвертировать выход.

 

Настройки на стороне MIPSFpga

  • при инициализации EJTAG-подключения отлаживаемое устройство передает на ПК значение регистра IDCODE, которое задается разработчиком в RTL коде. Рекомендую установить какие-либо произвольные (ненулевые) значения в этот регистр, т.к. это поможет при определении ошибок подключения: если полученный при подключении IDCODE не соответствует заданному в коде, значит где-то уже закралась ошибка.
  • формат этого регистра [D7] следующий:

  • параметры EJ_ManufID и EJ_PartNumber задаются в файле mfp_system.v;
  • проверить и установить значения EJ_DINT и EJ_TRST_N:
assign EJ_DINT            = 1'b0;
assign EJ_TRST_N       = 1'b1;

В рассматриваемой конфигурации для подключения они не используется.

 

Настройки компиляции

  • убедиться в том, что настройки компилятора в части использования памяти не противоречат параметрам команды configure в файле mipsfpga_ftdi.cfg;
  • добавить отладочные символы — параметры -g -gdwarf-2
  • установить уровень оптимизации -O0 или -O1. С -O2 отладка также будет работать, но исполнение кода может быть не последовательным: указатель текущей выполняемой строки кода будет «прыгать».

 

Тест подключения

  • открыть файл mipsfpga_ftdi.cfg и закомментировать все команды, которые идут после настройки сигнала сброса (после reset_config). Раскомментировать команду shutdown. В этой конфигурации OpenOCD будет подключаться к отлаживаемому устройству, получать IDCODE и отключаться;
  • выполнить в консоли команду openocd-0.9.2.exe -f mipsfpga_ftdi.cfg
  • результатом ее корректного выполнения является следующий вывод:
Open On-Chip Debugger 0.9.1-dev-microAptiv-dirty (2015-05-08-15:32)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
adapter speed: 10000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
shutdown command invoked
Info : clock speed 10000 kHz
Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -expected-id 0x000f1005 ..."
Warn : AUTO auto0.tap - use "... -irlen 5"
Warn : gdb services need one or more targets defined

где 0x000f1005 — это ранее заданный IDCODE.

  • проверить, что получено именно то значение, которое ранее было задано в RTL-коде (mfp_system.v);
  • в случае, если значения расходятся, необходимо найти и устранить ошибку подключения. Возможно, что следует снизить скорость. В моем случае, к примеру, помеху вносили щупы подключенного логического анализатора.
  • после того, как корректное значение IDCODE успешно получено, файл можно вернуть в начальное состояние.

 

Отладка в консольном режиме

  • запустить openocd-0.9.2.exe -f mipsfpga_ftdi.cfg. Иногда, при внезапной потере связи OpenOCD может зависнуть, поэтому я предпочитаю запускать его в отдельном окне терминала.
  • корректным является следующий вывод:
Open On-Chip Debugger 0.9.1-dev-microAptiv-dirty (2015-05-08-15:32)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
adapter speed: 10000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
scan delay: 20000 nsec
running in fast queued mode
Info : clock speed 10000 kHz
Info : JTAG tap: auto0.tap tap/device found: 0x000f1005 (mfg: 0x002, part: 0x00f1, ver: 0x0)

После чего OpenOCD не прерывает работу и ожидает подключения от gdb.

  • в отдельном окне терминала запустите gdb и выполните несколько операций по отладке: подключение к отлаживаемой системе, загрузка прошивки, установка точки останова на вход в функцию main, запуск кода на выполнение, получение значения регистров после останова. Пример корректного выполнения данных команд приведен ниже:

> mips-mti-elf-gdb -q program.elf

Reading symbols from program.elf...done.

(gdb) target remote localhost:3333

Remote debugging using localhost:3333
0xbfc00000 in ?? ()

(gdb) set endian little

The target is assumed to be little endian

(gdb) monitor reset halt

JTAG tap: auto0.tap tap/device found: 0x000f1005 (mfg: 0x002, part: 0x00f1, ver: 0x0)
target state: reset
entered debug state at PC 0xbfc00000, target->state: halted
target state: halted
target halted in MIPS32 mode due to debug-request, pc: 0xbfc00000

(gdb) load

Loading section .text_ram, size 0x260 lma 0x80001000
Loading section .init, size 0x24 lma 0x80001260
Loading section .fini, size 0x1c lma 0x80001284
Loading section .eh_frame, size 0x4 lma 0x800012a0
Loading section .data, size 0xc lma 0x800012a4
Loading section .ctors, size 0x8 lma 0x800012b0
Loading section .dtors, size 0x8 lma 0x800012b8
Loading section .jcr, size 0x4 lma 0x800012c0
Loading section .reset, size 0x280 lma 0x9fc00000
Start address 0xbfc00000, load size 1348
Transfer rate: 12 KB/sec, 149 bytes/write.

(gdb) b main

Breakpoint 1 at 0x800011e0: file main.c, line 14.

(gdb) c

Continuing.
entered debug state at PC 0x800011e0, target->state: halted
[Remote target] #1 stopped.
main () at main.c:14
warning: Source file is more recent than executable.
14      {

(gdb) i r

zero       at       v0       v1       a0       a1       a2       a3
R0   00000000 deadbeef 800011e0 00000010 00000000 00000002 80001000 00000000
t0       t1       t2       t3       t4       t5       t6       t7
R8   deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
s0       s1       s2       s3       s4       s5       s6       s7
R16  deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
t8       t9       k0       k1       gp       sp       s8       ra
R24  deadbeef deadbeef deadbeef deadbeef 800092a8 80040000 00000000 9fc00274
status       lo       hi badvaddr    cause       pc
00400000 00000100 00000000 c0000000 00000008 800011e0

(gdb)

 

Настройка VSCode

  • скачать и установить Visual Studio Code [L17];
  • запустить, перейти в раздел расширений, установить расширение vscode-cpptools [L11];
  • открыть в VSCode каталог (т.н. workspace directory), который содержит исходные коды отлаживаемой программы;
  • в корне workspace directory создать папку .vscode, скачать и поместить в нее файлы c_cpp_properties.json и launch.json;
  • открыть эти файлы и скорректировать пути заголовочным файлам, gdb, а также к elf файлу, который предполагается загружать на отлаживаемую систему;
  • я столкнулся с небольшим багом, из-за которого пришлось явно указывать полный путь к elf файлу.

 

Отладка в VSCode

  • предполагается, что компиляция уже произведена и elf файл находится там, где предполагается настройками в launch.json;
  • запустить openocd-0.9.2.exe -f mipsfpga_ftdi.cfg аналогично тому, как это было описано выше;
  • в интерфейсе VSCode перейти в панель «Debug», выбрать профиль отладки MIPS Load;
  • запустить отладку;
  • если все настроено верно, то окно VSCode будет выглядеть примерно также, как изображено на скриншоте ниже;
  • несмотря на то, что интерфейсе VSCode отсутствуют специализированные представления для просмотра инструкций ассемблера, просмотра памяти и регистров, данную информацию можно получить в отладочной консоли, обращаясь непосредственно к gdb. Для этого используется команда -exec. Например: -exec i r
  • если что-то пошло не так, то следует раскомментировать раздел «logging» в файле launch.json и выполнить анализ ошибок в консоли отладки (открывается сочетанием клавиш (ctrl + `);

 

 

Благодарности

Автор выражает благодарность коллективу переводчиков учебника Дэвида Харриса и Сары Харрис «Цифровая схемотехника и архитектура компьютера», компании Imagination Technologies за академическую лицензию на современное процессорное ядро, персонально Юрию Панчулу YuriPanchul за его работу по популяризации MIPSfpga, а также DIHALT за отладочную плату, которая вот уже который год не покидает поверхность моего стола.

 

Ссылки

[L1] — Как начать работать с MIPSfpga;

[L2] — Проект MIPSfpga-plus на github;

[L3] — FPGA плата Terasic DE10-Lite;

[L4] — Отладочная плата Pinboard II;

[L5] — Сайт компании FTDI;

[L6] — Интерфейс JTAG? — Это очень просто!

[L7] — EJTAG: аттракцион для хакеров;

[L8] — OpenOCD: руководство пользователя (перевод);

[L9] — Wikipedia. gdbserver;

[L10] — Документация VSCode: Debugging;

[L11] — Документация VSCode: C/C++ for VS Code;

[L12] — Codescape MIPS SDK;

[L13] — FTDI наносит ответный удар;

[L14] — Воскрешаем FTDI в картинках;

[L15] — MPSSELight. Lightweight .net MPSSE library;

[L16] — Согласование логических уровней 5В и 3.3В устройств

[L17] — Visual Studio Code;

 Документация

[D1] — FTDI FT2232D Datasheet;

[D2] — FTDI Application Note AN 135. FTDI MPSSE Basics;

[D3] — FTDI Application Note AN 108. Command Processor for MPSSE and MCU Host Bus Emulation Modes;

[D4] — FTDI Software Application Development. D2XX Programmer’s Guide;

[D5] — Debugging with gdb. Codescape GNU Tools 2016.05-03 for MIPS MTI Bare Meta;

[D6] — MIPS32 microAptiv UP Processor Core Family Integrator’s Guide;

[D7] — EJTAG Specification. Document Number: MD00047;

[D8] — OpenOCD User’s Guide for release 0.8.0;

[D9] — Using the GNU Compiler Collection. Codescape GNU Tools 2016.05-03 for MIPS MTI Bare Metal;

[D10] — MIPSfpga Getting Started Guide;

Изображения

[P1] Основные элементы системы;

[P2] Характеристики микросхем USB-адаптеров FTDI (источник: L5);

[P3] Фрагмент схемы отладочной платы Pinboard II (источник: L4);

[P4] Типовая схема подключения по EJTAG интерфейсу (источник: D6);

[P5] Таблица подключения USB-модуля к ПЛИС;

[P6] Регистр IDCODE (источник: D7);

[P7] Visual Studio Code в режиме отладки (скриншот).