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
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 :-)
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
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.
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.
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...
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,
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.
nee... sorry... das kommentar ist falsch. Hatte ich irgendwo von dieser
Seite kopiert und vergessen abzuändern. Nutze den internen Werksseitigen
Taktgeber bei 1MHz.
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.
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?
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
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?
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
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