14.1.1.4. Felsöka den fasta programvaran¶
Felsökning på hårdvaran innebär att stoppa processorn, sätta brytpunkter i C-källkoden, stega instruktion för instruktion och inspektera variabler, minne, register och kringutrustning – direkt inifrån VS Code. Detta kräver tre saker: en felsökningsbygge, en SWD-felsökningssond (en Segger J-Link) och tillägget Cortex-Debug som driver arm-none-eabi-gdb mot en J-Link GDB-server.
14.1.1.4.1. Bygga för felsökning¶
Bygg alltid om målet med DEBUG=1
make -j$(nproc) TARGET=<TARGET> DEBUG=1
En release-avbild (DEBUG=0) kompileras med -O2; i felsökaren kommer du att se <optimized out> för många variabler, inlinade funktioner kollapsar in i sina anropare och stegningen hoppar omkring oförutsägbart. DEBUG=1 bygger med -Og -ggdb3, vilket är felsökbart samtidigt som det fortfarande startar på kameran. Den ELF du pekar felsökaren mot är:
build/<TARGET>/bin/firmware.elf
(För Alif AE3, felsök build/OPENMV_AE3/bin/firmware_M55_HP.elf – högprestandakärnan.)
14.1.1.4.2. Hårdvaran: J-Link över SWD¶
Anslut en Segger J-Link till kamerans SWD-stift (SWDIO, SWCLK, GND och målets VCC som referens; kameran strömförsörjs via USB som vanligt). En J-Link EDU / Base / Pro fungerar alla. Var felsökningsstiften finns skiljer sig mellan kameror – många kort har en dedikerad JTAG/SWD-kontakt, andra exponerar SWD på I/O-listen eller på testpunkter – så kontrollera kortets stiftdiagram och kopplingsschema i OpenMV:s hårdvarudokumentation för att se vilka stift som ska kopplas. Installera J-Link Software and Documentation Pack från segger.com på den maskin där sonden är fysiskt inkopplad. Håll den någorlunda aktuell – äldre J-Link-programvara känner inte till de nyare enhetsnamnen (STM32N6, MIMXRT, Alif).
Varje MCU behöver sitt exakta J-Link-enhetsnamn så att sonden laddar rätt flash-laddare och minneskarta:
Kamera ( |
MCU |
J-Link |
|---|---|---|
|
STM32F427 |
|
|
STM32F765 |
|
|
STM32H743 |
|
|
STM32N657 |
|
|
MIMXRT1062 |
|
|
Alif Ensemble (M55-HP) |
|
|
STM32H747 |
|
14.1.1.4.3. Konfiguration av VS Code Cortex-Debug¶
Skapa .vscode/launch.json i arkivet. Det enklaste fallet – VS Code, J-Link och bygget finns alla på samma Linux-/macOS-maskin – använder servertype: "jlink", vilket får Cortex-Debug att själv starta en J-Link GDB-server:
{
"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"
}
]
}
Ändra executable och device för ditt kort (se tabellen ovan). Tryck på F5 för att bygga, flasha och köra till main och stoppa där.
Tips
För att bygga om automatiskt varje gång du startar felsökningen, lägg till en byggaktivitet i .vscode/tasks.json och referera till den från startkonfigurationen med "preLaunchTask". Till exempel en aktivitet som kör make -j$(nproc) TARGET=OPENMV4 DEBUG=1, med namnet "build-firmware", plus "preLaunchTask": "build-firmware" i konfigurationen ovan, så att F5 bygger om, flashar och startar felsökaren i ett enda steg.
Varning
Cortex-Debug behöver arm-none-eabi-gdb. Den medföljer i SDK:t i ~/openmv-sdk-<version>/gcc/bin men finns inte på PATH som standard, så felsökningen misslyckas med ”GDB executable ’arm-none-eabi-gdb’ was not found”. Åtgärda det antingen genom att ställa in armToolchainPath / gdbPath som visas ovan, eller genom att lägga till ~/openmv-sdk-<version>/gcc/bin i din PATH (printenv PATH bör då lista den).
14.1.1.4.4. Vy över kringutrustningens register (SVD)¶
Peka Cortex-Debug mot en CMSIS-SVD-fil för att få en avkodad vy över kringutrustningens register (timers, DMA, kameragränssnittet osv.) efter namn och bitfält:
"svdFile": "/path/to/STM32H743.svd"
För STM32 och MIMXRT hämtar du SVD:n från ST:s / NXP:s CMSIS-paket eller från Cortex-Debugs SVD-register. Alif-SVD:erna är inbakade i firmware-arkivet i lib/micropython/lib/alif_ensemble-cmsis-dfp/Debug/SVD/ (använd ..._CM55_HP_View.svd för AE3:s HP-kärna).
14.1.1.4.5. Windows: bryggan WSL ↔ Windows för J-Link¶
WSL 2 kan inte se J-Link:ens USB-enhet direkt, så uppdelningen är: Windows tillhandahåller sonden (där den är inkopplad) och VS Code + gdb körs i WSL och når den över TCP.
I Windows, installera Segger J-Link-paketet och anslut J-Link till en USB-port på Windows.
I Windows, starta J-Link Remote Server (den medföljer J-Link-paketet): starta den med J-Link ansluten och klicka på OK. Tillåt den genom Windows-brandväggen när du tillfrågas. Fönstret visar den IP-adress som den tillhandahåller sonden på – anteckna den.
I WSL, bygg med
DEBUG=1och se till attarm-none-eabi-gdbär nåbar (ställ inarmToolchainPathsom ovan).I WSL VS Code, behåll
servertype: "jlink"– GDB-servern körs i WSL och når sonden via Remote Server – och lägg tillserverpath+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" }
Ställ in
ipAddresstill adressen som Remote Server-fönstret visar. Det är hela bryggan.
Tips
Alternativ till GDB-serverbryggan: usbipd-win. I stället för att köra en server i Windows kan du ansluta J-Link:ens USB-enhet direkt in i WSL med usbipd-win. Från en PowerShell med administratörsbehörighet:
winget install usbipd
usbipd list
usbipd bind --busid <busid>
usbipd attach --wsl --busid <busid>
(<busid> är J-Link:ens buss-ID från usbipd list.) Sonden visas då inuti WSL, och du använder den enkla samma-maskin-konfigurationen servertype: "jlink" från VS Code Cortex-Debug setup utan IP-adress och utan en separat Windows-server. GDB-serverbryggan kräver mindre konfiguration för tillfällig användning; usbipd-win är bekvämare för rutinmässig utveckling.
Tips
Använd "request": "attach" för att felsöka den fasta programvaran medan den redan körs utan att återställa eller flasha om den – idealiskt för att fånga en hängning ute i fält. Använd "request": "launch" för att återställa, flasha ELF:en och starta om från runToEntryPoint.
14.1.1.4.6. Felsökning från kommandoraden med gdbrunner¶
Att sätta upp en GDB-session mot ett inbyggt mål för hand är en dans i fem steg: starta J-Link- / ST-Link-GDB-servern i ett fönster med rätt enhet, port och gränssnittsflaggor; vänta tills den skriver ut Waiting for GDB connection; kör arm-none-eabi-gdb i ett andra fönster; skriv target remote localhost:<port>; peka gdb mot ELF:en. När gdb-sessionen avslutas, kom ihåg att stänga serverfönstret. gdbrunner är ett litet CLI som kollapsar allt detta till ett enda förgrundskommando. Det medföljer i OpenMV-SDK:ts Python-miljö, så det finns inget att installera; den vanliga ingångspunkten är firmware-arkivets make debug-mål:
make -j$(nproc) TARGET=<TARGET> DEBUG=1 debug
Detta kör gdbrunner med felsökningsargumenten från kortets konfiguration – J-Link-enhetsnamnet och, där det behövs, ST-Link:ens externa flash-laddare – med SDK:ts arm-none-eabi-gdb redan på PATH. Standardbackenden är J-Link; make DEBUGGER=STLINK debug fungerar med en ST-Link-sond i stället.
gdbrunner kan även anropas direkt (utanför SDK:t, 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
Det första positionsargumentet väljer serverbackenden (jlink, stlink, qemu); resten vidarebefordras till den backenden, med standardvärden som fungerar för OpenMV-kamerorna. gdbrunner --help listar den fullständiga listan med flaggor per backend; varje backends argumenttabell är JSON-driven (src/gdbrunner/backends.json), så att lägga till en ny server är en konfigurationsändring snarare än kod.
Vad gdbrunner gör för arbete på kommandoraden:
En process, ren livscykel. Servern startar, gdb ansluter när porten är öppen, servern avslutas rent när gdb avslutas. Ingen kvarvarande
JLinkGDBServersom överlever sessionen, inga två terminaler att hantera.Automatisk upptäckt av STM32CubeProgrammer. Backenden
stlinksöker på de vanliga installationsplatserna (~/STM32CubeProgrammer/,/opt/st/, STM32CubeIDE-pluginträdet) efter STM32CubeProgrammer-verktygen, så att den långa--cube-prog-sökvägen inte behöver skrivas varje gång. SDK:t levererar sin egen kopia i~/openmv-sdk-<version>/stcubeprog/bin– peka--cube-progdit om ingen systeminstallation finns.Projektspecifik gdbinit respekteras. En
.gdbiniti den aktuella katalogen laddas med-ix– vilket åsidosätter den användaromfattande~/.gdbinit– så projektspecifika gdb-skript (pretty-printers, kortspecifika makron, brytpunktsuppsättningar) tillkommer bara genom att finnas i arbetskatalogen.make debugkörs från arkivets rot, så en.gdbinitdär gäller.Torrkörning.
--dryrunskriver ut serverkommandot utan att köra det, vilket är användbart för att anpassa anropet till ett omslagsskript, kopiera in det i en IDE-startkonfiguration eller bara kontrollera vilka argument gdbrunner sätter samman.Serverutdata synlig.
--show-outputhåller serverns stdout / stderr synlig. Standardvärdet undertrycker den (så att gdb:s gränssnitt förblir rent); slå om flaggan när det är servern själv som krånglar.QEMU-backend.
qemu-system-armfelsöker ett firmware-bygge utan något inkopplat kort. MåletMPS2_AN500väljer denna backend i sin kortkonfiguration, såmake TARGET=MPS2_AN500 DEBUG=1 debugbygger för QEMU:smps2-an500-maskin och stegar igenom den plattformsoberoende koden – allt som inte rör kameraspecifik kringutrustning – på resande fot. (qemu-system-armär en värdinstallation, inte en del av SDK:t.)
För stegning på källkodsnivå med brytpunktsmarginaler och en vy över kringutrustningens register är konfigurationen av VS Code Cortex-Debug ovan det bättre verktyget; gdbrunner är det rätta för allt som lever på kommandoraden.
14.1.1.4.7. Använda felsökaren¶
När en session väl körs (processorn stoppad vid main):
Brytpunkter – klicka i marginalen bredvid en C-rad, eller i Debug Console
break <file>:<line>/break <function>. Cortex-M-kärnor har ett litet antal hårdvaru-brytpunktskomparatorer (vanligen 6–8 på M7 / H7, 8 på M55). Att överskrida det antalet på kod i flashminne misslyckas tyst – håll antalet aktiva brytpunkter måttligt.Stegning – F10 stega över (
next), F11 stega in i (step), Shift+F11 stega ut (finish), F5 fortsätt. Stegning på instruktionsnivå ärstepi/nextii Debug Console.Variabler / bevakning / anropsstack – panelerna Variables och Call Stack visar lokala variabler och bakåtspårningen; lägg till uttryck i Watch. Hovra över en variabel i källkoden för att se dess värde. Allt som visar
<optimized out>betyder att du inte är på ettDEBUG=1-bygge.Bevakningspunkter (databrytpunkter) –
watch <expr>stoppar när en variabel skrivs,rwatchvid läsning,awatchvid endera. Cortex-M:s DWT-enhet stöder ~4 hårdvarubevakningspunkter – ovärderligt för att fånga vem som korrumperade en variabel.Register och kringutrustning – vyn Cortex Registers visar kärnregister; med
svdFileinställd avkodar vyn Peripherals varje register och bitfält i kringutrustningen (DMA, timers, kamera- / CSI-gränssnittet, XSPI osv.) – det snabbaste sättet att se varför en drivrutin krånglar.Minne – använd Cortex-Debugs minnesvisare eller gdb
x/för att inspektera bildbuffertar, DMA-buffertar och strukturer direkt.printf utan att stoppa (SWO/RTT) – för tidskänsliga problem ger Segger RTT eller SWO nära nog overhead-fri
printfmedan målet körs. Bygg medDEBUG_PRINTF=1och lägg till Cortex-DebugsrttConfig(RTT) ellerswoConfig(SWO, kräver kärnklockan). Detta är rätt verktyg när en brytpunkt skulle ändra den tidsstyrning du försöker observera.Koppla från – Stop på en
launch-session stoppar målet; Disconnect på enattach-session lämnar kameran igång. Strömcykla kameran för att återställa den till normal drift efteråt.
14.1.1.4.8. Fallgropar vid felsökning¶
Bortoptimerade variabler. Allt visar
<optimized out>– du byggdeDEBUG=0. Bygg om medDEBUG=1.”GDB executable not found” – SDK:ts
gcc/binfinns inte påPATH; ställ inarmToolchainPath/gdbPath.”Cannot connect” / fel minneskarta – fel eller saknat
device-namn; använd den exakta strängen från tabellen.Brytpunkter träffas tyst inte – för många hårdvarubrytpunkter på flash-resident kod; minska dem.
Källsökvägar matchar inte (Docker-byggd ELF) – bygg med Docker-målet
build-firmware-dev(samma absoluta sökväg innanför och utanför containern) eller ställ in gdbset substitute-path.