Jak zvětšit návratový zásobník v AVR Studiu?

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
divous
Příspěvky: 164
Registrován: 08 říj 2010, 00:00
Bydliště: ValMez

Jak zvětšit návratový zásobník v AVR Studiu?

#1 Příspěvek od divous »

Zdravím,

Potřeboval bych zvětšit návratový zásobník (STACK) v AVR studiu.
V ASM to umím, ale jak na to v Céčku ?
Uživatelský avatar
mtajovsky
Příspěvky: 3728
Registrován: 19 zář 2007, 00:00
Bydliště: Praha

#2 Příspěvek od mtajovsky »

V avr-libc je to funkce

void* alloca(size_t __size);
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#3 Příspěvek od AB1 »

Potřeboval bych zvětšit návratový zásobník (STACK) v AVR studiu.
V ASM to umím, ale jak na to v Céčku ?
Co tím konkrétně myslíš?
A jak to děláš v asm?
Uživatelský avatar
divous
Příspěvky: 164
Registrován: 08 říj 2010, 00:00
Bydliště: ValMez

#4 Příspěvek od divous »

AB1:

Kód: Vybrat vše

.EQU   SPCNT   =0x10      ;Velikost Stacku

.DSEG
.ORG   RAMEND-SPCNT      ;Na konec paměti
STACK:   .BYTE   SPCNT      ;reservuj paměť pro Stack


V podstatě tím překladači sdělím, že tato paměť je vyhrazena,
takže pokud pak svou blbostí či jinou chybou pokusím sáhnout,
tak mi překladač vyhodí chybu.

matajovsky: Mohl by jsi být podrobnější? Nějaká ukázka by mohla být vhod.
A nevíš náhodou jak zjistím současnou velikost (překladačem definovaného) stacku?
Andrea
Příspěvky: 9340
Registrován: 07 zář 2007, 00:00

#5 Příspěvek od Andrea »

divous píše:V podstatě tím překladači sdělím, že tato paměť je vyhrazena,
takže pokud pak svou blbostí či jinou chybou pokusím sáhnout,
tak mi překladač vyhodí chybu.

Assembler vyhodí chybu, jen když si dáš dvě statické proměnné přes sebe nebo se ti nevejdou do paměti, ale to, kam programem saháš, nekontroluje ani to, jestli ti zásobník nepřetejká a nepřepisuje proměnné.
Proč ten zásobník vlastně chceš zvětšit, když ani nevíš, jak je velký?
Uživatelský avatar
divous
Příspěvky: 164
Registrován: 08 říj 2010, 00:00
Bydliště: ValMez

#6 Příspěvek od divous »

Ano, máš pravdu, ale chybu mi vyhodí i v tomto případě.
Tj. pokud mám takto reservovaný stack a pokusím se jej "překrýt" jinou proměnnou.

Zpět však k tvé otázce proč...

Main() -> funkce1() -> funkce2() -> funkce3() -> funkce4()
Z funkce3 se nevracel do funkce2 ale na náhodné místo v programu.

Problém jsem však již nalezl.
Nebylo to velikostí stacku ani mi do něj přímo nezasahovala nějaká proměnná.
Já (ani původní autor mnou přebraného programu) si neuvědomil,
že parametry funkcí se také uchovávají ve stacku.
No a právě v té funkci3 se měnil (vypočítával) vlastní parametr.
Dál už si jen domýšlím, že během výpočtu pravděpodobně docházelo
k přetečení proměnné a tím zasahoval do návratové adresy.

Jakmile jsem tento zádrhel vyřešil, tak najednou vše funguje bez problémů.
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#7 Příspěvek od AB1 »

Kód: Vybrat vše

.EQU   SPCNT   =0x10      ;Velikost Stacku

.DSEG
.ORG   RAMEND-SPCNT      ;Na konec paměti
STACK:   .BYTE   SPCNT      ;reservuj paměť pro Stack

V podstatě tím překladači sdělím, že tato paměť je vyhrazena,

Tímto postupem jsi rezervoval posledních 16 bajtů v RAM pro proměnnou nazvanou "STACK", která ale s opravdovým stackem nemá nic společného.

Na začátku programu většinou nastavujeme stack_pointer na konec RAM.
Stack se postupně zaplňuje od konce RAM směrem dolů, k nižším adresám. Toto zaplňování není ničím omezené, takže stack má k dispozici celou RAM.
Větší prostor už nemůže mít, takže se nedá nijak "zvětšit".

Ale v RAM jsou také globální proměnné. Ty se naopak ukládají od začátku RAM směrem nahoru, k vyšším adresám. Tyto dvě věci (proměnné a stack) do sebe nesmí narazit, jinak se začnou vzájemně přepisovat.

Není obtížné zjistit velikost oblasti RAM obsazené proměnnými.
Horší je to se stackem. Překladač (Avr-gcc) neví v době překladu kam až může stack při běhu programu zasáhnout. Takže odpovědnost je na programátorovi.

Doporučuje se např. aby globální proměnné nezabíraly víc než asi 70% RAM.
Přednostně používat lokální proměnné.
Funkce, které jsou v kódu použity jen jednou deklarovat jako inline.

