14.1.1.4. Aygıt yazılımının hata ayıklaması¶
Donanım üzerinde hata ayıklama, işlemciyi durdurmak, C kaynağında kesme noktaları ayarlamak, tek adım adım ilerlemek ve değişkenleri, belleği, yazmaçları ve çevre birimlerini incelemek anlamına gelir – hepsi VS Code içinden. Bunun için üç şey gerekir: bir hata ayıklama derlemesi (debug build), bir SWD hata ayıklama probu (bir Segger J-Link) ve bir J-Link GDB sunucusuna karşı arm-none-eabi-gdb çalıştıran Cortex-Debug uzantısı.
14.1.1.4.1. Hata ayıklama için derleme¶
Hedefi her zaman DEBUG=1 ile yeniden derleyin:
make -j$(nproc) TARGET=<TARGET> DEBUG=1
Bir sürüm (DEBUG=0) imajı -O2 ile derlenir; hata ayıklayıcıda birçok değişken için <optimized out> görürsünüz, satır içine alınmış işlevler çağıranların içinde toplanır ve adım adım ilerleme öngörülemez biçimde sıçrar. DEBUG=1 ise -Og -ggdb3 ile derler; bu, kamera üzerinde hâlâ önyükleme yapabilirken hata ayıklanabilir olmasını sağlar. Hata ayıklayıcıyı yönlendirdiğiniz ELF şudur:
build/<TARGET>/bin/firmware.elf
(Alif AE3 için build/OPENMV_AE3/bin/firmware_M55_HP.elf dosyasında hata ayıklayın – yüksek performanslı çekirdek.)
14.1.1.4.2. Donanım: SWD üzerinden J-Link¶
Bir Segger J-Link’i kameranın SWD pinlerine bağlayın (SWDIO, SWCLK, GND ve referans için hedef VCC; kamera her zamanki gibi USB üzerinden güç alır). Bir J-Link EDU / Base / Pro hepsi çalışır. Hata ayıklama pinlerinin yüzeye çıktığı yer her kamerada farklılık gösterir – birçok kartta özel bir JTAG/SWD konektörü vardır, diğerleri SWD’yi G/Ç başlığında veya test pedlerinde açığa çıkarır – bu nedenle hangi pinleri bağlamanız gerektiğini OpenMV donanım belgelerindeki ilgili kartın pin çıkış diyagramında ve şemasında kontrol edin. Probun fiziksel olarak takılı olduğu makineye segger.com adresinden J-Link Software and Documentation Pack‘i kurun. Bunu makul ölçüde güncel tutun – eski J-Link yazılımı yeni cihaz adlarını (STM32N6, MIMXRT, Alif) bilmeyecektir.
Her MCU, probun doğru flash yükleyiciyi ve bellek haritasını yüklemesi için kendi tam J-Link cihaz adına ihtiyaç duyar:
Kamera ( |
MCU |
J-Link |
|---|---|---|
|
STM32F427 |
|
|
STM32F765 |
|
|
STM32H743 |
|
|
STM32N657 |
|
|
MIMXRT1062 |
|
|
Alif Ensemble (M55-HP) |
|
|
STM32H747 |
|
14.1.1.4.3. VS Code Cortex-Debug kurulumu¶
Depoda .vscode/launch.json oluşturun. En basit durum – VS Code, J-Link ve derlemenin tümü aynı Linux / macOS makinesinde olduğunda – Cortex-Debug’ın kendisinin bir J-Link GDB sunucusu başlatmasını sağlayan servertype: "jlink" kullanır:
{
"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"
}
]
}
Kartınıza göre executable ve device değerlerini değiştirin (yukarıdaki tabloya bakın). main işlevine kadar derle-flash’la-ve-çalıştır işlemini yapıp orada durmak için F5 tuşuna basın.
Tüyo
Hata ayıklamayı her başlattığınızda otomatik olarak yeniden derlemek için .vscode/tasks.json dosyasına bir derleme görevi ekleyin ve başlatma yapılandırmasından "preLaunchTask" ile ona referans verin. Örneğin, "build-firmware" adında make -j$(nproc) TARGET=OPENMV4 DEBUG=1 çalıştıran bir görev ile yukarıdaki yapılandırmadaki "preLaunchTask": "build-firmware" birlikte, böylece F5 tek bir adımda yeniden derler, flash’lar ve hata ayıklayıcıyı başlatır.
Uyarı
Cortex-Debug arm-none-eabi-gdb gerektirir. SDK’da ~/openmv-sdk-<version>/gcc/bin konumunda gelir ancak varsayılan olarak PATH üzerinde değildir, bu nedenle hata ayıklama “GDB executable ‘arm-none-eabi-gdb’ was not found” hatasıyla başarısız olur. Bunu ya yukarıda gösterildiği gibi armToolchainPath / gdbPath ayarlayarak ya da PATH ortam değişkeninize ~/openmv-sdk-<version>/gcc/bin ekleyerek düzeltin (printenv PATH o zaman onu listelemelidir).
14.1.1.4.4. Çevre birimi yazmaç görünümü (SVD)¶
Çözümlenmiş bir çevre birimi yazmaç görünümü (zamanlayıcılar, DMA, kamera arabirimi vb.) ada ve bit alanına göre elde etmek için Cortex-Debug’ı bir CMSIS SVD dosyasına yönlendirin:
"svdFile": "/path/to/STM32H743.svd"
STM32 ve MIMXRT için SVD’yi ST / NXP CMSIS paketlerinden veya Cortex-Debug SVD kayıt defterinden alın. Alif SVD’leri, aygıt yazılımı deposunda lib/micropython/lib/alif_ensemble-cmsis-dfp/Debug/SVD/ konumunda dahili olarak yer alır (AE3 HP çekirdeği için ..._CM55_HP_View.svd kullanın).
14.1.1.4.5. Windows: WSL ↔ Windows J-Link köprüsü¶
WSL 2, J-Link’in USB cihazını doğrudan göremez, bu nedenle bölünme şöyledir: Windows probu sunar (takılı olduğu yer) ve VS Code + gdb WSL içinde çalışır ve ona TCP üzerinden erişir.
Windows’ta, Segger J-Link paketini kurun ve J-Link’i bir Windows USB bağlantı noktasına takın.
Windows’ta, J-Link Remote Server‘ı başlatın (J-Link paketiyle birlikte gelir): J-Link takılıyken başlatın ve OK‘a tıklayın. İstendiğinde Windows güvenlik duvarından geçmesine izin verin. Pencere, probu sunduğu IP adresini gösterir – bunu not edin.
WSL’de,
DEBUG=1ile derleyin vearm-none-eabi-gdberişilebilir olduğundan emin olun (yukarıdaki gibiarmToolchainPathayarlayın).WSL VS Code’da,
servertype: "jlink"değerini koruyun – GDB sunucusu WSL’de çalışır ve proba Remote Server aracılığıyla erişir – veserverpath+ipAddressekleyin:{ "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" }
ipAddressdeğerini Remote Server penceresinin gösterdiği adrese ayarlayın. Köprünün tamamı budur.
Tüyo
GDB sunucu köprüsüne alternatif: usbipd-win. Windows’ta bir sunucu çalıştırmak yerine J-Link’in USB cihazını usbipd-win ile doğrudan WSL’ye bağlayabilirsiniz. Yönetici PowerShell’inden:
winget install usbipd
usbipd list
usbipd bind --busid <busid>
usbipd attach --wsl --busid <busid>
(<busid>, usbipd list çıktısındaki J-Link’in veri yolu kimliğidir.) Prob ardından WSL içinde görünür ve VS Code Cortex-Debug setup bölümündeki düz aynı makine servertype: "jlink" yapılandırmasını, IP adresi ve ayrı bir Windows sunucusu olmadan kullanırsınız. GDB sunucu köprüsü ara sıra kullanım için daha az kurulum gerektirir; usbipd-win ise rutin geliştirme için daha kullanışlıdır.
Tüyo
Aygıt yazılımını sıfırlamadan veya yeniden flash’lamadan zaten çalışırken hata ayıklamak için "request": "attach" kullanın – sahada bir takılmayı yakalamak için idealdir. Sıfırlamak, ELF’i flash’lamak ve runToEntryPoint noktasından yeniden başlamak için "request": "launch" kullanın.
14.1.1.4.6. gdbrunner ile komut satırı hata ayıklaması¶
Gömülü bir hedefe karşı bir GDB oturumunu elle kurmak beş adımlı bir danstır: J-Link / ST-Link GDB sunucusunu bir pencerede doğru cihaz, bağlantı noktası ve arabirim bayraklarıyla başlatın; Waiting for GDB connection yazdırmasını bekleyin; ikinci bir pencerede arm-none-eabi-gdb çalıştırın; target remote localhost:<port> yazın; gdb’yi ELF’e yönlendirin. gdb oturumu sona erdiğinde sunucu penceresini kapatmayı unutmayın. gdbrunner, tüm bunları tek bir ön plan komutunda toplayan küçük bir CLI’dir. OpenMV SDK’sının Python ortamında gelir, bu nedenle kurulacak bir şey yoktur; her zamanki giriş noktası aygıt yazılımı deposunun make debug hedefidir:
make -j$(nproc) TARGET=<TARGET> DEBUG=1 debug
Bu, gdbrunner’ı kartın yapılandırmasındaki hata ayıklayıcı argümanlarıyla – J-Link cihaz adı ve gerektiğinde ST-Link harici flash yükleyici – ve SDK’nın arm-none-eabi-gdb aracı zaten PATH üzerindeyken çalıştırır. Varsayılan arka uç J-Link’tir; make DEBUGGER=STLINK debug ise bunun yerine bir ST-Link probuyla çalışır.
gdbrunner doğrudan da çağrılabilir (SDK dışında, 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
İlk konumsal argüman sunucu arka ucunu seçer (jlink, stlink, qemu); geri kalanlar, OpenMV kameraları için çalışan varsayılanlarla birlikte o arka uca iletilir. gdbrunner --help her arka uca özel tam bayrak listesini gösterir; her arka ucun argüman tablosu JSON tabanlıdır (src/gdbrunner/backends.json), bu nedenle yeni bir sunucu eklemek kod değişikliği yerine bir yapılandırma düzenlemesidir.
gdbrunner’ın komut satırı çalışmaları için yaptıkları:
Tek işlem, temiz yaşam döngüsü. Sunucu başlar, bağlantı noktası açıldığında gdb bağlanır, gdb çıktığında sunucu temiz biçimde sonlandırılır. Oturumdan sağ kalan başıboş bir
JLinkGDBServeryok, yönetilecek iki terminal yok.STM32CubeProgrammer otomatik keşfi.
stlinkarka ucu, STM32CubeProgrammer araçları için her zamanki kurulum konumlarını (~/STM32CubeProgrammer/,/opt/st/, STM32CubeIDE eklenti ağacı) arar, böylece uzun--cube-progyolunun her seferinde yazılması gerekmez. SDK,~/openmv-sdk-<version>/stcubeprog/binkonumunda kendi kopyasını paketler – sistemde kurulu bir kopya yoksa--cube-progöğesini buraya yönlendirin.Proje başına gdbinit dikkate alınır. Geçerli dizindeki bir
.gdbinitdosyası-ixile yüklenir – kullanıcı genelindeki~/.gdbinitdosyasını geçersiz kılarak – böylece proje başına gdb betikleme (pretty-printer’lar, karta özgü makrolar, kesme noktası kümeleri) çalışma dizininde bulunarak devreye girer.make debugdepo kökünden çalışır, bu nedenle oradaki bir.gdbinitgeçerli olur.Kuru çalıştırma.
--dryrunsunucu komutunu çalıştırmadan yazdırır; çağrıyı bir sarmalayıcı betiğe uyarlamak, bir IDE başlatıcı yapılandırmasına kopyalamak veya yalnızca gdbrunner’ın hangi argümanları oluşturduğunu kontrol etmek için yararlıdır.Sunucu çıktısı görünür.
--show-outputsunucunun stdout / stderr çıktısını görünür tutar. Varsayılan bunu bastırır (böylece gdb’nin arabirimi temiz kalır); hatalı davranan şeyin sunucunun kendisi olduğu durumlarda bayrağı açın.QEMU arka ucu.
qemu-system-armhiçbir kart takılı olmadan bir aygıt yazılımı derlemesinde hata ayıklar.MPS2_AN500hedefi, kart yapılandırmasında bu arka ucu seçer, böylecemake TARGET=MPS2_AN500 DEBUG=1 debugQEMU’nunmps2-an500makinesi için derleme yapar ve platformdan bağımsız kodda – kameraya özgü çevre birimlerine dokunmayan her şey – adım adım ilerler; uçuş halindeyken. (qemu-system-armbir host kurulumudur, SDK’nın parçası değildir.)
Kesme noktası kenarlıkları ve bir çevre birimi yazmaç görünümüyle kaynak düzeyinde adım adım ilerlemek için yukarıdaki VS Code Cortex-Debug kurulumu daha iyi bir araçtır; gdbrunner ise komut satırında yaşayan her şey için doğru olandır.
14.1.1.4.7. Hata ayıklayıcının kullanımı¶
Bir oturum çalışmaya başladığında (işlemci main işlevinde durdurulmuş halde):
Kesme noktaları – bir C satırının yanındaki kenarlığa tıklayın veya Debug Console’da
break <file>:<line>/break <function>yazın. Cortex-M çekirdeklerinde az sayıda donanımsal kesme noktası karşılaştırıcısı bulunur (genellikle M7 / H7 üzerinde 6–8, M55 üzerinde 8). Flash’taki kod üzerinde bunu aşmak sessizce başarısız olur – etkin kesme noktası sayısını mütevazı tutun.Adım adım ilerleme – F10 üzerinden geç (
next), F11 içine gir (step), Shift+F11 dışarı çık (finish), F5 devam et. Komut düzeyinde adım adım ilerleme Debug Console’dastepi/nextiile yapılır.Değişkenler / izleme / çağrı yığını – Variables ve Call Stack bölmeleri yerel değişkenleri ve geri izlemeyi gösterir; Watch öğesine ifadeler ekleyin. Değerini görmek için kaynaktaki bir değişkenin üzerine gelin.
<optimized out>gösteren her şey, birDEBUG=1derlemesinde olmadığınız anlamına gelir.İzleme noktaları (veri kesme noktaları) –
watch <expr>bir değişkene yazıldığında durur,rwatchokumada,awatchise her ikisinde de durur. Cortex-M DWT birimi ~4 donanımsal izleme noktasını destekler – bir değişkeni kimin bozduğunu yakalamak için paha biçilmezdir.Yazmaçlar ve çevre birimleri – Cortex Registers görünümü çekirdek yazmaçlarını gösterir;
svdFileayarlandığında Peripherals görünümü her çevre birimi yazmacını ve bit alanını çözümler (DMA, zamanlayıcılar, kamera / CSI arabirimi, XSPI vb.) – bir sürücünün neden hatalı davrandığını görmenin en hızlı yolu.Bellek – çerçeve arabelleklerini, DMA arabelleklerini ve yapıları doğrudan incelemek için Cortex-Debug bellek görüntüleyicisini veya gdb
x/komutunu kullanın.Durdurma olmadan printf (SWO/RTT) – zamanlamaya duyarlı sorunlar için Segger RTT veya SWO, hedef çalışırken neredeyse sıfır ek yüklü
printfsağlar.DEBUG_PRINTF=1ile derleyin ve Cortex-Debug’ınrttConfig(RTT) veyaswoConfig(SWO, çekirdek saatine ihtiyaç duyar) yapılandırmasını ekleyin. Bir kesme noktasının gözlemlemeye çalıştığınız zamanlamayı değiştireceği durumlarda doğru araç budur.Bağlantıyı kesme – bir
launchoturumunda Stop hedefi durdurur; birattachoturumunda Disconnect kamerayı çalışır halde bırakır. Daha sonra normal çalışmasına döndürmek için kameranın gücünü kapatıp açın.
14.1.1.4.8. Hata ayıklama tuzakları¶
Optimize edilerek çıkarılmış değişkenler. Her şey
<optimized out>gösteriyor –DEBUG=0ile derlediniz.DEBUG=1ile yeniden derleyin.“GDB executable not found” – SDK
gcc/binPATHüzerinde değil;armToolchainPath/gdbPathayarlayın.“Cannot connect” / yanlış bellek haritası – yanlış veya eksik
deviceadı; tablodaki tam dizeyi kullanın.Kesme noktalarına sessizce ulaşılmıyor – flash’ta yer alan kod üzerinde çok fazla donanımsal kesme noktası var; bunları azaltın.
Kaynak yolları eşleşmiyor (Docker ile derlenmiş ELF) – Docker
build-firmware-devhedefiyle derleyin (kapsayıcının içinde ve dışında aynı mutlak yol) veya gdbset substitute-pathayarlayın.