Tento rychlokurz je součástí série článků o vývoji pro STM8 s OpenSource nástroji. Před použitím GDB je třeba mít nainstalovaný a spuštěný OpenOCD.

Celý toolchain a instalaci najdete v postu Vývoj STM8 s OpenSource nástroji


GDB maskot >>

GDB (GNU Debugger) je standardní nástroj na hledání chyb v software. Pokud budeme chtít program krokovat a za běhu se dívat do proměnných budeme potřebovat právě upravený STM8-GDB z GNU binutils a OpenOCD (Open On Chip Debuger).

Instalace je popsána v kapitole stm8-gdb výše zmíněného článku…

Nenechte se odradit

Ano, je to textové rozhraní, žádná klikátka ani pouťové efekty. Pouze textové příkazy. Toto rozhraní však může být velmi efektivní a díky prográmku [cgdb](#cgdb) i krásně barevné a přehledné.

Spuštění GDB

GDB můžete spustit ve dvou módech:

S TUI (Text User Interface) — přehlednější textové rozhraní s okny pro kód:

1
stm8-gdb --tui build-STM8S208/out-STM8S208.elf

Bez TUI — jednodušší příkazový řádek:

1
stm8-gdb build-STM8S208/out-STM8S208.elf

Samozřejmě nemusíte to vždy znovu vypisovat. Je to napsané v Makefile, takže stačí zavolat:

1
make debug
  • Ctrl+X A — zapne/vypne TUI mód (můžete přepínat kdykoliv)
  • Ctrl+X 2 — rozdělí okno (split layout)
  • Ctrl+L — překreslí obrazovku (užitečné když se rozbije)
  • layout src — zobrazí zdrojový kód
  • layout asm — zobrazí assembler
  • layout split — zobrazí obojí
  • layout regs — přidá zobrazení registrů
  • focus cmd — přepne focus na příkazový řádek
  • focus src — přepne focus na okno se zdrojovým kódem
  • Ctrl+X O — přepíná fokus mezi src, src, asm, atd.

Vizuální markery v TUI:

  • > — aktuální pozice programu (current execution point)

Breakpoint markery (kombinace hit/not-hit a enabled/disabled):

  • B+ — breakpoint byl zasažen (hit) a je aktivní (enabled)
  • B- — breakpoint byl zasažen (hit) a je vypnutý (disabled)
  • b+ — breakpoint nebyl ještě zasažen (not hit) a je aktivní (enabled)
  • b- — breakpoint nebyl ještě zasažen a je vypnutý (disabled)

Hardware breakpointy:

  • H+ / H- — hardware breakpoint hit, enabled/disabled
  • h+ / h- — hardware breakpoint not hit, enabled/disabled

Připojení a spuštění programu

Takže máme dva terminály: v jednom běží OpenOCD a ve druhém běží GDB. Než spustíte GDB, ujistěte se, že OpenOCD již běží.

Po spuštění GDB jednoduše zadejte:

1
(gdb) run

Příkaz run automaticky:

  1. Připojí se k OpenOCD (localhost:3333)
  2. Nahraje program do čipu
  3. Provede reset
  4. Spustí program

… má v sobě tedy ukryto asi toto:

1
2
3
(gdb) target remote localhost:3333
(gdb) load
(gdb) continue &

Základní příkazy GDB

V programu funguje tabulátor. To znamená, že při stisku klávesy TAB se GDB pokusí uhodnout, co chcete napsat a doplní slova tak, aby byla smysluplná.

Pokud zadáte jen Enter — tedy odentrujete prázdný příkaz, zopakuje se ten předchozí. Takže nemusíte pořád psát např. next, ale stačí ho napsat jednou a pek jen Enter.

list main, list main.c:20, list main.c:setup
nalistuje ve zdrojovém kódu příslušné místo, řádek, funkci

Breakpointy

b main, break main
nastaví breakpoint na vstup do funkce main
b 48, break 48
nastaví breakpoint na řádek 48
b milis.c:48, break milis.c:48
nastaví breakpoint na řádek 48 v souboru milis.c
info b, info breakpoints
vypíše informace o breakpointech
d 2, delete 2
vymaže breakpoint 2
disable 2, enable 2
dočasně vypne/zapne breakpoint 2

Ovládání běhu programu

r, run
spustí program (s auto-connect)
c, cont, continue
pokračuje v běhu programu, dokud nenarazí na breakpoint
s, step
vykoná jeden příkaz/řádek zdrojového kódu, vstoupí do funkcí
n, next
vykoná jeden příkaz/řádek zdrojového kódu, funkci vykoná jako jeden příkaz — nebude vstupovat do funkce
fin, finish
dokončí funkci, ve které se program právě nachází (pokud v ní není další breakpoint)
interrupt, Ctrl+C
přeruší program, program se zastaví tam, kde zrovna teď je

Proměnné a paměť

p time, print time
vypíše obsah proměnné time
p/x time, print/x time
vypíše obsah proměnné v hexadecimálním formátu
p *ptr@10
vypíše 10 prvků pole na které ukazuje pointer
p array[0]@10
vypíše 10 prvků pole od indexu 0
p/s string
vypíše řetězec (string)
x/10x array
examine memory — zobrazí 10 hodnot v hexadecimálním formátu od adresy array
x/s string
examine memory jako string (užitečné pro char*)

Formáty výpisu (použijte /formát za příkazem):

  • p/d variable — decimal (desítkově)
  • p/x variable — hexadecimal (šestnáctkově)
  • p/o variable — octal (osmičkově)
  • p/t variable — binary (binárně)
  • p/c variable — character (jako znak)
  • p/s variable — string (jako řetězec)

Display s formáty:

display time
vypíše obsah proměnné time pokaždé, když se program zastaví
display/d time
totéž jako display, ale vynutí desítkový formát
display/x time
zobrazí hodnotu v hexadecimálním formátu při každém zastavení
undisplay 2
už nebude vypisovat display číslo 2, když se program zastaví
info locals
vypíše všechny lokální proměnné
info variables
vypíše všechny globální proměnné

Monitor příkazy (ovládání OpenOCD)

monitor reset halt
resetuje čip a zastaví ho
monitor reset run
resetuje čip a spustí program
monitor halt
zastaví běžící program

Zjištění pozice

where, backtrace, bt
zobrazí call stack s aktuální pozicí (soubor, funkce, řádek)
frame, info frame
zobrazí detailní informace o aktuálním frame (včetně soubor:řádek)
info line
zobrazí přesnou informaci o aktuálním řádku
list
po zastavení programu (Ctrl+C) ukáže kód kolem aktuální pozice
set listsize 20
nastaví počet řádků, které ukáže příkaz list

Pokročilé

load
ručně nahraje program do čipu (obvykle není potřeba, dělá to run)
target remote localhost:3333
ručně se připojí k OpenOCD (obvykle není potřeba, dělá to run)
info sources
vypíše seznam zdrojových souborů
frame 2, f 2
přepne se na frame číslo 2 v call stacku

Watchpointy (zastaví program při změně/čtení proměnné):

Omezení STM8

OpenOCD pro STM8 podporuje pouze watchpointy délky 1 byte. Pro větší datové typy (např. uint16_t, uint32_t) budete muset sledovat jednotlivé byty nebo použít podmínkové breakpointy. Pokud se pokusíte nastavit watchpoint na větší typ, dostanete chybu: Error: Only watchpoints of length 1 are supported

watch variable
zastaví program při zápisu do proměnné (pouze 1 byte!)
rwatch variable
zastaví program při čtení z proměnné (pouze 1 byte!)
awatch variable
zastaví program při čtení i zápisu do proměnné (pouze 1 byte!)

Pokročilé breakpointy:

tbreak main
temporary breakpoint — smaže se automaticky po prvním zastavení
break main.c:42 if x == 5
podmínkový breakpoint — zastaví se jen když je podmínka splněna
condition 1 x > 10
přidá nebo změní podmínku u existujícího breakpointu číslo 1
ignore 1 5
ignoruje breakpoint číslo 1 příštích 5x (pak se aktivuje)

Zde něco málo více k příkazům print a display.

GDB %%

cgdb

cgdb je curses-based rozhraní pro GDB. Práce s ním je o něco málo příjemnějsí a barevnější než když používáte TUI vestavěné přímo v GDB. Domumentaci naleznete na domovské stránce projektu.

Instalace

1
apt install cgdb

Spuštění

Opět je vše zapsáno v Makefile, takže pokud běží openocd stačí zavolat:

1
make cgdb

Případně můžete spustit ručně:

1
cgdb -d stm8-gdb -- out.elf

Ovládání

cgdb je jen nadstavba nad GDB — v dolním okně běží plnohodnotný GDB, takže platí vše, co je popsáno výše: breakpointy, watchpointy, print, display, monitor příkazy i veškerá další syntaxe jsou naprosto stejné.

cgdb má dvě okna: horní zobrazuje zdrojový kód, dolní je klasický GDB terminál. Přepínání mezi nimi funguje takto:

  • Esc — přepne fokus do okna se zdrojovým kódem (vim-like mód)
  • i — vrátí fokus zpět do GDB příkazového řádku

V okně se zdrojovým kódem platí vim klávesy:

  • Space — přidá/odebere breakpoint na aktuálním řádku
  • t — přidá/odebere dočasný (temporary) breakpoint na aktuálním řádku
  • j / k, 🡇 /🡅 — pohyb nahoru/dolů
  • Ctrl+F / Ctrl+B — stránkování dolů/nahoru
  • gg / G — skok na začátek/konec souboru
  • /pattern — hledání, n / N přeskakuje výsledky
  • o — otevře dialog pro výběr souboru

  • Ctrl+W — přepíná horizontální a vertikální layout oken

  • =/-, +/_ — zvětšuje/zmenšuje velikost okna se zdrojovým kódem

Funkční klávesy (fungují z obou oken):

  • F5run
  • F6continue
  • F7finish
  • F8next
  • F10next
  • F11step

Související posty