Tento post je součástí série článků o vývoji pro STM8 s OpenSource nástroji. Celý popis toolchainu najdete v postu Vývoj STM8 s OpenSource nástroji
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 upravený STM8-GDB z GNU binutils
Před použitím GDB je třeba mít nainstalovaný a spuštěný Open On Chip Debugger. Tento nástroj zprostředkovává komunikaci mezi GDB a čipem přes debugovací rozhraní — ST-LINK. GDB je tedy nástroj pro ladění (sem zadáváte příkazy, krokujete, prohlížíte proměnné), zatímco OpenOCD zajišťuje fyzickou komunikaci s mikrokontrolérem.
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 i krásně barevné a přehledné.
Instalace¶
Legacy verze¶
Po internetu najdete různé návody na build GDB verze 8.1 ze starších zdrojů. Konkrétně je to projekt stm8-binutils-gdb. Funguje to dobře, ale pokud byste to chtěli použít doporučuji raději naše repo stm8-binutils-gdb-legacy, protože zdrojáky z něj jdou buildnout i dnes i se současným Python 12+.
Obecně bych ale doporučil novější verzi stm8-gdb založenou na GDB v15.0
Novější a hezčí GDB v15.0¶
V současné době je k dispozici výrazně novější verze stm8-gdb založená na GDB 15.0,
která přináší vylepšení oproti staré verzi 8.1: Práce s ním je přehlednější
díky barvičkám a celkově je to prostě novější verze…
Zdrojáky si můžete stáhnout z mého forku na GitLabu:
1 2 3 | |
(Původní fork, který zařadil patche pro GDBv8.1 do aktuálního GDB, raději nepoužívejte protože obsahuje několik chybiček.)
Build je velmi jednoduchý:
1 2 3 4 5 6 7 | |
A opět Stow.
1 2 | |
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 | |
Bez TUI — jednodušší příkazový řádek:
1 | |
Samozřejmě nemusíte to vždy znovu vypisovat. Je to napsané v Makefile, takže stačí zavolat:
1 | |
Je třeba poznamenat, že ještě předtím, než zavoláte make debug musíte v jiném
terminálu zavolat:
1 | |
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 | |
Příkaz run automaticky:
- Připojí se k OpenOCD (localhost:3333)
- Nahraje program do čipu
- Provede reset
- Spustí program
… má v sobě tedy ukryto asi toto:
1 2 3 | |
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á.
Aby ale TAB fungoval musí být focus na frejmu s příkazy a ne na frejmu
se zdrojovým kódem.
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 pak jen Enter.
Text User Interface¶
Několik příkazů a klávesových skratek pro TUI:
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ódlayout asm— zobrazí assemblerlayout split— zobrazí obojílayout regs— přidá zobrazení registrůfocus cmd— přepne focus na příkazový řádekfocus src— přepne focus na okno se zdrojovým kódemCtrl+X O— přepíná fokus mezisrc,cmd,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/disabledh+/h-— hardware breakpoint not hit, enabled/disabled
Navigace ve zdrojovém kódu¶
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é
timepokaž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.

cgdb¶
cgdb je curses-based rozhraní pro GDB. Práce s ním je o něco málo příjemnější a barevnější než když používáte TUI vestavěné přímo v GDB. Dokumentaci naleznete na domovské stránce projektu.
Instalace¶
1 | |
Spuštění¶
Opět je vše zapsáno v Makefile, takže pokud běží openocd stačí zavolat:
1 | |
Případně můžete spustit ručně:
1 | |
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 řádkut— přidá/odebere dočasný (temporary) breakpoint na aktuálním řádkuj/k, 🡇 /🡅 — pohyb nahoru/dolůCtrl+F/Ctrl+B— stránkování dolů/nahorugg/G— skok na začátek/konec souboru/pattern— hledání,n/Npř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):
F5—runF6—continueF7—finishF8—nextF10—nextF11—step