Jste zde

Ladění programů mikroprocesorů AVR

Mikroprocesory Atmel AVR nemají integrované prostředky pro ladění aplikačních programů, které by umožňovaly pozastavit běh programu na zvolené adrese a kontrolovat nebo modifikovat obsah vnitřní paměti. Tento příspěvek ukazuje jednu z cest, jak tento problém řešit.

Pro základní ladění aplikace se používá simulační program např. Studio AVR, poté se aplikace naprogramuje a ověří se její správná činnost. I v této fázi ladění je žádoucí co největší množství informací o běhu laděného programu, proto se k samotné aplikací připojuje ještě další část programu, monitor, která umožňuje přenést požadované informace do dalšího systému a zde pokud možno komfortně interpretovat. Při programování níže popsaného monitoru pro AVR procesory, který je v rámci GNU licence volně šířitelný, jsem stanovil dva základní požadavky:
 

  1. Zakódování programu provést celé / nebo alespoň podstatnou část / v jazyce C s požitím co nejlevnějšího a zároveň pro kompletní vývoj aplikace použitelného překladače.
  2. Komunikační protokol mezi monitorem a nadřízeným systémem zvolit tak, aby bylo možné použít některý komerční systém určený k monitorování činnosti programu AVR procesoru .
Pro splnění  prvního bodu byl vybrán GCC překladač pro AVR procesory, který je v rámci GNU licence volně dostupný jak ve verzi pro Linux, tak i ve verzi pro Windows.

Druhý bod požadavku je zajištěn implementací komunikačního protokolu, který je součástí souboru programů určených k vývoji aplikací pro Atmel AVR procesory, spojených v integrovaný celek s označením BuilderAVR. Jedna z těchto komponent, DebuggerAVR, umožňuje ovládat monitor, je stručně popsána níže.
 

Princip monitoru

Monitor potřebuje ke své činnosti komunikační kanál, přes který přijímá příkazy a vysílá data, a zdroj aktivování tohoto kanálu.
Jako komunikační kanál byl v základní implementaci použit seriový kanál 19200 Bd, 8bitů bez parity, 1 start, 1 stop bit. Pokud je třeba uvolnit sériový kanál pro komunikaci s jiným systémem v rámci aplikace, je třeba přepracovat komunikační kanál např. tak, že se pro účely ladění rozšíří hardware o další sériový obvod nebo se použijí digitální porty procesoru.
Aktivita komunikačního kanálu je kontrolována přerušením od časovače 0. V rámci tohoto periodického přerušení se zjišťuje přijetí příkazu a pokud je příkaz přijat, v rámci tohoto přerušení se příkaz provede. Důvod použití časovače 0 bude objasněn v odstavci Omezení.
 

Základní funkce

Protože monitor je v podstatě část aplikačního programu, je možné jeho služby libovolně rozšiřovat, pokud jsme ale omezeni paměťovým prostorem, což u mikroprocesorů s velikostí kódové paměti 4 k instrukcí jsme, je nutné zvolit alespoň ty základní. Většina příkazů je ve zdrojových souborech podmíněně přeložitelná, což vede k úspoře kódu monitoru. Monitor poskytuje následující soubor služeb:
  1. Skenování vnitřní paměti mikroprocesoru
  2. Zastavení programu a jeho opětovné spuštění 
  3. Reset 
  4. Modifikaci obsahu paměti ram mikroprocesoru
  5. Plný běh programu do zvoleného místa v programu / UserBreak /
  6. Krokování programu po instrukcích / viz. Omezení
  7. Kontinuální krokování programu až do stanoveného místa / Break /
  8. Příkazem zadat a libovolně  měnit break programu

Protokol

Komunikační protokol je textový. Vstupní / příkazové / pakety mají pevnou délku osm byte. Záhlaví příkazového paketu tvoří řídící znak ‚$‘ a písmeno, poté následuje šest byte parametru. Písmeno určuje typ příkazu.
Obsah parametrů závisí na typu příkazu.
Výstupní pakety mají proměnnou délku, záhlaví tvoří opět kombinace ‚$‘ a písmeno, následuje soubor dat a kombinace CR,LF.
 

