14.1.1.4. Men-debug firmware¶
Debugging pada hardware berarti menghentikan prosesor, menetapkan breakpoint dalam source C, melakukan single-stepping, dan memeriksa variabel, memori, register, dan periferal -- dari dalam VS Code. Ini membutuhkan tiga hal: sebuah debug build, sebuah SWD debug probe (Segger J-Link), dan ekstensi Cortex-Debug yang menjalankan arm-none-eabi-gdb terhadap J-Link GDB server.
14.1.1.4.1. Build untuk debugging¶
Selalu build ulang target dengan DEBUG=1
make -j$(nproc) TARGET=<TARGET> DEBUG=1
Citra rilis (DEBUG=0) dikompilasi dengan -O2; di debugger Anda akan melihat <optimized out> untuk banyak variabel, fungsi-fungsi yang di-inline menyatu ke pemanggilnya, dan stepping melompat-lompat secara tidak terduga. DEBUG=1 di-build dengan -Og -ggdb3, yang dapat di-debug namun tetap bisa booting pada kamera. ELF yang Anda arahkan ke debugger adalah:
build/<TARGET>/bin/firmware.elf
(Untuk Alif AE3, debug build/OPENMV_AE3/bin/firmware_M55_HP.elf -- core berkinerja tinggi.)
14.1.1.4.2. Hardware: J-Link melalui SWD¶
Hubungkan Segger J-Link ke pin SWD kamera (SWDIO, SWCLK, GND, dan VCC target sebagai referensi; kamera dinyalakan melalui USB seperti biasa). J-Link EDU / Base / Pro semuanya bisa digunakan. Lokasi pin debug berbeda-beda per kamera -- banyak board memiliki konektor JTAG/SWD tersendiri, lainnya mengekspos SWD pada header I/O atau pada test pad -- jadi periksa diagram pinout dan skematik board tersebut dalam dokumentasi hardware OpenMV untuk mengetahui pin mana yang perlu dihubungkan. Pasang J-Link Software and Documentation Pack dari segger.com pada mesin tempat probe secara fisik terhubung. Pertahankan agar tetap cukup terkini -- perangkat lunak J-Link yang lebih lama tidak akan mengenali nama perangkat yang lebih baru (STM32N6, MIMXRT, Alif).
Setiap MCU membutuhkan nama perangkat J-Link yang tepat agar probe memuat flash loader dan peta memori yang benar:
Kamera ( |
MCU |
J-Link |
|---|---|---|
|
STM32F427 |
|
|
STM32F765 |
|
|
STM32H743 |
|
|
STM32N657 |
|
|
MIMXRT1062 |
|
|
Alif Ensemble (M55-HP) |
|
|
STM32H747 |
|
14.1.1.4.3. Pengaturan VS Code Cortex-Debug¶
Buat .vscode/launch.json di repositori. Kasus paling sederhana -- VS Code, J-Link, dan build semuanya berada pada mesin Linux / macOS yang sama -- menggunakan servertype: "jlink", yang membuat Cortex-Debug memulai J-Link GDB server sendiri:
{
"version": "0.2.0",
"configurations": [
{
"name": "OpenMV J-Link",
"type": "cortex-debug",
"request": "launch",
"cwd": "${workspaceFolder}",
"executable": "${workspaceFolder}/build/OPENMV4/bin/firmware.elf",
"servertype": "jlink",
"device": "STM32H743VI",
"interface": "swd",
"runToEntryPoint": "main",
"armToolchainPath": "${env:HOME}/openmv-sdk-1.6.0/gcc/bin",
"gdbPath": "${env:HOME}/openmv-sdk-1.6.0/gcc/bin/arm-none-eabi-gdb"
}
]
}
Ubah executable dan device untuk board Anda (lihat tabel di atas). Tekan F5 untuk build-flash-and-run ke main dan berhenti di sana.
Tip
Untuk melakukan build ulang otomatis setiap kali Anda memulai debugging, tambahkan build task ke .vscode/tasks.json dan referensikan dari launch config dengan "preLaunchTask". Misalnya sebuah task yang menjalankan make -j$(nproc) TARGET=OPENMV4 DEBUG=1, bernama "build-firmware", ditambah "preLaunchTask": "build-firmware" dalam konfigurasi di atas, sehingga F5 melakukan build ulang, flashing, dan memulai debugger dalam satu langkah.
Peringatan
Cortex-Debug membutuhkan arm-none-eabi-gdb. Ia disertakan dalam SDK di ~/openmv-sdk-<version>/gcc/bin tetapi tidak berada di PATH secara default, sehingga debugging gagal dengan "GDB executable 'arm-none-eabi-gdb' was not found". Perbaiki dengan mengatur armToolchainPath / gdbPath seperti ditunjukkan di atas, atau dengan menambahkan ~/openmv-sdk-<version>/gcc/bin ke PATH Anda (printenv PATH kemudian harus menampilkannya).
14.1.1.4.4. Tampilan register periferal (SVD)¶
Arahkan Cortex-Debug ke file CMSIS SVD untuk mendapatkan tampilan register periferal yang telah diterjemahkan (timer, DMA, antarmuka kamera, dll.) berdasarkan nama dan bitfield:
"svdFile": "/path/to/STM32H743.svd"
Untuk STM32 dan MIMXRT, dapatkan SVD dari paket CMSIS ST / NXP atau registri SVD Cortex-Debug. SVD Alif disertakan dalam repositori firmware di lib/micropython/lib/alif_ensemble-cmsis-dfp/Debug/SVD/ (gunakan ..._CM55_HP_View.svd untuk core HP AE3).
14.1.1.4.5. Windows: jembatan WSL ↔ Windows J-Link¶
WSL 2 tidak dapat melihat perangkat USB J-Link secara langsung, sehingga pembagiannya adalah: Windows melayani probe (tempat perangkat terhubung) dan VS Code + gdb berjalan di WSL serta mencapainya melalui TCP.
Di Windows, pasang paket Segger J-Link dan hubungkan J-Link ke port USB Windows.
Di Windows, jalankan J-Link Remote Server (disertakan dengan paket J-Link): jalankan dengan J-Link terpasang dan klik OK. Izinkan melalui firewall Windows saat diminta. Jendela menampilkan alamat IP tempat probe disajikan -- catat alamat tersebut.
Di WSL, build dengan
DEBUG=1dan pastikanarm-none-eabi-gdbdapat diakses (aturarmToolchainPathseperti di atas).Di VS Code WSL, pertahankan
servertype: "jlink"-- GDB server berjalan di WSL dan mencapai probe melalui Remote Server -- serta tambahkanserverpath+ipAddress{ "name": "OpenMV J-Link (Windows host)", "type": "cortex-debug", "request": "launch", "cwd": "${workspaceFolder}", "executable": "${workspaceFolder}/build/OPENMV4/bin/firmware.elf", "servertype": "jlink", "serverpath": "/opt/SEGGER/JLink/JLinkGDBServer", "ipAddress": "192.168.x.x", "device": "STM32H743VI", "interface": "swd", "runToEntryPoint": "main", "armToolchainPath": "${env:HOME}/openmv-sdk-1.6.0/gcc/bin" }
Atur
ipAddresske alamat yang ditampilkan jendela Remote Server. Itulah seluruh jembatannya.
Tip
Alternatif untuk jembatan GDB-server: usbipd-win. Alih-alih menjalankan server di Windows, Anda dapat melampirkan perangkat USB J-Link langsung ke WSL dengan usbipd-win. Dari PowerShell administrator:
winget install usbipd
usbipd list
usbipd bind --busid <busid>
usbipd attach --wsl --busid <busid>
(<busid> adalah bus ID J-Link dari usbipd list.) Probe kemudian muncul di dalam WSL, dan Anda menggunakan konfigurasi servertype: "jlink" mesin yang sama dari VS Code Cortex-Debug setup tanpa alamat IP dan tanpa server Windows terpisah. Jembatan GDB-server membutuhkan pengaturan lebih sedikit untuk penggunaan sesekali; usbipd-win lebih nyaman untuk pengembangan rutin.
Tip
Gunakan "request": "attach" untuk men-debug firmware saat sudah berjalan tanpa mereset atau mereflash -- ideal untuk menangkap hang di lapangan. Gunakan "request": "launch" untuk mereset, flash ELF, dan memulai dari awal di runToEntryPoint.
14.1.1.4.6. Debugging command-line dengan gdbrunner¶
Menyiapkan sesi GDB terhadap target tertanam secara manual adalah proses lima langkah: mulai J-Link / ST-Link GDB server di satu jendela dengan flag perangkat, port, dan antarmuka yang tepat; tunggu hingga mencetak Waiting for GDB connection; jalankan arm-none-eabi-gdb di jendela kedua; ketik target remote localhost:<port>; arahkan gdb ke ELF. Ketika sesi gdb berakhir, ingat untuk mematikan jendela server. gdbrunner adalah CLI kecil yang menggabungkan semua itu menjadi satu perintah foreground. Ia disertakan dalam lingkungan Python SDK OpenMV, jadi tidak ada yang perlu dipasang; titik masuk biasanya adalah target make debug repositori firmware:
make -j$(nproc) TARGET=<TARGET> DEBUG=1 debug
Ini menjalankan gdbrunner dengan argumen debugger dari konfigurasi board -- nama perangkat J-Link dan, bila diperlukan, flash loader eksternal ST-Link -- dengan arm-none-eabi-gdb SDK sudah ada di PATH. Backend default adalah J-Link; make DEBUGGER=STLINK debug bekerja dengan probe ST-Link.
gdbrunner juga dapat dipanggil langsung (di luar SDK, pip install gdbrunner):
gdbrunner jlink --device STM32H743VI build/OPENMV4/bin/firmware.elf
gdbrunner stlink build/OPENMV4/bin/firmware.elf
gdbrunner qemu --machine mps2-an500 build/MPS2_AN500/bin/firmware.elf
Argumen posisional pertama memilih backend server (jlink, stlink, qemu); sisanya diteruskan ke backend tersebut, dengan default yang berfungsi untuk kamera OpenMV. gdbrunner --help mencantumkan daftar flag per-backend lengkap; tabel argumen setiap backend didorong oleh JSON (src/gdbrunner/backends.json), sehingga menambahkan server baru adalah pengeditan konfigurasi bukan kode.
Yang dilakukan gdbrunner untuk pekerjaan command-line:
Satu proses, lifecycle bersih. Server dimulai, gdb terhubung saat port terbuka, server dihentikan dengan bersih saat gdb keluar. Tidak ada
JLinkGDBServeryatim yang bertahan setelah sesi, tidak ada dua terminal yang perlu dikelola.Penemuan otomatis STM32CubeProgrammer. Backend
stlinkmencari lokasi instalasi yang umum (~/STM32CubeProgrammer/,/opt/st/, pohon plugin STM32CubeIDE) untuk alat STM32CubeProgrammer, sehingga path--cube-progyang panjang tidak perlu diketik setiap saat. SDK menyertakan salinannya sendiri di~/openmv-sdk-<version>/stcubeprog/bin-- arahkan--cube-progke sana jika tidak ada instalasi sistem.gdbinit per-proyek dihormati. Sebuah
.gdbinitdi direktori saat ini dimuat dengan-ix-- mengesampingkan~/.gdbinityang berlaku untuk seluruh pengguna -- sehingga skrip gdb per-proyek (pretty-printer, makro spesifik board, set breakpoint) aktif dengan hanya menempatkannya di direktori kerja.make debugdijalankan dari root repositori, sehingga.gdbinitdi sana berlaku.Dry run.
--dryrunmencetak perintah server tanpa menjalankannya, berguna untuk menyesuaikan pemanggilan ke skrip wrapper, menyalinnya ke konfigurasi launcher IDE, atau hanya memeriksa argumen apa yang disusun oleh gdbrunner.Output server terlihat.
--show-outputmembuat stdout / stderr server tetap terlihat. Default menekannya (agar UI gdb tetap bersih); balik flag saat server itulah yang bermasalah.Backend QEMU.
qemu-system-armmen-debug build firmware tanpa board yang terhubung. TargetMPS2_AN500memilih backend ini dalam konfigurasi boardnya, sehinggamake TARGET=MPS2_AN500 DEBUG=1 debugdi-build untuk mesin QEMUmps2-an500dan menelusuri kode yang independen dari platform -- semua yang tidak menyentuh periferal spesifik kamera -- dalam simulasi. (qemu-system-armadalah instalasi host, bukan bagian dari SDK.)
Untuk stepping level source dengan gutter breakpoint dan tampilan register periferal, pengaturan VS Code Cortex-Debug di atas adalah alat yang lebih baik; gdbrunner adalah alat yang tepat untuk semua yang berada di command line.
14.1.1.4.7. Menggunakan debugger¶
Setelah sesi berjalan (prosesor berhenti di main):
Breakpoint -- klik gutter di sebelah baris C, atau di Debug Console
break <file>:<line>/break <function>. Core Cortex-M memiliki sejumlah kecil hardware breakpoint comparator (biasanya 6--8 pada M7 / H7, 8 pada M55). Melebihi itu pada kode di flash akan gagal secara diam-diam -- jaga agar jumlah breakpoint aktif tetap terbatas.Stepping -- F10 step over (
next), F11 step into (step), Shift+F11 step out (finish), F5 lanjutkan. Stepping tingkat instruksi adalahstepi/nextidi Debug Console.Variabel / watch / call stack -- panel Variables dan Call Stack menampilkan variabel lokal dan backtrace; tambahkan ekspresi ke Watch. Arahkan kursor ke variabel di source untuk melihat nilainya. Apa pun yang menampilkan
<optimized out>berarti Anda tidak menggunakan buildDEBUG=1.Watchpoint (data breakpoint) --
watch <expr>berhenti saat variabel ditulis,rwatchsaat dibaca,awatchuntuk keduanya. Unit DWT Cortex-M mendukung ~4 hardware watchpoint -- sangat berharga untuk menangkap siapa yang merusak variabel.Register dan periferal -- tampilan Cortex Registers menampilkan register inti; dengan
svdFilediatur, tampilan Peripherals mendekode setiap register periferal dan bitfield (DMA, timer, antarmuka kamera / CSI, XSPI, dll.) -- cara tercepat untuk melihat mengapa driver bermasalah.Memori -- gunakan penampil memori Cortex-Debug atau
x/gdb untuk memeriksa buffer bingkai, buffer DMA, dan struktur secara langsung.printf tanpa menghentikan (SWO/RTT) -- untuk masalah yang sensitif terhadap waktu, Segger RTT atau SWO memberikan
printfdengan overhead hampir nol saat target berjalan. Build denganDEBUG_PRINTF=1dan tambahkanrttConfig(RTT) atauswoConfig(SWO, membutuhkan clock inti) dari Cortex-Debug. Ini adalah alat yang tepat ketika breakpoint akan mengubah timing yang sedang Anda amati.Memutuskan koneksi -- Stop pada sesi
launchmenghentikan target; Disconnect pada sesiattachmembiarkan kamera tetap berjalan. Matikan dan hidupkan kembali kamera untuk mengembalikannya ke operasi normal setelahnya.
14.1.1.4.8. Jebakan dalam debugging¶
Variabel ter-optimasi-keluar. Semuanya menampilkan
<optimized out>-- Anda membangun denganDEBUG=0. Build ulang denganDEBUG=1."GDB executable not found" -- SDK
gcc/bintidak ada diPATH; aturarmToolchainPath/gdbPath."Cannot connect" / peta memori salah -- nama
devicesalah atau tidak ada; gunakan string yang tepat dari tabel.Breakpoint diam-diam tidak terpicu -- terlalu banyak hardware breakpoint pada kode yang berada di flash; kurangi jumlahnya.
Path source tidak cocok (ELF yang di-build dengan Docker) -- build dengan target Docker
build-firmware-dev(path absolut yang sama di dalam dan di luar container) atau atur gdbset substitute-path.