Hallo,
ich hab mal wieder mit C meine lieben Probleme...(bezutze AVR Studio)
mein Programm funktioniert nicht richtig, schon in der Simulation nicht,
Variablen ändern schlagartig ihren Wert obwohl weit und breit nichts
darauf zugreift. Es ist sicher ein Problem mit static, volatile &
Co...ich hab die Sachen wohl nicht verstanden...
Ich hab schon einiges probiert, ich weis schon gar nicht mehr wie der
Urzustand war, aber ich fang jetzt einfach mal an:
Auf jedenfall ist mir aufgefallen das in meinem Programm die Variablen
buffer[] und timer_adc die selbe Adresse haben was wohl nicht gut ist...
hier ein Ausschnitt vom Program:
> Variablen ändern schlagartig ihren Wert obwohl weit und breit nichts> darauf zugreift.
Das deutet i.d.R. auf einen Überlauf oder einen fehlgeleiteten Zeiger
hin. Und auf welchem Controller bist Du unterwegs?
Ich verwende einen ATmega8, die Compileroptimierung hab ich auch mal
ausgeschaltet aber ändert nix. Beim Übersetzten kommt, das nur ca 50%
Speicher belegt sind. Bin ratlos, bei meinen Versuchen bin ich laufend
auf Probleme der Art: "schreibe was in eine Variable, eine andere nimmt
einen ganz kuriosen Wert an, oder: Vor einem Unterprogramm Aufruf ist
die Variable in der main() noch ok, bis zum Rücksprung aus dem UP auch
noch, nach dem Rücksprung ist der Wert ein anderer
Peter schrieb:>> if(bytecnt >= 512)>> die Prüfung kommt ein wenig spät wenn du vorher schon 10mal etwas auf> bytecnt addierst.
Hab ich zuerst auch gedacht, aber er hat das Glück, dass seine Records
immer 8 Bytes lang sind und das geht sich ganzzahlig in 512 Bytes aus.
Schön ist es trotzdem nicht. Fehleranfällig: ja klar.
Sollte man korrigieren, aber dürfte hier nicht das Problem sein.
Stefan A. schrieb:> Ich verwende einen ATmega8, die Compileroptimierung hab ich auch mal> ausgeschaltet aber ändert nix. Beim Übersetzten kommt, das nur ca 50%> Speicher belegt sind.
Moment.
Du hast >50% SRAM verbraucht?
Dann überläufst du deinen Speicher.
Denn der 512-Byte Buffer in main() ist als funktionslokale Variable in
dieser Statistik nicht mit enthalten. Mach den mal als globale Variable
und erfreue dich an >100% SRAM Auslastung.
> Bin ratlos, bei meinen Versuchen bin ich laufend> auf Probleme der Art: "schreibe was in eine Variable, eine> andere nimmt einen ganz kuriosen Wert an, oder: Vor einem> Unterprogramm Aufruf ist die Variable in der main() noch ok,> bis zum Rücksprung aus dem UP auch noch, nach dem Rücksprung> ist der Wert ein anderer
All das sind (unter anderem) klassische Symptome von: Stack durch
Überlauf zerschossen.
Peter schrieb:>> if(bytecnt >= 512)>> die Prüfung kommt ein wenig spät wenn du vorher schon 10mal etwas auf> bytecnt addierst.
hm ich möchte den buffer mit 512 Byte randvollschreiben -- 512/8 = 64,
sollte also irgendwann genau eine Punktlandung auf 512 ergeben und
write_data(buffer, address) wird aufgerufen
> Moment.> Du hast >50% SRAM verbraucht?>> Dann überläufst du deinen Speicher.> Denn der 512-Byte Buffer in main() ist als funktionslokale Variable in> dieser Statistik nicht mit enthalten. Mach den mal als globale Variable> und erfreue dich an >100% SRAM Auslastung.>> All das sind (unter anderem) klassische Symptome von: Stack durch> Überlauf zerschossen.
Ei ei, das hört sich aber nicht gut an...In der Tat, wenn ich buffer[]
global mache, dann hab ich schon 99.8% Auslastung...
kurios ist, es funktioniert etwas besser in der Simulation und auch auf
Real, aber dann schlägt wieder dieser, ich nen es mal "Fehler" zu:
1
for(inti=0;i<512;i++)buffer[i]=0;
Die Laufvariable kommt bis genau 509 und als nächstes kommt wieder 266 =
Endlossschleife, aber der Rest ging bis dahin besser...
Naja das ändert aber nichts daran, dass ich ein Problem hab. Wie kann
ich meinen SRAM "entschlacken"?
>Hab ich zuerst auch gedacht, aber er hat das Glück, dass seine Records>immer 8 Bytes lang sind und das geht sich ganzzahlig in 512 Bytes aus.>Schön ist es trotzdem nicht. Fehleranfällig: ja klar.>Sollte man korrigieren, aber dürfte hier nicht das Problem sein.
Hm wie kann man das besser machen?
Stefan A. schrieb:> kurios ist, es funktioniert etwas besser in der Simulation und auch auf> Real, aber dann schlägt wieder dieser, ich nen es mal "Fehler" zu:for(int i = 0;
i < 512; i++) buffer[i] = 0; Die Laufvariable kommt bis genau 509 und als nächstes
kommt wieder 266 =
> Endlossschleife, aber der Rest ging bis dahin besser...
Du hast ja nun keinen Platz für den Stack mehr
Stefan A. schrieb:> Naja das ändert aber nichts daran, dass ich ein Problem hab. Wie kann> ich meinen SRAM "entschlacken"?
Indem du Variablen einsparst.
Wo wird denn der Rest des Speichers verbraucht?
Bei dir reicht ein Byte hier, ein Byte da nicht mehr.
Da muss man schon gröber nachsehen. Also: Alle globalen Variablen
durchsehen, vor allen Dingen große Arrays und versuchen sie loszuwerden.
Die SD-Routinen unterhalten nicht zufällig auch noch große Buffer?
> Hm wie kann man das besser machen?
Indem man nach jedem Byte, welches in den Buffer kommt nachsieht, ob man
den Buffer nicht ausleeren müsste. Zu diesem Zwecke bietet sich dann
eine Funktion an, die genau das macht:
1 Byte in den Buffer einfügen
prüfen ob der Buffer dadurch voll geworden ist und ausgeleert werden
muss
Deine Schreibsequenz sieht dann so aus:
1
....
2
if(blockcnt<=2)
3
{
4
cache=BINtoASCII(temp);
5
6
write_byte(0x3D);
7
write_byte(0x3D);
8
write_byte((cache>>24)&0xFF);
9
write_byte((cache>>16)&0xFF);
10
write_byte((cache>>8)&0xFF);
11
write_byte((cache>>0)&0xFF);
12
write_byte(0x0D);
13
write_byte(0x0A);
14
}
15
....
16
17
...
18
19
voidwrite_byte(BYTEbyte)
20
{
21
buffer[bytecnt]=byte;
22
bytecnt++;
23
24
if(bytecnt>=512)
25
{
26
bytecnt=0;
27
// uart_putint(address);
28
if(write_data(buffer,address)==0)
29
uart_puts("Schreiben erfolgreich...");
30
else
31
uart_puts("Error ......
32
....
Neben dem defensiven Gedanken zur Fehlervermeidung hat das dann auch
noch den Vorteil der besseren Übersicht :-) Man sieht sehr viel besser
was in welcher Reihenfolge geschrieben wird, ohne dass immer wieder
irgendwelche 'Zwischenanweisungen' den Lesefluss stören.
Es ist zwar nicht viel, aber du könntest mal damit anfangen all die
konstanten Texte ins Flash auszulagern (*)
Das sind schon mal 100 Bytes SRAM, die du ziemlich billig freischaufeln
kannst. Nur mit den Texten, die du gezeigt hast :-)
(*) eigentlich falsch ausgedrückt. Denn die Texte sind schon im Flash.
Sie werden beim Programmstart noch zusätzlich ins SRAM kopiert, damit zb
uart_puts schön darauf zugreifen kann.
Karl heinz Buchegger schrieb:> Das sind schon mal 100 Bytes SRAM, die du ziemlich billig freischaufeln> kannst. Nur mit den Texten, die du gezeigt hast :-)
Einfach uart_puts durch uart_puts_P ersetzen
ich liebe euch :D
hab nun ca 400 Byte rausgeschunden - und alles funktioniert einwandfrei
nun. Auf den Fehler wäre ich nie im Leben gekommen
>Einfach uart_puts durch uart_puts_P ersetzen
Aber ich weis nicht was damit gemeint ist. Meine uart Routinen hab ich
selbst geschrieben und sind deshalb recht einfach
Auf die schnelle hab ich nicht rausgefunden wie ich meine Texte auf den
Flash speichern lassen kann - damit würde ich nochmal 60Byte rausholen
können
Warum gibt es denn keinen Fehlermeldung oder zumindest ne Warnung wenn
der SRAM überfüllt ist?
> Auf die schnelle hab ich nicht rausgefunden wie ich meine Texte auf den> Flash speichern lassen kann
pgm_read_*() zum lesen, PSTR() ums bequem in den Flash zu verbannen.
Beides in pgmspace.h (avr-libc)
> Warum gibt es denn keinen Fehler oder zumindest ne Warnung wenn der SRAM> überfüllt ist?
Weil es in der Regel nicht möglich ist, das vorherzusagen(!). Und wenns
mit ("globalem") Zeugs zugemüllt ist, dann gibts dir avr-objcopy/..
hüpsch aus :-)