Kontrola zásobníku v Atmel Studiu
Moderátor: Moderátoři
Kontrola zásobníku v Atmel Studiu
Dělám jednu aplikaci v Atmel Studiu 6 a mám podeření, že jsem neuhlídal zásobník a ten mě převálcoval část datové oblasti. V projektech, které jsem dosud dělal jsem velikostí RAM neměl problémy, tak jsem to zatím nemusel řešit. Je nějaká metoda, jak omezit velikost zásobníku, nebo alespoň monitorovat maximální hodnotu zásobníku?
Díky Jirka
Díky Jirka
Jirka
Existuje na to nástroj Stack Checker
Většinou stačí když globální proměnné nezabírají víc než cca 70% RAM a nepoužívat (velká) lokální pole.
Monitorovat zásobník jde např. tak, že oblast RAM, která nás zajímá, vyplníme nějakou hodnotou, třeba 'A' a pak můžeme sledovat rozsah stacku při běhu programu, např. v simulátoru nebo výpisem RAM na terminál.
Monitorovat zásobník jde např. tak, že oblast RAM, která nás zajímá, vyplníme nějakou hodnotou, třeba 'A' a pak můžeme sledovat rozsah stacku při běhu programu, např. v simulátoru nebo výpisem RAM na terminál.
Tak tohle bohužel není můj případ. Mě proměnné zabírají cca 85% RAM a mám tam i velké komunikační buffery. Na nějaké optimalizaci ještě zapracuji, zatím je SW v dost syrovém stavu, nicméně kontrola by nebyla od věci.AB1 píše:Většinou stačí když globální proměnné nezabírají víc než cca 70% RAM a nepoužívat (velká) lokální pole.
Honzo mnohokrát děkuji. Já jsem nabyl dojmu, že je to pro procesory od AVR nahoru. Tím každopádně začnu.FHonza píše:Vyzkoušel sem nástroj s ATTiny2313 a funguje. Není to všemocné, ale pro první nástřel docela dobrý.
Jirka
Tak děkuji všem za rady.
Nakonec se prokázalo že zásobník nepřetéká. Problém způsobuje pole konstatnt, které jsou uložené v RAM a které se z mě neznámého důvodu přepíšou. Já nyní začnu zkoumat všechna místa v programu, kde používám nepřímé adresování. Napadlo mě ale jestli to nemůže způsobovat optimalizace v překladači.
pole mám deklarované následovně:
volatile char pole1[50] = {k0,k1 .. K49};
Ten Stack Checker se mě nepovedlo rozpohybovat. Povedlo se mě vložit kód, přeložit, nahrát do MCU ale když jsem to spustil, tak hned na 1. programové instrukci mě to hlásilo 100% paměti pro zásobník 1024/1024. A ať jsem to stopnul v jakémkoli bodě, nikdy jsem neviděl jinou hodnotu.
Nicméně to vypadá jako dobrý pomocník, tak to zkusím ještě v jném projektu.
Nakonec se prokázalo že zásobník nepřetéká. Problém způsobuje pole konstatnt, které jsou uložené v RAM a které se z mě neznámého důvodu přepíšou. Já nyní začnu zkoumat všechna místa v programu, kde používám nepřímé adresování. Napadlo mě ale jestli to nemůže způsobovat optimalizace v překladači.
pole mám deklarované následovně:
volatile char pole1[50] = {k0,k1 .. K49};
Ten Stack Checker se mě nepovedlo rozpohybovat. Povedlo se mě vložit kód, přeložit, nahrát do MCU ale když jsem to spustil, tak hned na 1. programové instrukci mě to hlásilo 100% paměti pro zásobník 1024/1024. A ať jsem to stopnul v jakémkoli bodě, nikdy jsem neviděl jinou hodnotu.
Nicméně to vypadá jako dobrý pomocník, tak to zkusím ještě v jném projektu.
Jirka
Dokonce to je velmi neefektivní, protože ty konstanty musí někde ve FLASH být. Takže
způsobí jednak že ty konstanty budou za běhu přítomny 2x a za druhé dodatečný kód pro překopírování konstant z FLASH do RAM.
Kromě toho postrádám smysl pole konstant v RAM.
Kód: Vybrat vše
volatile char pole1[50] = {k0,k1 .. K49};
Kromě toho postrádám smysl pole konstant v RAM.
Děkuji za připomínky matjovsky i AB1. Důvod je jednoduchý. Nevím, jak nadeklarovat pole konstatnt do Flash a následně, jak se na toto pole odkazovat v programu. V materiálech, které jsem přečetl jsem to buď nenašel nebo to nefungovalo.
Nicméně mám pocit, že způsob deklarace problém nevyřeší. Zdá se, že se mě část paměti dat nekontrolovaně přepisuje. Když na tomto místě nebudou konstanty ale jiná data, dojde s největší pravděpodobností rovněž k přepisu a bude zlobit jiná část programu.
Pokud je to jednoduché, napište mě sem deklaraci konstanty do Flash a referenci na ni v programu. Případně odkaz na něco, kde se to dočtu.
Teď při psaní odpovědi jsem si uvedomil, že vlastně již deklaraci jednoduchých konstant používám. Pomocí direktivy #define deklaruji jednoduché konstanty, nezkoušel jsem to zobecnit pro pole konstant.
Díky za odpověď.
Nicméně mám pocit, že způsob deklarace problém nevyřeší. Zdá se, že se mě část paměti dat nekontrolovaně přepisuje. Když na tomto místě nebudou konstanty ale jiná data, dojde s největší pravděpodobností rovněž k přepisu a bude zlobit jiná část programu.
Pokud je to jednoduché, napište mě sem deklaraci konstanty do Flash a referenci na ni v programu. Případně odkaz na něco, kde se to dočtu.
Teď při psaní odpovědi jsem si uvedomil, že vlastně již deklaraci jednoduchých konstant používám. Pomocí direktivy #define deklaruji jednoduché konstanty, nezkoušel jsem to zobecnit pro pole konstant.
Díky za odpověď.
Jirka
Při použití WinAVR.
Definice 5 konstant v programové paměti:
Modifikátor PROGMEM říká, že konstanty jsou umístěny do programové paměti.
Přístup na konstanty:
Funkce pgm_read_byte() má jako parametr adresu do programové paměti. takže screen_len je adresa prvního prvku pole, status je index do pole.
Příklad pro řetězcové konstanty pro zobrazení obsahu LCD displeje pro různé stavy programu. Vše řešeno přes pointery vypočítané při kompilaci a umístěné do programové paměti:
Přístup na řetězce přes pointery pro zobrazení na LCD:
Celé je to popsáno v dokumentaci k WinAVR.
Definice 5 konstant v programové paměti:
Kód: Vybrat vše
#include <avr/pgmspace.h>
. . .
static u08 screen_len[] PROGMEM = {4, 3, 4, 5, 4};
Přístup na konstanty:
Kód: Vybrat vše
u08 table_len = pgm_read_byte(screen_len + status);
Příklad pro řetězcové konstanty pro zobrazení obsahu LCD displeje pro různé stavy programu. Vše řešeno přes pointery vypočítané při kompilaci a umístěné do programové paměti:
Kód: Vybrat vše
static char welcome_text1[] PROGMEM = "\7\0MT9851";
static char welcome_text2[] PROGMEM = "\2\1SWEEP GENERATOR";
static char welcome_text3[] PROGMEM = "\6\2""0-50 MHz";
static char welcome_text4[] PROGMEM = "\0\3Welcome to machine!!";
static char cf_heading[] PROGMEM = "\1\0CONSTANT FREQUENCY\2";
static char am_heading[] PROGMEM = "\1\0\3AMPLTD MODULATION\2";
static char swp_heading[] PROGMEM = "\1\0\3SWEEP GENERATOR\2";
static char af_heading[] PROGMEM = "\1\0\3ACOUSTIC FRQ.SWEEP";
static char fmod_value[] PROGMEM = "\1\2Fmod: . Hz";
static char frq_value[] PROGMEM = "\1\1Freq: . . Hz";
static char af_value[] PROGMEM = "\1\1Freq:10-100.000 Hz";
static char mrk_value[] PROGMEM = "\1\2Mark: . . Hz";
static char v_out[] PROGMEM = "\1\3Vout: mV";
static char swp_value[] PROGMEM = "\15\3\6f: %";
// --------------- screens for individual status ----------
static prog_char* welcome_screen[] PROGMEM =
{
welcome_text1,
welcome_text2,
welcome_text3,
welcome_text4
};
static prog_char* cf_screen[] PROGMEM =
{
cf_heading,
frq_value,
v_out
};
static prog_char* am_screen[] PROGMEM =
{
am_heading,
frq_value,
fmod_value,
v_out
};
static prog_char* swp_screen[] PROGMEM =
{
swp_heading,
frq_value,
mrk_value,
v_out,
swp_value
};
static prog_char* afsw_screen[] PROGMEM =
{
af_heading,
af_value,
mrk_value,
v_out
};
// ------------------ all screens array -------------------
static prog_char** screens[] PROGMEM =
{
welcome_screen,
cf_screen,
am_screen,
swp_screen,
afsw_screen
};
Kód: Vybrat vše
// ---------------- displayScreen -------------------------
// Function displays screen according to given state.
void displayScreen(CCP_STATUS status)
{
LCD_clear(); // erase old screen content
prog_char** screen = (prog_char**)pgm_read_word(screens + status); // load screen table addres
u08 table_len = pgm_read_byte(screen_len + status); // load screen table length
for(u08 i = 0; i < table_len; ++i) // for all strings in table
{
prog_char* string = (prog_char*)pgm_read_word(screen + i); // load string from table
LCD_putstrxy_P(string); // put string to LCD
}
}
Příklad pana Tajovského je dobrý, ale zdá se být trochu starý.
Novější verze překladače by s ním mohly mít problém.
Viz např. http://www.tuxgraphics.org/electronics/ ... char.shtml
Psal jsem kdysi nějaké výukové texty, tak kousek přikládám.
Jsou to jenom jednoduché operace, pokud možno bez hvězdiček, s kterými mají začátečníci problémy.
Novější verze překladače by s ním mohly mít problém.
Viz např. http://www.tuxgraphics.org/electronics/ ... char.shtml
Psal jsem kdysi nějaké výukové texty, tak kousek přikládám.
Jsou to jenom jednoduché operace, pokud možno bez hvězdiček, s kterými mají začátečníci problémy.
- Přílohy
-
- progmem.zip
- (1.25 KiB) Staženo 62 x