Realizace funkcí monitoru

 V rámci přerušení od časovače 0 se testuje přijetí příkazu. Pokud je přijat syntakticky správný příkaz, je proveden a podle typu příkazu mohou být zároveň odeslána požadovaná data, je-li formát příkazu chybný, odesílá se chybový paket. Debugger pracuje s vlastním zásobníkem, jehož velikost určuje uživatel nastavením konstanty nDeepDebuggerStack. Do tohoto zásobníku se na začátku přerušení od časovače 0 uloží obsah všech registrů, nadřízený systém potom zobrazuje tento obsah jako aktuální obsah registrů laděné aplikace.  Protože velikost zásobníku může být potřeba změnit v závislosti na použitém překladači, je aktuální velikost zásobníku odesílána ve výstupním paketu $S. Celá činnost monitoru je řízena proměnnou DebuggerStatus. Jednotlivé bity mají následující význam:
 
  • #define USERBREAK_STATUS  0x10 aplikační program se zastavil na místě makra UserBreak 
  • #define GOTOBREAK_STATUS  0x20 monitor zajišťuje kontinuální krokování instrukce po instrukci až do dosažení nastaveného bodu přerušení
  • #define STEP_STATUS   0x40 monitor zajišťuje krokování po instrukci v rámci základní  úrovně
  • #define ORDER_STATUS  0x80 monitor setrvává ve smyčce v přerušení od časovače 0 až do  přijetí příkazu
1.Skenování pamětí mikroprocesoru. 

V řadě případů je třeba ponechat laděnou aplikaci běžet a průběžně získávat informace o obsahu proměnných. Jsou implementovány dva příkazi pro vyčtení dat paměti ram a jeden příkaz pro vyčtení paměti Eeprom.

  • $Sxxxxxx aktivuje odeslání obsahu celé paměti SRAM
  • $M address aktivuje odeslání 256 byte z externí paměti ram od  zadané adresy
  •  $Fxxxxxx aktivuje odeslání obsahu celé paměti EEPROM
Obsah SRAM se odesílá výstupním paketem s následujícím formátem:
 $S, velikost zásobníku debuggeru, data, kontrolní součet , CRLF

Obsah 256 byte externí ram se odesílá výstupním paketem s následujícím formátem:
 $M, adresa, data, kontrolní součet , CRLF

Obsah EEPROM se odesílá výstupním paketem s následujícím formátem:
 $F, data, CRLF

2.Zastavení programu a jeho opětovné spuštění.

Zastavení programu se realizuje jako smyčka, která je uvolněna příkazem pro další běh programu. Příkaz  $P pozastaví program v přerušovací rutině časovače 0 nastavením bitu ORDER_STATUS proměnné DebuggerStatus. Po přijetí příkazu  $G se smyčka uvolní a program pokračuje.

3. Reset. 

Příkazem $R se realizuje programový reset. To znamená, že se aplikace spustí od adresy 0. Neprovádí se tedy reset hardware s nastavení registrů periferií do výchozího stavu.
 

4. Modifikaci obsahu paměti ram mikroprocesoru.

Příkazem $W adresa data se modifikuje obsah paměti ram mikroprocesoru. Parametr adresa určuje místo v paměti ram, data požadovaný obsah. Při modifikaci paměti ram je třeba brát zřetel na systémové proměnné debuggeru a v nadřízeném systému přijmout taková opatření aby tyto obsahy nebylo možné přepsat.

5. Plný běh programu do zvoleného místa v programu.

Při ladění aplikace lze nalést určitá klíčová místa, kde je třeba ověřit obsah proměnných, přičemž je žádoucí aby až do jejich dosažení běžel program plnou rychlostí. V monitoru je tento požadavek realizován prostřednictvím makra UserBreak. Makro vkládá do aplikačního programu na požadované místo programátor aplikace / nejlépe s podmíněným překladem /. Makro představuje smyčku, ve které program setrvá až do přerušení  od časovače 0, poté informuje nadřízený systém o dosažení bodu UserBreak  odesláním paketu $U, velikost zásobníku debuggeru, data, kontrolní součet, CRLF, kde data jsou obsah paměti SRAM. Nejběžnější použití tohoto makra je na následujícím příkladě:

int main(void)
{
 outp(0xff,DDRA);

 outp(12,UBRR);
 outp(0x98,UCR);

 InitializeAT90InternalDebugger();

// user initialize
 ApplInitialize();

 asm volatile
 (
  "sein"
 ); 

#if DevelopApplUserBreak
 UserBreak;
#endif
 ApplLoop();
}

Program představuje úvodní sekci, ve které se provedou inicializační nastavení, která bývá zpravidla potřeba ověřit. Makro UserBreak  umožňuje pozastavit program před spuštění další části aplikace.
 

6. Krokování programu po instrukcích. 