Existuje metoda, při které se na úplném začátku programu vyplní celá RAM nějakými znaky, třeba 'A'. Při simulaci pak jsou tyto znaky přepisovány proměnnými a stackem. Sledujeme obsah RAM a vidíme mezeru mezi proměnnými a stackem jako řadu těchto znaků. Pokud stack zasáhne do proměnných, znaky zmizí.
Uživatelský avatar
ZdenekHQ
Významný člen
Příspěvky: 25519
Registrován: 21 črc 2006, 00:00
Bydliště: skoro Brno
Kontaktovat uživatele:

#8 Příspěvek od ZdenekHQ »

Výborná věc je, když má procesor využitý nějaký komunikační port a člověk si může online udělat memory dump...
Pro moje oslovení klidně použijte jméno Zdeněk
Správně navržené zapojení je jako recept na dobré jídlo.
Můžete vynechat půlku ingrediencí, nebo přidat jiné,
ale jste si jistí, že vám to bude chutnat[?
]
Uživatelský avatar
divous
Příspěvky: 164
Registrován: 08 říj 2010, 00:00
Bydliště: ValMez

#9 Příspěvek od divous »

AB1 píše:Tímto postupem jsi rezervoval posledních 16 bajtů v RAM pro proměnnou nazvanou "STACK", která ale s opravdovým stackem nemá nic společného.



Všimni si však, že jsem je rezervoval na konci paměti, tj. přesně tam,
kde se stack nachází.
Samozřejmě tím nezabráním ,aby stack přetekl mimo toto vymezení,
ani to nezabrání aby se mi do této oblasti nezasáhla nějaká dynamická proměnná.
Bude mi však hlásit v případě, když už budu mít zbytek paměti zaplácaný
statickými proměnnýma a pokusím se tam vecpat "ještě jednu navíc".

Ve většině případů to není potřeba,
ale dvakrát či třikrát jsem vyvíjel paměťově náročný program,
a tam mi to bylo docela vhod.
Pro jistotu tuto reservaci paměti pro stack používám pokaždé.
Ničemu to nevadí a může jen pomoci.

A v podstatě něco takového jsem chtěl i v Céčku.
Prostě dát překladači najevo, aby počítal s větším nárokem na stack
a necpal tam statické proměnné.
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#10 Příspěvek od AB1 »

A v podstatě něco takového jsem chtěl i v Céčku.
Prostě dát překladači najevo, aby počítal s větším nárokem na stack
a necpal tam statické proměnné.

Zkusím to jinak:

V AvrStudiu v okně "Build" vidíš po překladu kolik ramky zabírají proměnné.
Celý zbytek RAM může použít stack.

Na obrázku je příklad.
V řádku "Data" vidíme kolik místa zabírají deklarované globální a statické lokální proměnné. Zde 425 bajtů (41.5% RAM).
RAM má 1024 bajtů.
Takže stack může použít 1024-425 = 599 bajtů.
Neboli velikost stacku je 599 bajtů.

Z toho je zřejmé, že zvětšit stack můžeš jen tím, že ubereš proměnných.
Mimochodem, kolik procent zabírají proměnné v tom programu, který měl problémy se stackem?
Přílohy
build.gif
(10.46 KiB) Staženo 108 x
Uživatelský avatar
67kapa
Příspěvky: 73
Registrován: 31 říj 2010, 00:00

Jestli mohu...

#11 Příspěvek od 67kapa »

...v knize C pro mikrokontroléry je to pospáno.Píše se tam o souboru *.xcl v souvislosti se spjovacím programem XLINK pro AVR.Kompilátor jazyka C umísťuje kód a data do segmentů,jimž jsou teprvespojovacím programem(linkerem) XLINK přiřazovány absolutní adresy.Výsledkem je pak spustitelný kód.Soubory spojovacího programu mají koncovku .xcl,ve kterých je mimo jiné uvedeno i rozdělení paměti.A právě tento soubor si můžeš upravit k obrazu svému.Může se to např. hodit,když se pracuje s externím rozšířením paměti.Např. přizpůsobení návratového zásobníku (return stack) o velikosti 0x40 provedeš v tom souboru takto:
-Z(DATA)RSTACK+40=E0-11F
Princip je takový,že než se spustí program C funkcí main,proběhne tzv. startup program(assemblerovský),který je výrobcem kompilátoru dodán do zdrojového textu a objektového kódu.Ten program se jmenuje cstartup.s90.Celé ti to tu nemohu popsat,dávám odkaz na knihu v pdf,můžeš si ji stahnout a tam se dočteš víc,od str.143

http://www.edisk.sk/stahni/82334/C_pro_ ... 9.6MB.html

....klikni na pomalé stažení,ať se nemusíš registrovat:-)...
Uživatelský avatar
divous
Příspěvky: 164
Registrován: 08 říj 2010, 00:00
Bydliště: ValMez

#12 Příspěvek od divous »

Tuto knihu mám, a používám.
Problém je, že tento postup je určen pro IAR, nikoliv pro AVR studio.
Jinak děkuji, problém jsem již vyřešil jiným způsobem.
Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“