Debugování
Debugování znamená, že program jen nenahrajeme do čipu a nehádáme, co se uvnitř děje. Debugger umí běžící program zastavit, krokovat po řádcích, koukat na hodnoty proměnných a prohlížet registry periferií.
U ATtiny je důležité vědět jednu věc:
novější ATtiny, jako třeba ATtiny1626,
používají pro programování i debugování rozhraní
UPDI.
Je to jedna společná datová linka.
Žádný JTAG konektor s hromadou pinů,
žádné SWD jako u ARM čipů.
Jeden pin.
Malý čip,
malá brána dovnitř.
UPDI adaptér není vždy debugger
V kapitole Překlad a nahrávání
jsme používali jednoduchou UPDI linku z USB-UART převodníku
a nástroj pymcuprog.
To je skvělé na nahrávání programu.
Na skutečné interaktivní debugování to ale typicky nestačí.
USB-UART adaptér se umí domluvit s čipem tak,
aby mu nahrál .hex,
ale neumí pohodlně zastavit procesor na konkrétním řádku
a ukazovat hodnoty proměnných v živém programu.
Na to se používá opravdový hardwarový debugger,
třeba Atmel-ICE,
MPLAB Snap,
MPLAB PICkit 5
nebo jiný Microchip nástroj,
který podporuje debugování AVR přes UPDI.
Programátor umí hlavně nahrát program do paměti. Debugger umí program i řídit: zastavit ho, pustit dál, krokovat, číst paměť, sledovat proměnné a dívat se do registrů.
Některá zařízení umí obojí. Jednoduchý USB-UART UPDI adaptér je ale hlavně programátor.
Zapojení pro debugování
Pro debugování přes UPDI se obvykle připojují jen základní signály:
UPDI je datová linka.
GND musí být společná zem.
VTG, někdy označené jako target voltage,
říká debuggeru,
jakým napětím je napájený cílový čip.
Některé debugery umí cílový čip i napájet,
ale není dobré na to spoléhat bez přečtení manuálu konkrétního nástroje.
Debugger musí pracovat se stejnou logickou úrovní,
jakou používá ATtiny.
Když je ATtiny napájený z 3.3 V,
debugger nesmí tlačit na UPDI pin 5 V logiku.
Co debugger umí
Při debugování ATtiny přes UPDI se typicky používají tyto funkce:
| funkce | co znamená |
|---|---|
| breakpoint | program se zastaví na vybraném místě |
| run / continue | program se po zastavení znovu rozběhne |
| step over | provede se další řádek programu |
| step into | vstoupí se dovnitř volané funkce |
| watch | sleduje se hodnota proměnné |
| registers | prohlíží se pracovní registry procesoru |
| I/O view | prohlíží se registry periferií, třeba PORTA.DIR |
| memory view | čte se obsah paměti |
To je velmi užitečné u chyb, které se v kódu špatně hledají jen očima. Například když LED nebliká, debuggerem se dá ověřit:
- jestli program vůbec doběhne do správné funkce,
- jestli má proměnná očekávanou hodnotu,
- jestli je pin nastavený jako výstup,
- jestli se opravdu mění registr portu.
Jak vypadá typický postup
Nejčastější postup je:
- Program se přeloží s ladicími informacemi.
- Výsledný
.elfsoubor se nahraje do čipu. - Debugger zastaví program na začátku funkce
main. - Nastaví se breakpoint na zajímavé místo.
- Program se pustí.
- Po zastavení se prohlédnou proměnné a registry.
Ladicí informace vzniknou typicky přepínačem -g.
Pro debugování je také lepší nepoužívat příliš agresivní optimalizace.
Když kompilátor s optimalizací kus kódu přeskládá nebo úplně odstraní,
debugger pak může ukazovat řádky trochu překvapivě.
Pro první pokusy je rozumné něco jako:
target_compile_options(attiny_blink PRIVATE
-g
-Og
)
-g přidá ladicí informace.
-Og zapne optimalizace,
které se ještě snaží zachovat rozumné debugování.
Debugování přes sériovou linku
Poměrně standardní způsob debugování embedded programů je obyčejná sériová linka. Program si průběžně posílá ven krátké zprávy a člověk je čte v terminálu na počítači.
Není to tak pohodlné jako breakpointy, ale má to jednu velkou výhodu: program běží dál normální rychlostí. Když ladíte problém, který závisí na čase, zastavení procesoru breakpointem může chybu úplně schovat. Sériová linka program nezastaví, jen z něj vytáhne informace ven.
Typicky se posílají třeba:
- aktuální stav programu,
- naměřená hodnota,
- číslo větve, do které program vstoupil,
- chybový kód,
- jednoduchá zpráva typu
start,button,timeout.
V C může taková myšlenka vypadat zhruba takto:
uart_print("start\n");
if (tlacitko_stisknuto) {
uart_print("tlacitko\n");
led_zapni();
}
Na počítači pak běží terminál, například:
picocom -b 115200 /dev/ttyUSB0
nebo:
screen /dev/ttyUSB0 115200
UPDI se používá pro nahrávání a on-chip debugování.
Sériová linka pro výpisy z programu je běžný USART/UART v aplikaci.
Jsou to dvě různé věci. Mohou vést přes podobný USB-UART převodník, ale v programu i v zapojení mají jinou roli.
Sériové ladění je trochu staromódní,
ale pořád velmi užitečné.
Když program napíše,
že je ve stavu CEKAM_NA_TLACITKO,
hned víme víc než když máme tichý čip,
který jen odmítá blikat s LED.
Co od UPDI debugování nemůžeme čekat
UPDI debugování je velmi užitečné, ale není kouzelné okno do všeho. Je dobré počítat s několika omezeními:
- ATtiny má málo prostředků, takže počet breakpointů může být omezený.
- Když je procesor zastavený, program neběží a čas v programu se tím rozbije.
- Některé periferie mohou při zastavení běžet dál nebo se chovat jinak, než čekáte.
- Velmi rychlé děje se přes krokování hledají špatně.
- Optimalizovaný kód nemusí přesně odpovídat řádkům v C.
- UPDI pin se při debugování používá pro debugger, ne jako obyčejný GPIO.
Když se chyba týká přesného časování, třeba komunikace po UARTu nebo generování signálu, je debugger jen část odpovědi. Často je potřeba přidat i měření osciloskopem, logickým analyzátorem nebo si do programu dočasně vyvést stav na LED nebo na pin.
Breakpoint není pauza světa
Breakpoint zastaví jádro procesoru. To ale neznamená, že se celý fyzický svět zastaví s ním.
Napětí na pinu zůstane takové, jaké bylo. Externí součástky běží dál. Tlačítko může být mezitím puštěné. Motor se může pořád točit, pokud ho drží zapnutý výstup.
Proto je debugování embedded programů trochu jiné než debugování webu nebo běžného programu na počítači. Zastavený program je užitečný, ale skutečný obvod kolem něj žije dál.
Když debugger nejde připojit
Když debugger čip nevidí, zkontrolujte hlavně, jestli:
- ATtiny je napájený,
GNDdebuggeru a čipu je propojené,UPDIvede na správný pin,- v nástroji je vybraný správný typ čipu,
- debugger podporuje UPDI pro danou řadu AVR,
- UPDI pin nebyl přenastavený fuse bity tak, že je potřeba vysokonapěťová aktivace.
Microchip má k vysokonapěťové aktivaci UPDI samostatný popis v části
UPDI High-Voltage Activation.
Pro začátek je ale nejlepší se do fuse bitů moc nepouštět.
Nahrát blikání LED je jedna věc.
Zamknout si jediný vstup do čipu je jiná disciplína.