Forum: Compiler & IDEs Grundsätzliches: Ungeklärtes Verhalten


von Alex (Gast)


Lesenswert?

Hallo!

Ich habe ein Programm für den Atmega8 im AVR-Studio in GCC geschrieben, 
was mit -Os ca. 25% des Speichers belegt. Ich habe viele ungeklärte 
Verhaltensprobleme des Programms. Dinge, die einfach funktionieren 
müssen, weil sie sehr einfach gestrickt sind gehen nicht.

Also habe ich versucht und versucht - als ich schließlich große Teile 
des Programms entfernte funktionierte es plötzlich. Da die entfernten 
Teile alles Funktionen waren, die aufgerufen wurden und das entfernen 
dessen Aufrufe im Hauptprogramm keine Lösung war wunderte mich die 
Anzeige von "25% belegt".

Als ich hier im Forum nach ähnlichen Dingen suchte fiel mir auf, dass es 
ein Stack-Problem sein könnte. Aber ich erhalte keine Warnungen etc. 
beim Kompilieren. Auch benötige ich diese Programmteile. Was könnte man 
da machen? Gibt es ein Tool mit dem man diese Stack-Überschreibungen 
aufspüren kann und wie kommen sie überhaupt zustande? Benutzt der 
Kompiler nur die Register zum Speichern der Variablen und nicht den 
SRAM, wenn der Speicher knapp wird?

Ich bin neu auf diesem Gebiet und habe bisher nur kleinere Dinge 
geproggt. Habt Verständnis für meine Unwissenheit.

Gruß,

Alex

von Sven P. (Gast)


Lesenswert?

Frag erst garnich, was der Compiler macht, das versteht man nicht mal 
eben schnell. Stell lieber mal eine konkrete Frage mit Quelltext, dann 
können wir hier mithelfen und analysieren und bei Bedarf den Entwicklern 
des Compilers eine Ohrfeige verpassen :-)

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Ich weiß nicht ob das wirklich weiterhelfen wird. Es soll ein 
Akkuladegerät mit Kapazitätsmessung werden. Beispielsweise in der 
function main() wird hier testweise mode fest auf 0 gesetzt, damit ich 
fehlerhafte EEPROM-Werte ausschließen konnte. Er springt zum Verrecken 
nicht in die if-Abfrage
1
if (mode==0) { // 0 - Standby 
2
if ( !(PINB & (1<<PINB3)) ) { // Akkutyptaster (PB3) abfragen
3
....

obwohl er nichts anderes machen müsste.

von uwegw (Gast)


Lesenswert?

Wenn das Programm kompiliert wird, gibt es den Stack noch nicht! Der 
Stack wird während der Programmlaufzeit dynamisch verwaltet. Daher lässt 
sich die maximale Belegung nur sehr eingeschränkt vorhersagen.

Ach ja: meist du mit den 25% belegt wirklich das RAM, oder vielleicht 
doch eher den Flash? Das sind zwei völlig verschiedene Speicherbereiche.

von Alex (Gast)


Lesenswert?

das gibt er mir aus:

Program:    2094 bytes (25.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


Zum Verständnis: ich speichere bestimmte Werte im EEPROM ab, damit der 
µC dort weitermachen kann wo er aufgehört hat.

von Uwe .. (uwegw)


Lesenswert?

Bei den EEPROM-Zugriffen hat der Compiler mir insgesamt fünfzehn 
Warnungen um die Ohren! Und _delay_ms kannst du auch nicht mit so großen 
Werten aufrufen...

von Sven P. (Gast)


Lesenswert?

Uwe ... wrote:
> Bei den EEPROM-Zugriffen hat der Compiler mir insgesamt fünfzehn
> Warnungen um die Ohren! Und _delay_ms kannst du auch nicht mit so großen
> Werten aufrufen...

Ersteres kann ich grad nich beurteilen, aber _delay_ms kann man mit 
großen Werten aufrufen. Hauptsache, die Werte sind konstant. Wird dann 
bissi ungenau, aber gehen tuts in jedem Fall, bis zu 6.5535 Sekunden 
sind möglich,

von Alex (Gast)


Lesenswert?

das habe ich testweise so gemacht, dass ich die speicheradresse direkt 
reinschreibe um den stack zu schonen. war vorher anders. AAh... das 
erklärt, warum die 10 Sekunden beim Laden nicht wirklich 10 sind. Danke 
für den Hinweis.

von Sven P. (Gast)


Lesenswert?

Das mit den zehn Sekunden hat vermutlich nen andren Grund:
1
#define F_CPU 1000000UL     /* Quarz mit 3.6864 Mhz  */

von Alex (Gast)


Lesenswert?

nee... sorry... das kommentar ist falsch. Hatte ich irgendwo von dieser 
Seite kopiert und vergessen abzuändern. Nutze den internen Werksseitigen 
Taktgeber bei 1MHz.

von Alex (Gast)


Lesenswert?

was ich auch nicht verstehe... im Debugger funxt alles so wie ich mir 
das vorstelle. Dort wird doch auch der Stack simuliert, oder?

von Simon K. (simon) Benutzerseite


Lesenswert?

Sven Pauli wrote:
> Uwe ... wrote:
>> Bei den EEPROM-Zugriffen hat der Compiler mir insgesamt fünfzehn
>> Warnungen um die Ohren! Und _delay_ms kannst du auch nicht mit so großen
>> Werten aufrufen...
>
> Ersteres kann ich grad nich beurteilen, aber _delay_ms kann man mit
> großen Werten aufrufen. Hauptsache, die Werte sind konstant. Wird dann
> bissi ungenau, aber gehen tuts in jedem Fall, bis zu 6.5535 Sekunden
> sind möglich,

Jau, ganz klammheimlich hat's sich eingeschlichen:
http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, 
_delay_ms() provides a decreased resolution functionality. In this mode 
_delay_ms() will work with a resolution of 1/10 ms, providing delays up 
to 6.5535 seconds (independent from CPU frequency). The user will not be 
informed about decreased resolution.

von Micha (Gast)


Lesenswert?

Also ich hab bei meinen ungeklärten Phänomenen letztlich doch immer den 
Fehler irgendwie bei MIR gefunden. Jetzt bzgl. EEPROM war es so, daß ich 
irgendwann entdeckt hab, daß man KEINES der EEPROM-Register ändern kann, 
solange der Schreibvorgang noch nicht abgeschlossen ist, also man kann 
solange auch nicht lesen! Zumindest nicht das, was man richtigerweise 
gelesen hätte.
Jetzt kann man natürlich vor JEDEM Zugriff das EEPE-bit im EECR 
abfragen, ich hab dann aber (nachdem ich nur einen zentralen 
Schreibzugriff hab) die Abfrage nur nach dem Schreibvorgang eingebaut.
Hab damals auch eine Weile das "ungeklärte Verhalten" studiert....
Wie schaut dein EEPROM-Zugriff (schreiben) aus?

von Alex (Gast)


Lesenswert?

Hi Micha!

Danke für deinen Hinweis. Ich habe mal testweise alle EEPROM-Zugriffe 
entfernt und es läuft. Also habe ich meine EEPROM Routine mal 
überarbeitet.
1
#include <avr/io.h> 
2
#include <stdint.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
#ifndef F_CPU 
6
#warning "F_CPU war noch nicht definiert, wird nun mit 1MHz definiert"
7
#define F_CPU 1000000UL     /* Quarz mit 1.0000 Mhz  */
8
#endif
9
#include <util/delay.h>
10
#include <avr/eeprom.h>
11
12
#ifndef EEMEM
13
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
14
#define EEMEM  __attribute__ ((section (".eeprom")))
15
#endif
16
17
uint8_t emode, eakkutyp EEMEM=0;
18
uint16_t ezaehler EEMEM=0;
19
20
21
//...verschiedene Funktionen...
22
23
24
25
int main(void) {
26
27
28
//Datenrichtungen bestimmen
29
DDRB = 0b11000110;
30
DDRC = 0b00111100;
31
DDRD = 0b11100111;
32
PORTB = 0b00001000; //Pullup Wahltaster
33
PORTD = 0b10000000; //Pullup Wahltaster
34
35
int mode, akkutyp=0;
36
uint16_t zaehler=0;
37
38
mode=eeprom_read_byte(&emode);
39
zaehler=eeprom_read_word(&ezaehler);
40
akkutyp=eeprom_read_byte(&eakkutyp);

Wenn ich die letzten 3 Zeilen weglasse geht es. Mache ich etwas falsch?

von Alex (Gast)


Lesenswert?

achso... die Schreibzugriffe sehen so aus:
1
eeprom_write_byte(&emode, mode);

hab aber irgendwo gelesen, dass der Compiler automatisch einen Code 
einbaut der wartet, bis das Schreiben abgeschlossen ist.

von holger (Gast)


Lesenswert?

>hab aber irgendwo gelesen, dass der Compiler automatisch einen Code
>einbaut der wartet, bis das Schreiben abgeschlossen ist.

Nö, macht er nicht.

von Alex (Gast)


Lesenswert?

Hmmm... Hier aus dem AVR-GCC Tutorial:

Bei Nutzung des EEPROMs ist zu beachten, dass vor dem Zugriff auf diesen 
Speicher abgefragt wird, ob der Controller die vorherige 
EEPROM-Operation abgeschlossen hat. Die avr-libc-Funktionen beinhalten 
diese Prüfung, man muss sie nicht selbst implementieren

BTW: Habe inzwischen herausgefunden, dass ich die beiden Bytes auf diese 
Art lesen kann - nur beim Word hängt er sich auf. Ideen?

von Alex (Gast)


Lesenswert?

hat noch jemand eine mögliche Fehlerursache für dieses Problem?

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Welche Compiler-Version? Es gab vor ein paar Monaten eine avr-gcc 
Version die ein paar Macken hatte. Die sind in der aktuellen Version 
behoben.

von Alex (Gast)


Lesenswert?

ich habe das auch gelesen dass es vorher Probleme gab. Habe deswegen 
sowohl AVR Studio als auch WinAVR auf die neuste Version geupdatet.

von Oliver (Gast)


Lesenswert?

1
uint8_t emode, eakkutyp EEMEM=0;

und
1
uint8_t emode EEMEM;
2
eakkutyp EEMEM=0;

ist nicht das selbe. Im ersten Fall wird emode als normale Variable im 
SRAM angelegt, nicht im EEPROM.

Oliver

von Oliver (Gast)


Lesenswert?

Arrhgh..

so sollte es sein:
1
uint8_t emode EEMEM;
2
uint8_t eakkutyp EEMEM=0;

Oliver

von Alex (Gast)


Lesenswert?

es bleibt leider bei dem Verhalten, dass er keine Words aus dem EEPROM 
lesen kann... warum auch immer...

gibt es eine möglichkeit eine Word-Variable in 2 Bytevariablen zu 
zerlegen um diese beiden Werte zu speichern und später auch wieder 
einzeln zu lesen um daraus wieder eine Word-Variable zu machen?

Habe solche Umwandlungen noch nie durchgeführt. Gibt es dafür komplette 
Funktionen in AVRGCC?

Gruß,

Alex

von Oliver (Gast)


Lesenswert?

Gibt es. Nennt sich eeprom_read_word().

Wie immer bei solch langen und am Ende fruchtlosen Threads:
Ohne warnungs- und fehlerfrei kompilierbaren und lauffähigen Sourcecode, 
der das Problem zeigt, wird das nichts.

Oliver

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.