Forum: Mikrocontroller und Digitale Elektronik Zu wenig ram?


von timo91 (Gast)


Lesenswert?

Guten Tag,

Ich habe die Vermutung das mein Programm zu viel ram verschluckt...bin 
mir aber nicht sicher.

Und zwar:
Ich nutze einen Atmega16@16mhz mit dem ich einen tlc5940 ansteuere, was 
durch 2 timer-interrupts funktioniert.

Mit der IRMP-Lib kann ich erfolgreich ein  RC6 signal über uart 
ausgeben, doch nur, solange der timer-interrupt eines tlc-timers (der 
andere toggelt nur einen ausgang) ausgeschaltet ist.
In der config der IRMP-Lib sind 15000 Interrupts / Sekunde eingestellt.
Der TLC5940-Timer führt 1953 Interrupts / Sekunde aus.

 (Wenn ich das richtig berechnet habe, init:)
1
  TCCR2 |= (1<<WGM21)  | (1<<CS21)  | (1<<CS22) | (1<<CS20);
2
  OCR2 = 7;

Kann das am Ram liegen? Könnte ich das mit einem atmega32 ausbügeln?

von 42er (Gast)


Lesenswert?

timo91 schrieb:
> Ich habe die Vermutung das mein Programm zu viel ram verschluckt...bin
> mir aber nicht sicher.

Ja, wieviel schluckt es denn?
Hast du einen Listfile und einen Simulator? Nur du kennst das Programm. 
Was tut dein Programm, wenn es nicht funktioniert?

von Ingo L. (Gast)


Lesenswert?

RAM != Rechenleistung, jedenfalls bei einem uC. 15kHz si d schon ganz 
schön schnell....


Ingo

von timo91 (Gast)


Lesenswert?

Guten morgen,

Danke für die schnellen Antoworten :)

Ich habs jetzt inzwischen soweit bekommen, das fast alles miteinander 
funktioniert, doch wenn ich meine fade-funktionen laufen lasse startet 
der µC immer wieder neu.

Das liegt dann in dem fall doch am RAM oder?

von Cyblord -. (cyblord)


Lesenswert?

timo91 schrieb:
> Das liegt dann in dem fall doch am RAM oder?
Völlig klar, oder am Osterhasen.

Woher sollen wir wissen wieviel dein Programm ram braucht? Wenn du es 
nichtmal weißt.
Nutzt du dynamische allokierung zur Laufzeit? Ansonsten müsstet du ja 
den Ram Bedarf schon zur Compilierzeit sehen.
Bei vielen verschachtelten Interrupts kann dir auch der Stackpointer in 
den Heap laufen. Sollte halt nicht passieren dass sich INTs 
verschachteln, vorallem nicht unkontrolliert. Aber nur du kennst das 
Program, also was willst du?

gruß cyblord

von timo91 (Gast)


Angehängte Dateien:

Lesenswert?

Ok ich habe den kompletten Source-Code jetzt mal angehängt. Falls jemand 
zeit & lust hat sich das mal an zu schauen wäre ich ihm oder auch ihr =D 
sehr dankbar.

Ich weiß der Code ist ziemlich unsauber und man kann noch vieles 
verbessern. Doch das jetzige problem beschränkt sich darauf das jede 
teil funktion funktioniert, nur zusammen nicht.
Und zwar:
In der Schleife der main-function wird Erstens geschaut ob IRMP etwas 
empfangen hat, wenn ja wird der RC6-command mit zwei werten verglichen 
und je nach dem wird eine led dunklet oder heller gestellt.
Am ende der Schleife wird updateFades() aufgerufen um die fades zu 
aktualisieren (ne is klar), doch danach wird updatePrograms() aufgerufen 
um die Fade-Programme (steuerung mit mehreren fades hintereinander usw) 
zu aktualisieren.
Wenn diese beide Funktionen in der main-schleife aufgerufen werden, 
empfängt IRMP aufeinmal nichts mehr. Doch sobald ich entweder 
updatePrograms() oder updateFades auskommentiere funktioniert IRMP 
aufeinmal wieder und empfängt.
Der controller startet auch nicht mehr neu oder so, es funktioniert 
einfach nur nicht wenn diese beide funktionen in der Schleife aufgerufen 
werden.

Falls es am RAM liegen sollte könnte man da noch vieles tun z.B. die 
TLC5940 werte nicht bitweise in 8bit zu speichern..doch ich wollte 
erstmal sicher gehen ob es daran liegt.

Viel dank
timo91

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

1
uint8_t dcData[96 * TLC5940_N] = { ...
2
uint8_t gsData[192 * TLC5940_N] = { ...
Das sind schon mal fast 600 Bytes. Dazu hast du noch ein paar 
Strukturen, die Speicherplatz brauchen und dein uC hat gerade mal 1kB...

> Falls es am RAM liegen sollte könnte man da noch vieles tun
> ..doch ich wollte erstmal sicher gehen ob es daran liegt.
Du kannst einfach im Listing nachsehen, oder an den Meldungen, die der 
Compiler ausspuckt...

von Meisel (Gast)


Lesenswert?

Wobei das aber auch nur der statische RAM ist.

Dazu kommt nochmal der Stack.

Meine Vermutung:
Du kratzt knapp unterhalb der 1kB die der mega16 hat.
Dann rufst du paar verschachtelte Funktionen auf, der Stack wächst in 
den Heap und richtet dort ordentlich Schaden an.
Aber - natürlich nur ne Vermutung...

von timo91 (Gast)


Lesenswert?

So in der Art hab mir ich das auch schon gedacht, denn schon als ich 
IRMP und fade.c miteinander einbinden wollte funktionierte auch erstmal 
überhaupt nichts bis ich den fade-struct array von 16 auf 3 elemente 
herabgesetzt habe.

Hab mir von anfang an gedacht das es keine gute idee ist die bits in nem 
langen uint8 array zu speichern.

Ich werd mich jetzt mal ranmachen und das alles so umschreiben das ich 
durch überarbeiten der Datenspeicherung viel ram spar und werds dann 
nochmal mit IRMP zusammen ausprobieren und berichten.

Vielen Danke für die Infos.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

timo91 schrieb:
> Hab mir von anfang an gedacht das es keine gute idee ist die bits in nem
> langen uint8 array zu speichern.

Ach, das sind nur Bits? Dann kannst Du die Arrays auf ein Achtel (+1) 
herunterschrumpfen.

Mal so hingeschmiert:
1
#define setarraybit(a,x)   a[x/8] |= (1<<(x%8))
2
#define resetarraybit(a,x) a[x/8] &= ~(1<<(x%8))
3
#define getarraybit(a,x)   a[x/8] & (1<<(x%8))

Ist nicht getestet, sollte aber so gehen.

Wenn Du zum Beispiel 123 Bits brauchst, dann definierst Du das Array so:
1
#define MAX_BITS  123
2
uint8_t myarray[MAX_BITS/8 + 1];

Anwendung:
1
   setarraybit(myarray, 23);      // Setze Bit 23 (angefangen bei 0!)
2
   resetarraybit(myarray, 24);    // Setze Bit 24 zurück
3
4
   if (getarraybit(myarray, 23))  // Teste, ob Bit 23 gesetzt
5
   {
6
       irgendwas();               // Bit ist gesetzt!
7
   }

Viel Spaß,

Frank

P.S.
Sei unbesorgt: Der gcc wird die Division durch 8 durch einen 
Schiebebefehl ersetzen. Ebenso wird der Modulo-Operator durch 
entsprechendes Maskieren erledigt. Die obigen Macros sind daher bei 
Optimierung mit -Os nicht sehr CPU-intensiv.

von timo91 (Gast)


Lesenswert?

Der Controller verhält sich wirklich ziemlich komisch.

Ich habe versucht es in kleine varine mit kleineren arrays um zu 
schreiben auch  Frank M.'s idee habe ich versucht. Doch bisher noch 
keinen Erfolg.
Ich konnte jedoch den kleineren der beiden arrays (uint8_t dcData[96 * 
TLC5940_N]) auskommentieren weil es nur optional ist.

Doch zu den problIch em:
Egal ob ich die updateFades() & updatePrograms() nur einmal in der 
endlos-schleife oder nur alle 1, 2 oder 50 mal.
Doch sobald ich eine der beiden funktionen garnicht aufrufe aus 
auskomenntiere funktioniert IRMP wunderbar.

Ideen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

timo91 schrieb:
> Ich habe versucht es in kleine varine mit kleineren arrays um zu
> schreiben
Und, wie sieht die Speicherauslastung jetzt aus?

> Egal ob ich die updateFades() & updatePrograms() nur einmal in der
> endlos-schleife oder nur alle 1, 2 oder 50 mal.
Hast du gesehen: dieser Satz ist noch nicht ganz fertig...

WAS funktioniert dann nicht mehr? WIE stllst du das fest?
Kann es sein, dass die beiden Funktionen zusammen einfach zu lange 
dauern?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Angehängte Dateien:

Lesenswert?

Lass dir doch mal den freien RAM Ausgeben.
Im Anhang mal Code dazu von RN Wissen.

von timo91 (Gast)


Lesenswert?

Lothar Miller schrieb:
> timo91 schrieb:
>> Ich habe versucht es in kleine varine mit kleineren arrays um zu
>> schreiben
> Und, wie sieht die Speicherauslastung jetzt aus?
>

Nachdem der array entfernt wurde spuckt die funktion 214 freie bytes 
aus, was ja eigentlich reichen sollte.

>> Egal ob ich die updateFades() & updatePrograms() nur einmal in der
>> endlos-schleife oder nur alle 1, 2 oder 50 mal.
> Hast du gesehen: dieser Satz ist noch nicht ganz fertig...
>
Srry, :
Egal ob ich die updateFades() und updatePrograms() nur einmal in der
endlos-schleife oder nur nach 1, 2 oder 50 mal aufrufe, IRMP will dann 
nichmehr.


> WAS funktioniert dann nicht mehr? WIE stllst du das fest?
> Kann es sein, dass die beiden Funktionen zusammen einfach zu lange
> dauern?
IRMP, also das empfangen mit einer RC6 fernbedienung.
In der endlos-schleife:
1
    if (irmp_get_data (&irmp_data))
2
        { 
3
      if(irmp_data.command == 16)
4
      {
5
        puts("LAUTER ");
6
        //cli();
7
        //fade_up(24);
8
        //sei();
9
      }
10
      else if(irmp_data.command == 17)
11
      {
12
        puts("LEISER ");
13
        //cli();
14
        //fade_down(24);
15
        //sei();
16
      }

Doch sobald updateFades() und updatePrograms() zusammen in der 
endlos-schleife aufgerufen werden empfang ich kein IR signal mehr.

Viel dank bis hierhin schonmal :)

von timo91 (Gast)


Lesenswert?

Naja ich hab noch weitere dinge ausprobiert:
Anstatt die updateFades() & updatePrograms function hab ich einfach 
versucht wie weit ich mit einem delay in der endlos-schleife hoch gehen 
kann bis IRMP nichts mehr empfängt. Ich habs bis 1ms hochgetestet und 
der IRMP empfang immernoch daten (doch auch nicht mehr ganz sauber).

Ich habe den freien ram mit aufrufen der funktionen ohne ausgeben 
lassen, ca 216bytes frei.

Was ist da los?!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

timo91 schrieb:
> Ich habs bis 1ms hochgetestet und
> der IRMP empfang immernoch daten (doch auch nicht mehr ganz sauber).

Da IRMP die IR-Signale über die Timer1-ISR empfängt, ist das auch nicht 
das Problem. Da kannst Du noch so lange Delays einbauen: zumindest ein 
IR-Kommando empfängt dann IRMP immer noch, das nächste allerdings erst, 
wenn Du das erste auch "abgeholt" hast.

> Ich habe den freien ram mit aufrufen der funktionen ohne ausgeben
> lassen, ca 216bytes frei.

Sollte reichen, wenn Du keine gößeren lokalen(!) Arrays in irgendeiner 
Funktion stecken hast.

> Was ist da los?!

Was macht denn ISR(TIMER2_COMP_vect) so alles? Da gibt es eine 
for(;;)-Schleife drin. Solange diese Schleife läuft, werden natürlich 
keine anderen Interrupts mehr aufgerufen und IRMP könnte dann wegen 
verlorener Interrupts ins Schleudern geraten.

Abhilfe: Setze in Deiner Timer2-ISR lediglich ein volatile-Flag, dass Du 
diese Kopierschleife (oder was es auch sein mag) ausführen musst und 
verlagere die Schleife ins main.

Gruß,

Frank

von timo91 (Gast)


Lesenswert?

Frank M. schrieb:
> timo91 schrieb:
>> Ich habs bis 1ms hochgetestet und
>> der IRMP empfang immernoch daten (doch auch nicht mehr ganz sauber).
>
> Da IRMP die IR-Signale über die Timer1-ISR empfängt, ist das auch nicht
> das Problem. Da kannst Du noch so lange Delays einbauen: zumindest ein
> IR-Kommando empfängt dann IRMP immer noch, das nächste allerdings erst,
> wenn Du das erste auch "abgeholt" hast.
>
  Joa genau das hatte ich auch im Sinn doch mich wunderte wieso es nur 
nicht empfängt wenn die funktionen aufgerufen werden

>> Ich habe den freien ram mit aufrufen der funktionen ohne ausgeben
>> lassen, ca 216bytes frei.
>
> Sollte reichen, wenn Du keine gößeren lokalen(!) Arrays in irgendeiner
> Funktion stecken hast.
>
Nein nicht innerhalb funktionen.
>
>> Was ist da los?!
>
> Was macht denn ISR(TIMER2_COMP_vect) so alles? Da gibt es eine
> for(;;)-Schleife drin. Solange diese Schleife läuft, werden natürlich
> keine anderen Interrupts mehr aufgerufen und IRMP könnte dann wegen
> verlorener Interrupts ins Schleudern geraten.
>
> Abhilfe: Setze in Deiner Timer2-ISR lediglich ein volatile-Flag, dass Du
> diese Kopierschleife (oder was es auch sein mag) ausführen musst und
> verlagere die Schleife ins main.
>
In der ISR2 werden wenn gsUpdate gesetzt ist, bits (für helligkeit 
verschiedener kanäle) an den TLC5940 übertragen.
ich habe ss jetzt mal so laufen lassen das ich in der ISR2 die 
kopier-schleife auskommentiert habe, jedoch in der endlos-schleife der 
main-function beide funktionen (updateFades() und updatePrograms()) drin 
stehen hab...uuund IR-Signale werden aufeinmal empfangen!!

Der kopiertvorgang kann ich leider nicht einfach in die schleife 
schieben da es in bestimmten zeitabständen geschickt werden muss. (ISR2 
löst ca 2000 interrupts/s aus).

Ich habe auch versucht in der ISR1 des IRMP am anfang ein cli() und am 
ende ein sei() zu setzten..doch dies hat leider nichts geholfen.
Deshalb hab ich daran gedacht das ich die ISR1 und ISR2 zusammenfüge.
Die ISR1 des IRMP macht 10 000 Interrupts/s (Ist auf minimale 
einstellung und läuft prima (range ist 10-20k default 15k).
Da aber 10k Interrupts/s für die Kopierfunktion der ISR2 zuviel sind, 
dachte ich daran in der ISR2() sowas zu intigrieren:
1
static uint8_t callISR2 = 0;
2
if(callISR2 >4)
3
{
4
  ISR2();
5
  callISR2 = 0;
6
7
}
8
callISR2++;*/

Das würde die doch die 10 000 Interrupts /5 Teilen ..also auch ca. 2000 
Aufrufe pro sekunde.

Richtig?

Danke leute ihr seid klasse :)

von timo91 (Gast)


Lesenswert?

Ich habe es wie oben beschrieben mal versucht...und es hat nicht 
geklappt. Ich habe den TIMER2 ausgemacht und rufe ISR2 jetzt von der 
ISR1 aus auf. Das Faden usw hat alles funktioniert (also der TLC) aber 
IRMP nicht.
Dann hab ich wie vorgeschlagen die ISR2 in die schleife der 
main-function einzufügen und ...TADA  alles funktioniert schön 
miteinander.

Nur hab ich jetzt eben nicht mehr das genaue timing für die 
datenübertragung. Denn falls mehrere fade-programme gleichzeitig laufen 
steigt die zeit zwischen den übertragungen was nicht sehr gut ist.
Ich versuch später mal die update-functionen in eine ISR zu packen..mal 
sehen ob das funktioniert.

Doch wieso kann ich nicht beide funktionen über ISRs aufrufen?
Liegt es an der Zeit die, die datenübertragung benötigt? Hat IRMP 
nichtmehr funktioniert weil die ISR2() zur datenübertragung zulange 
dauert und sich die interrupts dann irgendwie verschachtelt haben?

mfg
timo

von Sascha W. (sascha-w)


Lesenswert?

timo91 schrieb:
> Ich habe es wie oben beschrieben mal versucht...und es hat nicht
> geklappt. Ich habe den TIMER2 ausgemacht und rufe ISR2 jetzt von der
> ISR1 aus auf. Das Faden usw hat alles funktioniert (also der TLC) aber
> IRMP nicht.
> Dann hab ich wie vorgeschlagen die ISR2 in die schleife der
> main-function einzufügen und ...TADA  alles funktioniert schön
> miteinander.
wie erwartet

> Nur hab ich jetzt eben nicht mehr das genaue timing für die
> datenübertragung.
du kannst dir in der ISR an der stelle ein Flag setzen wo die 
Tranferroutine war, das fragst du dann in Main ab und startest das 
Update der TLC's

> Denn falls mehrere fade-programme gleichzeitig laufen
> steigt die zeit zwischen den übertragungen was nicht sehr gut ist.
das verstehe ich nicht ganz, die Zeit für Übertragungen würde auch in 
der ISR steigen

> Ich versuch später mal die update-functionen in eine ISR zu packen..mal
> sehen ob das funktioniert.
>
> Doch wieso kann ich nicht beide funktionen über ISRs aufrufen?
> Liegt es an der Zeit die, die datenübertragung benötigt?
genau - die Übertragung dauert zu lang

> Hat IRMP
> nichtmehr funktioniert weil die ISR2() zur datenübertragung zulange
> dauert und sich die interrupts dann irgendwie verschachtelt haben?
verschachtelt nicht, aber die IRMP-ISR muss eben warten wenn die 
Übertragung läuft! Damit IRMP funktioniert, darf keine andere ISR länger 
brauchen als die Zeit zwischen 2 IRMP INT's (bei 15kHz also ca. 0.07ms)

du könntest den Transfer zum TLC beschleunigen, wenn du dafür die 
SPI-Schnittstelle verwendest - falls der TLC eine höhere Geschwindigkeit 
zulässt.

Sascha

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.