Спросили меня тут недавно, как приспособить дебаггер GDB для отладки софта на микроконтроллере PIC32. Подготовил краткий обзор.
Вам понадобится:
- Компьютер с установленныи Линуксом. В принципе, всё то же самое можно проделать на Маке или на Windows, но мне с Линуксом удобнее.
- Плата chipKIT Wi-Fire с каким-нибудь приложением. В качестве примера я задействую ядро опреационной системы LiteBSD, прошитое во Flash-память микроконтроллера, с файловой системой на карточке micro-SD.
- Bus Blaster for MIPS для подключения к отладочному порту EJTAG через USB.
- Два кабеля мини-USB, для подключения плат Wi-Fire и Bus Blaster к линуксному компьютеру.
- Бинарник GDB из пакета MIPS Codescape GNU Toolchain, MTI Bare Metal release.
1. Подсоединяем Bus Blaster к отладочному порту
Подключите Bus Blaster через плоский кабель и переходник 14-на-6 контактов к разъёму JTAG платы Wi-Fire.

2. Втыкаем кабели USB
Подключите кабели мини-USB cables к Вашему линуксному компьютеру. Устройства должны быть видны как:
$ lsusb
Bus 002 Device 040: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
Bus 002 Device 041: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
3. Запускаем отлаживаемое приложение
В этом примере, мы входим в LiteBSD на PIC32 и запускаем утилиту vmstat.
Консольный порт доступен как /dev/ttyUSB0, со скоростью 115200 бит/сек:
$ kermit -c -l /dev/ttyUSB0 -b 115200
4.4BSD-Lite (bsd.net) (console)
login: root
/root # vmstat 1
procs --memory--- ---------page---------- disk ---faults--- --cpu---
r b w avm fre flt re pi po fr sr sd0 in sy cs us sy id
0 0 0 12968 16 294 15 84 25 0 110 143 104 150 289 17 18 64
0 0 0 12972 20 8 1 4 2 0 8 3 129 19 21 0 1 99
...
4. Запускаем ejtagproxy
Создайте новое окно терминала в Линуксе и запустите в нём утилиту ejtagproxy. Она создает TCP-порт с номером 2000 и ждёт подключения отладчика GDB:
$ ejtagproxy
GDB proxy for Microchip PIC32 processors, Version 1.0.34
...
ejtagproxy: waiting on TCP port 2000
Утилита ejtagroxy будет перенаправлять запросы от GDB через Bus Blaster к отлаживаемому микроконтроллеру PIC32.
5. Стартуем отладчик GDB
В случае, если у Вас имеется бинарный ELF-файл Вашего приложения - используйте его при запуске GDB. Без него отладчик не будет иметь представления об именах и адресах в Вашей программе, и все имена функций будут печататься как '??'.
Здесь я использую 'vmunix.elf', бинарный файл ядра LiteBSD.
$ mips-mti-elf-gdb vmunix.elf
GNU gdb (Codescape GNU Tools 2019.02-01 for MIPS MTI Bare Metal) 7.9.1
...
Reading symbols from vmunix.elf...done.
(gdb) _
GDB стартовал, но пока не соединился с отлаживаемой платой.
Подключимся, но сначала сообщим отладчику "
остроконечность" нашего процессора, а также количество реализованных в аппаратуре точек останова и контроля данных. Эти значения можно узнать из документации на микроконтроллер PIC32:
(gdb) set endian little
The target is assumed to be little endian
(gdb) set remote hardware-breakpoint-limit 6
(gdb) set remote hardware-watchpoint-limit 2
(gdb) target remote localhost:2000
Remote debugging using localhost:2000
0x9d00197c in idle ()
(gdb) _
Отладчик подключился и остановил выполнение программы на процессоре PIC32.
В окошке ejtagproxy Вы можете видеть информацию об аппаратуре:
ejtagproxy: connected
adapter: Dangerous Prototypes Bus Blaster, id 0403:6010
processor: Microchip PIC32MZ2048ECG100
processor: reset occured
hardware: 8 breakpoints, 4 watchpoints
oscillator: internal Fast RC
Продолжим выполнение приложения:
(gdb) c
Continuing.
Чтобы остановить программу, нажмите ^C:
^C
Program received signal SIGTRAP, Trace/breakpoint trap.
0x9d00197c in idle ()
(gdb) _
Сделаем несколько шагов по одной машинной команде, и напечатаем текущую команду:
(gdb) si
0x9d000200 in _interrupt_vector ()
(gdb) si
0x9d000204 in _interrupt_vector ()
(gdb) si
0x9d000208 in _interrupt_vector ()
(gdb) si
0x9d000210 in _interrupt_vector ()
(gdb) x/i $pc
=> 0x9d000210 <_interrupt_vector+16>: j 0x9d000468 <kern_interrupt>
0x9d000214 <_interrupt_vector+20>: nop
(gdb) _
Посмотрим содержимое машинных регистров:
(gdb) i reg
zero at v0 v1 a0 a1 a2 a3
R0 00000000 a0000000 00000000 00004bbb c0106000 00000800 591b9a64 00000000
t0 t1 t2 t3 t4 t5 t6 t7
R8 00000000 00000000 00004bbc 00000000 00000000 00000000 00000000 00000000
s0 s1 s2 s3 s4 s5 s6 s7
R16 c0106000 00000001 c010e600 00000000 a0000878 c0106100 00412c9c 00410000
t8 t9 k0 k1 gp sp s8 ra
R24 00000001 00000000 00000000 9d00197c a0000000 ffffdf00 00410000 9d00b074
sr lo hi bad cause pc
00000003 851f6cb8 0000ce2b c010a509 40801800 9d000210
(gdb) _
Опять продолжим выполнение:
(gdb) c
Continuing.
И так далее.