# ATMEL mikrokontrolleri >  attiny2313 programēšana, out of memory

## gget

Sveiki visiem,

Radās tāds neliels jautājums.
Lieta sekojoša.
Ir programma atmelim, rakstīta c++ ar avrstudio un izmantojot winavr kompileri.
ir nodefinētas divas funkcijas.
izsaucu vienu, tad otru. kompilējot aizņem ~ 10% no 2KB, bet kolīdz vēlos vienu funkciju izsaukt vairākas reizes tā uzreiz vajadzīgā atmiņa uzlec uz 4KB, kas attiecīgi ir 200% no atmelim pieejamā.
Kāpēc rodas tāda situācija un kā to risina? Liekas dīvaini, ka nevar izsaukt vienu funkciju vairākas reizes, bet var uzrakstīt, piem, 10 funkcijas un katru izsaukt vienreiz un viss būs ok.

Ar cieņu, gget.

----------


## JDat

1-kārt: Jāraksta AVR forumā!
2-kārt: kodu studijā!

----------


## gget

Piedošanu par 1.
Elektronika tā ir, iesācējs ar esmu, itkā viss sakrita  :: 
2.


```
#define F_CPU 800000UL
#include <avr/io.h>
#include <util/delay.h>

int main()
{


DDRB = 0xFF;
PORTB = 0x00;

void cw(int speed, int count)
{
    for(int i=0; i<count; i++){
        _delay_ms(speed);
        PORTB = 0x10;
        _delay_ms(speed);
        PORTB = 0x40;
        _delay_ms(speed);
        PORTB = 0x20;
        _delay_ms(speed);
        PORTB = 0x80;
    }
}
return 0;
}
```

 ja izsauc tikai cw(10,10), tad programma aizņem ~ 180 byte
ja divreiz izsauc cw(10,10), cw(20,20), tad programma aizņem ~ 4000 byte

----------


## JDat

viss par Atmel kontrolieriem (gan C, gan asm, gan programmešana, gan iešūšana, gan fīčas, gan problēmas). Iesācēju forums domāts tiem kas lodē kopā pirmo LED mikšķinātāju uz diviem tranzistoriem, vai mēģina pieslēgt datoru pie radiotehnikas pastiprinātāja.

es protams nemāku ar C kodēt AVR (esmu ASMists, kas nezin pat C sintaksi, bet kādreiz iemācīšos), bet nu ar manām pieticīgajā C zināšanām izskatās ka ir sekojoša figņa:
main funkcijā iekšā ir cita funkcija. Vai tad nevajadzēja rakstīt skatru funkciju atsevišķi un no main izsaukt tik reizes cik vajag?
Kaut kā tā:


```
#define F_CPU 800000UL
#include <avr/io.h>
#include <util/delay.h>

void cw(int speed, int count)
{
    for(int i=0; i<count; i++){
        _delay_ms(speed);
        PORTB = 0x10;
        _delay_ms(speed);
        PORTB = 0x40;
        _delay_ms(speed);
        PORTB = 0x20;
        _delay_ms(speed);
        PORTB = 0x80;
    }
}

int main()
{
DDRB = 0xFF;
PORTB = 0x00;
return 0;

call cw;   //vai kātur pareizi rakstās
}
```

----------


## habitbraker

> Piedošanu par 1.
> Elektronika tā ir, iesācējs ar esmu, itkā viss sakrita 
> 2.
> 
> 
> ```
> #define F_CPU 800000UL
> #include <avr/io.h>
> #include <util/delay.h>
> ...


 pirmkārt jau funkcijas jāinicializē sākumā.
Otrkārt , kā JDat teica - tev funkcija definēta iekš main(). Vajag ārpus (beigās)
treškārt tu to funkciju nemaz neizsauc.
Izskatās pēc kautkāda LED mirkšķināt'ja, bet nu kods tev nestrādās jau pašā saknē

----------


## JDat

Kā izskatās inicializācija? Ar to domāta kāda rindiņa vai vienkārši init kods pirms main loop?
ir atšķirība sākumā vai beigās? It kā pa ausu galam esmu dzirdējis ka no sākuma vajag funkcijas utt salikt un main beigās likts. It kā kompilatoram tā labāk patīk, bet varbūt es kaut ko jaucu. Varbūt kāds pieredzējis AVR-C zinātājs var pakomentēt...

----------


## gget

Tātad,
Pēc būtības nav starpība kur ir inicializēta funkcija, šo sauc par hiarhiju. Starpība varētu būt tikai ar atmiņas izdalīšanu, bet šā vai tā, tā nav kļūda.

Funkcija nav izsaukta tikai [code.. apgabalā, apakšā es pierakstīju kas un kā.

Un kāpēc kods man nestrādās?

edit: kods domāts stepera darbināšanai

----------


## habitbraker

```
#define F_CPU 800000UL
#include <avr/io.h>
#include <util/delay.h>
void cw(int speed, int count); //sākumā  init

