Grundsätzliches: Ungeklärtes Verhalten

Gast #932916
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
Gast #932918
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 :-)
Gast #932926
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.
Angehängte Dateien:
Gast #932929
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.
Gast #932932
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.
Gast #932956
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,
Gast #932957
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.
Persönliche Seite #932971
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.
Gast #932987
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?
Gast #932991
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?
Gast #932995
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.
Gast #933156
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?
Gast #936259
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
Gast #936673
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren