14.1.1.4. Ladění firmwaru¶
Ladění přímo na hardwaru znamená zastavení procesoru, nastavování breakpointů v C kódu, krokování a kontrolu proměnných, paměti, registrů a periferií – to vše z prostředí VS Code. K tomu jsou potřeba tři věci: ladicí build, SWD ladicí sonda (Segger J-Link) a rozšíření Cortex-Debug, které řídí arm-none-eabi-gdb proti J-Link GDB serveru.
14.1.1.4.1. Build pro ladění¶
Vždy znovu sestavte cíl s DEBUG=1
make -j$(nproc) TARGET=<TARGET> DEBUG=1
Release verze (DEBUG=0) se kompiluje s -O2; v ladicím nástroji uvidíte u mnoha proměnných <optimized out>, vložené (inlined) funkce splynou se svými volajícími a krokování skáče nepředvídatelně. DEBUG=1 sestavuje s -Og -ggdb3, což je laditelné a přitom se to na kameře stále nabootuje. ELF, na který ladicí nástroj nasměrujete, je:
build/<TARGET>/bin/firmware.elf
(Pro Alif AE3 laďte build/OPENMV_AE3/bin/firmware_M55_HP.elf – vysoce výkonné jádro.)
14.1.1.4.2. Hardware: J-Link přes SWD¶
Připojte Segger J-Link na piny SWD kamery (SWDIO, SWCLK, GND a referenční target VCC; kamera je napájena přes USB jako obvykle). J-Link EDU / Base / Pro všechny fungují. Kde se ladicí piny vyvádějí, se u jednotlivých kamer liší – mnoho desek má vyhrazený JTAG/SWD konektor, jiné vyvádějí SWD na I/O header nebo na testovací plošky – proto se v dokumentaci hardwaru OpenMV podívejte do schématu zapojení pinů a do schématu dané desky, které piny zapojit. Na počítač, ke kterému je sonda fyzicky připojena, nainstalujte J-Link Software and Documentation Pack ze stránky segger.com. Udržujte jej přiměřeně aktuální – starší software J-Link nezná novější názvy zařízení (STM32N6, MIMXRT, Alif).
Každý MCU potřebuje svůj přesný název zařízení J-Link, aby sonda načetla správný flash loader a mapu paměti:
Kamera ( |
MCU |
J-Link |
|---|---|---|
|
STM32F427 |
|
|
STM32F765 |
|
|
STM32H743 |
|
|
STM32N657 |
|
|
MIMXRT1062 |
|
|
Alif Ensemble (M55-HP) |
|
|
STM32H747 |
|
14.1.1.4.3. Nastavení Cortex-Debug ve VS Code¶
V repozitáři vytvořte .vscode/launch.json. Nejjednodušší případ – VS Code, J-Link i build jsou všechny na stejném stroji s Linuxem / macOS – používá servertype: "jlink", díky čemuž si Cortex-Debug sám spustí 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"
}
]
}
Změňte executable a device podle své desky (viz tabulka výše). Stiskněte F5, čímž se provede build, flash a spuštění až do main, kde se zastaví.
Tip
Aby se build automaticky provedl pokaždé, když spustíte ladění, přidejte build úlohu do .vscode/tasks.json a odkažte se na ni z konfigurace spouštění pomocí "preLaunchTask". Například úloha spouštějící make -j$(nproc) TARGET=OPENMV4 DEBUG=1 pojmenovaná "build-firmware" plus "preLaunchTask": "build-firmware" ve výše uvedené konfiguraci, takže F5 znovu sestaví, naflashuje a spustí ladicí nástroj v jediném kroku.
Varování
Cortex-Debug potřebuje arm-none-eabi-gdb. Dodává se v SDK v ~/openmv-sdk-<version>/gcc/bin, ale ve výchozím nastavení není v PATH, takže ladění selže s hláškou „GDB executable ‚arm-none-eabi-gdb‘ was not found“. Opravíte to buď nastavením armToolchainPath / gdbPath jak je ukázáno výše, nebo přidáním ~/openmv-sdk-<version>/gcc/bin do svého PATH (printenv PATH by jej pak měl vypisovat).
14.1.1.4.4. Zobrazení registrů periferií (SVD)¶
Nasměrujte Cortex-Debug na CMSIS soubor SVD, abyste získali dekódované zobrazení registrů periferií (časovače, DMA, rozhraní kamery atd.) podle názvu a bitového pole:
"svdFile": "/path/to/STM32H743.svd"
Pro STM32 a MIMXRT získáte SVD z CMSIS balíčků ST / NXP nebo z registru SVD pro Cortex-Debug. SVD soubory pro Alif jsou součástí firmware repozitáře v lib/micropython/lib/alif_ensemble-cmsis-dfp/Debug/SVD/ (pro jádro AE3 HP použijte ..._CM55_HP_View.svd).
14.1.1.4.5. Windows: most WSL ↔ Windows pro J-Link¶
WSL 2 nevidí USB zařízení J-Link přímo, takže rozdělení je: Windows obsluhuje sondu (kam je zapojena) a VS Code + gdb běží ve WSL a dosáhnou na ni přes TCP.
Ve Windows nainstalujte balíček Segger J-Link a zapojte J-Link do USB portu Windows.
Ve Windows spusťte J-Link Remote Server (dodává se s balíčkem J-Link): spusťte jej s připojeným J-Linkem a klikněte na OK. Při výzvě jej povolte přes bránu firewall Windows. Okno zobrazí IP adresu, na které sondu obsluhuje – poznamenejte si ji.
Ve WSL sestavte build s
DEBUG=1a ujistěte se, že jearm-none-eabi-gdbdostupný (nastavtearmToolchainPathjak je uvedeno výše).Ve VS Code ve WSL ponechte
servertype: "jlink"– GDB server běží ve WSL a dosáhne na sondu přes Remote Server – a přidejteserverpath+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" }
Nastavte
ipAddressna adresu, kterou zobrazuje okno Remote Server. To je celý most.
Tip
Alternativa k mostu přes GDB server: usbipd-win. Místo spouštění serveru na Windows můžete USB zařízení J-Link připojit přímo do WSL pomocí usbipd-win. Z PowerShellu spuštěného jako administrátor:
winget install usbipd
usbipd list
usbipd bind --busid <busid>
usbipd attach --wsl --busid <busid>
(<busid> je ID sběrnice J-Linku z usbipd list.) Sonda se pak objeví uvnitř WSL a použijete prostou konfiguraci servertype: "jlink" pro stejný stroj z Nastavení Cortex-Debug ve VS Code bez IP adresy a bez samostatného serveru na Windows. Most přes GDB server vyžaduje pro příležitostné použití méně nastavování; usbipd-win je pohodlnější pro běžný vývoj.
Tip
Pomocí "request": "attach" lze ladit firmware tak, jak již běží, bez resetování nebo přeflashování – ideální pro zachycení zaseknutí v terénu. Pomocí "request": "launch" provedete reset, naflashujete ELF a začnete od začátku v runToEntryPoint.
14.1.1.4.6. Ladění z příkazové řádky pomocí gdbrunner¶
Ruční nastavení relace GDB proti vestavěnému cíli je pětikrokový tanec: v jednom okně spustíte J-Link / ST-Link GDB server se správným zařízením, portem a příznaky rozhraní; počkáte, až vypíše Waiting for GDB connection; v druhém okně spustíte arm-none-eabi-gdb; zadáte target remote localhost:<port>; nasměrujete gdb na ELF. Když relace gdb skončí, nezapomeňte ukončit okno serveru. gdbrunner je malé CLI, které tohle všechno sloučí do jediného popředního příkazu. Dodává se v Python prostředí OpenMV SDK, takže není co instalovat; obvyklým vstupním bodem je cíl make debug ve firmware repozitáři:
make -j$(nproc) TARGET=<TARGET> DEBUG=1 debug
Tím se spustí gdbrunner s argumenty ladicího nástroje z konfigurace desky – názvem zařízení J-Link a, kde je to potřeba, externím flash loaderem ST-Link – přičemž arm-none-eabi-gdb z SDK je již v PATH. Výchozím backendem je J-Link; make DEBUGGER=STLINK debug funguje místo toho se sondou ST-Link.
gdbrunner lze také vyvolat přímo (mimo 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
První poziční argument vybírá backend serveru (jlink, stlink, qemu); zbytek se předává tomuto backendu s výchozími hodnotami, které fungují pro kamery OpenMV. gdbrunner --help vypíše úplný seznam příznaků pro jednotlivé backendy; tabulka argumentů každého backendu je řízena JSONem (src/gdbrunner/backends.json), takže přidání nového serveru je úprava konfigurace, nikoli kódu.
Co gdbrunner dělá pro práci z příkazové řádky:
Jeden proces, čistý životní cyklus. Server se spustí, gdb se připojí, jakmile je port otevřený, server se po ukončení gdb čistě ukončí. Žádný osiřelý
JLinkGDBServerpřežívající relaci, žádné dva terminály ke spravování.Automatické vyhledání STM32CubeProgrammer. Backend
stlinkprohledá obvyklá instalační umístění (~/STM32CubeProgrammer/,/opt/st/, strom pluginů STM32CubeIDE) a najde nástroje STM32CubeProgrammer, takže se dlouhá cesta--cube-prognemusí psát pokaždé. SDK přibaluje vlastní kopii v~/openmv-sdk-<version>/stcubeprog/bin– nasměrujte--cube-progsem, pokud žádná systémová instalace neexistuje.Respektování gdbinit pro jednotlivé projekty. Soubor
.gdbinitv aktuálním adresáři se načte pomocí-ix– přebíjí celouživatelský~/.gdbinit– takže gdb skriptování pro daný projekt (pretty-printery, makra specifická pro desku, sady breakpointů) se zapojí jen tím, že je přítomno v pracovním adresáři.make debugběží z kořene repozitáře, takže se uplatní tamní.gdbinit.Suchý běh.
--dryrunvypíše příkaz serveru, aniž by jej spustil, což je užitečné pro přizpůsobení volání obalovacímu skriptu, zkopírování do konfigurace spouštěče v IDE nebo prostě pro kontrolu, jaké argumenty gdbrunner skládá.Viditelný výstup serveru.
--show-outputponechá stdout / stderr serveru viditelný. Výchozí nastavení jej potlačuje (aby zůstalo UI gdb čisté); přepněte tento příznak, když je problémem samotný server.QEMU backend.
qemu-system-armladí firmware build bez připojené desky. CílMPS2_AN500ve své konfiguraci desky volí tento backend, takžemake TARGET=MPS2_AN500 DEBUG=1 debugsestaví pro QEMU strojmps2-an500a krokuje kód nezávislý na platformě – vše, co se nedotýká periferií specifických pro kameru – za letu. (qemu-system-armje instalace na hostiteli, není součástí SDK.)
Pro krokování na úrovni zdrojového kódu s vyznačením breakpointů na okraji a se zobrazením registrů periferií je lepším nástrojem výše popsané nastavení Cortex-Debug ve VS Code; gdbrunner je ten správný pro vše, co žije na příkazové řádce.
14.1.1.4.7. Použití ladicího nástroje¶
Jakmile relace běží (procesor zastavený na main):
Breakpointy – klikněte na okraj vedle řádku v C, nebo v Debug Console
break <file>:<line>/break <function>. Jádra Cortex-M mají malý počet hardwarových komparátorů breakpointů (typicky 6–8 na M7 / H7, 8 na M55). Jejich překročení u kódu ve flash paměti tiše selže – udržujte počet aktivních breakpointů střídmý.Krokování – F10 přeskočit (
next), F11 vstoupit do (step), Shift+F11 vystoupit z (finish), F5 pokračovat. Krokování na úrovni instrukcí jestepi/nextiv Debug Console.Proměnné / watch / zásobník volání – panely Variables a Call Stack zobrazují lokální proměnné a backtrace; výrazy přidejte do Watch. Najetím na proměnnou ve zdrojovém kódu zobrazíte její hodnotu. Cokoli, co zobrazuje
<optimized out>, znamená, že nejste na builduDEBUG=1.Watchpointy (datové breakpointy) –
watch <expr>zastaví při zápisu do proměnné,rwatchpři čtení,awatchpři obojím. Jednotka DWT v Cortex-M podporuje ~4 hardwarové watchpointy – neocenitelné pro zachycení toho, kdo proměnnou poškodil.Registry a periferie – zobrazení Cortex Registers ukazuje jádrové registry; s nastaveným
svdFilezobrazení Peripherals dekóduje každý registr a bitové pole periferie (DMA, časovače, rozhraní kamery / CSI, XSPI atd.) – nejrychlejší způsob, jak zjistit, proč se ovladač chová špatně.Paměť – pomocí prohlížeče paměti Cortex-Debug nebo gdb
x/zkoumejte přímo snímkové buffery (frame buffers), DMA buffery a struktury.printf bez zastavení (SWO/RTT) – pro problémy citlivé na časování poskytuje Segger RTT nebo SWO
printfs téměř nulovou režií, zatímco cíl běží. Sestavte sDEBUG_PRINTF=1a přidejterttConfig(RTT) neboswoConfig(SWO, potřebuje hodiny jádra) z Cortex-Debug. Toto je správný nástroj, když by breakpoint změnil časování, které se snažíte pozorovat.Odpojení – Stop v relaci
launchzastaví cíl; Disconnect v relaciattachnechá kameru běžet. Poté kameru vypněte a zapněte, abyste ji vrátili do normálního provozu.
14.1.1.4.8. Úskalí ladění¶
Optimalizací odstraněné proměnné. Vše zobrazuje
<optimized out>– sestavili jsteDEBUG=0. Sestavte znovu sDEBUG=1.„GDB executable not found“ –
gcc/binz SDK není vPATH; nastavtearmToolchainPath/gdbPath.„Cannot connect“ / chybná mapa paměti – chybný nebo chybějící název
device; použijte přesný řetězec z tabulky.Breakpointy tiše nezasáhnou – příliš mnoho hardwarových breakpointů na kódu rezidentním ve flash paměti; snižte jejich počet.
Cesty ke zdrojům nesouhlasí (ELF sestavený v Dockeru) – sestavte s cílem
build-firmware-devv Dockeru (stejná absolutní cesta uvnitř i vně kontejneru) nebo nastavte gdbset substitute-path.