void main() //lieto void nevis int, jo main neatgriež neko
{
DDRB = 0xFF;
PORTB = 0x00;

cw(int speed, int count); //izsauc funkciju argumentu speed un count vietā liekot int skaitļus

return 0;
}
//////////////////////////////////////////////
void cw(int speed, int count) //beigaas pati funkcija
{
    for(int i=0; i<count; i++){
        _delay_ms(speed);
        PORTB = 0x10;
        _delay_ms(speed);
        PORTB = 0x40;
        _delay_ms(speed);
        PORTB = 0x20;
        _delay_ms(speed);
        PORTB = 0x80;
    }
}
```

 Es tā rakstītu. 
Nezinu, varbūt stradā tavs variants. Tu neesi pamēģinājis vismaz nosimulēt?

edit:
AA! Ievērioju ka C++ sākumā pieminēji tikai tagad. Nu es runāju par C

----------


## Vikings

Šitam pats pirms pāris nedēļām izgāju cauri. Problēma ir tajā, ka winavr taisot kodu _delay_ms funkcijas kompilē kā inline, tas ir, katru reizi, kad izsaukta funkcija, kompilators nevis to izsauc, bet ievieto kodā visu funkcijas tekstu.
Nerakstīšu visu koda piemēru, bet, lūk pāris punkti, kurus ievērojot varētu tikt pie cilvēcīga koda izmēra.
1. izveido apakšprogrammu, piemēram, delay_1ms() ārpus main() funkcijas.
2. Noteikti nodefinē šo funkciju arī programmas sākumā, pirms main() sākuma uzrakstot: void delay_1ms(void) __attribute__((noinline));
3. funkciju izsaukumu _delay_ms(speed) aizvieto ar:
for(int i=0;i<speed;i++)
{
delay_1ms();
}

Kas ir panākts? Delay funkcija netiek kompilēta kā inline, bet ir viena apakšprogramma, kas izdara 1ms aizturi un kura tiek ciklēta cik reizes vajag. Nevaru garantēt, ka mans variants izdosies, bet kā saku - pēc līdzīga principa izdevās iekš Tiny13 iespiest programmu, kuru sākumā likās nereāli iespiest. Ziņo par rezultātiem.  ::

----------


## gget

mazliet pats sajaucu, man arī skaitās c, bet šā vai tā c no c++ manuprāt atšķirās tikai ar bibliotēkām. sintakse ir vienāda un tik daudz cik te jāizmanto, tad šeit nav atšķirības.

viss jau kārtībā, man programma strādā, ja izsaucu tikai vienreiz. steperis pa reizei griežas, tikai kaut kāds joks ar frekvencēm, tad viņš ar vienu ātrumu, tad ar citu, nav ne jausmas, varbut atmelim kristāls draņķīgs.

problēma ir ka nevaru to funkciju nodefinēt jo uzreiz vietu pa daudz aizņem, laikam neesmu diezgan optimāli uzrakstījis kodu.

dīvaini jau ir tas, ka es to funkciju varu ar roku iekopēt kaut vai 20 reizes un viss būs ok, nebūs par daudz vietas, bet kolīdz definēju vienreiz un izsaucu vismaz divreiz, tā uzreiz pa daudz.

----------


## Vikings

Ka es saku, man bija līdzīga problēma tieši ar šo pašu delay bibliotēku. Es arī mēģināju taisīt vienu izsaucamu delay funkciju, kurai uzdot aizturi, bet tā arī man aizņēma mežonīgi daudz vietas. Tad nu es izdarīju aptuveni tā kā apstāstīju. Patiesībā, ja tā padomā, Tavs variants tomēr atšķiras no manējā un pilnīgi varētu pietikt ar manis pieminēto 3. punktu.
Ja frekvence ir stipri atšķirīga - tad jāmeklē citas problēmas, diez vai tas ir kvarcs.

----------


## JDat

A nevar uztaisīt ASM kodu no tā visa un apskatīties ASM versijā, kas tur saiet dēlī un izlabot.
Vai arī uzcepts savu ASM funkciju tam delay.
Viens no iemesliem kāpēc nepāreju uz C....

Teorētiski AVR programmētājam tomēr vajadzētu vismaz aptuveni zināt ASM...

----------


## Velko

Problēma tiešām ir dēļ __delay_ms()_ funkcijas. Vienu iemeslu jau Vikings pieminēja - inline.

Tomēr, ir vēl viena (manuprāt daudz lielāka) problēma - aiztures vērtības tips ir *double*. Tas nozīmē, ka iespējams norādīt arī 0.5, 0.1 un tamlīdzīgas floating-point vērtības. Un te nu arī sākas bēdas - AVR nav nekādu iebūvēto instrukciju darbam ar floating-point, tas tiek emulēts kompilējot klāt milzīgu lērumu papildus koda no bibliotēkām.

Autoram iesaku izmantot __delay_loop_2()_ funkciju includojot _util/delay_basic.h_. Šeit gan nāksies pašam drusku parēķināt, kādas vērtības tam __delay_loop_2()_ dot iekšā - katra vienība aizņem 4 clockus. Man slinkums tagad izvest formulu, bet gan jau izdomāsi.

Uz ātro pamēģināju nokompilēt (vienkārši samainot delay funkciju autora kodā) - man sanāca 228 baiti.

P.S. Tiešām biji domājis 800 kHz taktsfrekvenci pie F_CPU, vai aizmirsi dažas nulles no 8 MHz?

----------


## go-men

sveicinati!! vai kads var ieteikt shemu pec kuras var konstruet programmatoru prieks atmel cipiem. uz usb. ka ari uzklausisu citus padomus, kas saistiti ar programesanu. piem ari programma interese. kura labak panak velamo efektu.

----------


## JDat

Jau apspriests, bet nu...
http://www.elfa.lv/forum/viewtopic.php?f=24&t=4875
http://www.elfa.lv/forum/viewtopic.php?f=32&t=4773

Lodē vesels!

----------