Krokování programu po instrukcích využívá vlastnosti mikroprocesoru „po návratu z přerušení provést alespoň jednu instrukci v základní úrovni před dalším přerušením“. Do režimu krokování se monitor uvede příkazem $P, následující příkaz $S nastaví status monitoru do režimu STEP_STATUS a uvolní pozastavovací smyčku. V režimu STEP_STATUS se interval časovače nastavuje tak, aby již po instrukci reti bylo přerušení od časovače aktivováno. Po instrukci reti se provede  jedna instrukce v základní úrovni programu a opět se přejde do pozastavovacího režimu.  Poněkud jiné provedení viz. Omezení.
 

7. Kontinuální krokování programu až do stanoveného místa.

Příkazem $I se monitor uvede do stavu GOTOBREAK_STATUS. V tomto režimu mikroprocesor krokuje po jedné instrukci až do doby, kdy se shoduje obsah aktualního čítače programu s některou položkou seznamu BreakPoint.
 

8. Příkazem zadat a libovolně  měnit break programu.

Příkazem $B pořadové číslo adresase zadáva bod přerušení do seznamu BreakPoint. Lze zadat až čtyři body přerušení. Inicializace monitoru  a příkaz $C celý seznam nuluje. 
 

Omezení

Připojení monitoru k aplikaci a používání jeho služeb pro ladění má některá omezení, které je třeba akceptovat. Základní omezení obvodové vyplývající s nutnosti komunikačního kanálu a jeho řízení je zřejmé, obdobně jako velikost paměti RAM, kterou zabírají proměnné monitoru. Paměť kódu monitoru lze omezit podmíněným překladem a používat pouze ty služby, které jsou pro ladění vhodné.

U některých aplikací, které zpracovávají sled rychle se měnících vstupních dat mohou nastat problémy již při prostém skenování běhu programu. Příkaz pro skenování  provede odeslání obsahu vnitřní paměti SRAM mikroprocesoru do komunikačního kanálu. Přenos má určitou časovou režii /závislou na nastavené přenosové rychlosti / a navíc je prováděn v rámci přerušení, další přerušení nebudou tedy po tuto dobu zpracována. 

Pokud je aplikace zabezpečena přes watchdog, je třeba předpokládat, že v režimu krokování programu bude třeba jeho činnost potlačit.

Další základní omezení nastává při krokování programu. Zpracování příkazů monitoru je řízeno přerušením. Obecně lze říci, že priorita tohoto přerušení ovlivní při krokování programu činnost aplikace. Krokování programu provede pouze jednu instrukci na základní úrovni / nulové prioritě / pouze tehdy nebude-li souběžně aktivováno některé přerušení s vyšší prioritou. Pokud bude, bude navíc zpracován celý podprogram zařazený k tomuto přerušení. Naopak všechna přerušení s nižší prioritou zpracována nebudou. Toto omezení je třeba mít na paměti především při používání break podmínky. Pokud je dosažení určitého místa v programu podmíněno zpracováním přerušení s nižší prioritou, pak tohoto místa dosaženo nebude, protože ani přerušení se neprovede.
 

Příklad použití

Součástí tohoto článku jsou zdrojové soubory monitoru. Download obsahuje kromě zdrojových souborů monitoru / debugger.c, debugger.h/, také aplikační soubory main.c a run_appl.c a sestavovací dávku run_appl.bat. Dávka je napsána pro použití překladače pod Windows. Výstupem je k´d programu ve formátu Intel hex, a soubory debugger.obj, debugger.elf, které jsou nutné pokud se jako nadřízený debugger použije DebuggerAVR.
 

Kde nalézt

 Kompilátor GNU C pro AVR mikroprocesory lze stáhnout z internetu. Přímo na stránce Atmel www.atmel.com v sekci avr, spolupracující firmy je odkaz na Linux i Windows verzi.
 

DebuggerAVR

Jak bylo uvedeno již výše, komunikační protokol mezi monitorem a nadřízeným systémem byl zvolen tak, aby bylo možné používat komerční debugger pro AVR s přijatelnou cenou s limitem do 10$ US. Tyto požadavky splňuje DebuggerAVR, / jednodušší, omezená verze pouze pro sériový komunikační kanál /, kde je podporován formát elf, což je výstupní formát gcc-avr. Tento formát obsahuje mimo jiné debugger informace nutné pro zobrazení symbolických proměnných. 
 

Základní vlastnosti:

  1. Pracuje pod Win95, NT
  2. Práce přímo se zdrojovým souborem s možností přepnutí do výpisu assembleru
  3. Obsahuje veškeré příkazy monitoru 
  4. Zobrazení symbolických proměnných aplikace 
Představu o vlastnostech si lze udělat ze skenu obrazovky.
 

DOWNLOAD



Na případné dotazy k funkci nebo objednávky se těším na mém emailu - viz podpis..


 

Sken obrazovky 

Hodnocení článku: