mikrocontroller.net

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


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Alex (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
if (mode==0) { // 0 - Standby 
if ( !(PINB & (1<<PINB3)) ) { // Akkutyptaster (PB3) abfragen
....

obwohl er nichts anderes machen müsste.

Autor: uwegw (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Uwe ... (uwegw)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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,

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sven P. (haku) Benutzerseite
Datum:

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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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__...

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.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <avr/io.h> 
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef F_CPU 
#warning "F_CPU war noch nicht definiert, wird nun mit 1MHz definiert"
#define F_CPU 1000000UL     /* Quarz mit 1.0000 Mhz  */
#endif
#include <util/delay.h>
#include <avr/eeprom.h>

#ifndef EEMEM
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif

uint8_t emode, eakkutyp EEMEM=0;
uint16_t ezaehler EEMEM=0;


//...verschiedene Funktionen...



int main(void) {


//Datenrichtungen bestimmen
DDRB = 0b11000110;
DDRC = 0b00111100;
DDRD = 0b11100111;
PORTB = 0b00001000; //Pullup Wahltaster
PORTD = 0b10000000; //Pullup Wahltaster

int mode, akkutyp=0;
uint16_t zaehler=0;

mode=eeprom_read_byte(&emode);
zaehler=eeprom_read_word(&ezaehler);
akkutyp=eeprom_read_byte(&eakkutyp);

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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achso... die Schreibzugriffe sehen so aus:
eeprom_write_byte(&emode, mode);

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

Autor: holger (Gast)
Datum:

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

Nö, macht er nicht.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat noch jemand eine mögliche Fehlerursache für dieses Problem?

Autor: Hannes Jaeger (pnuebergang)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint8_t emode, eakkutyp EEMEM=0;

und
uint8_t emode EEMEM;
eakkutyp EEMEM=0;

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

Oliver

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arrhgh..

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

Oliver

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.