Hi, ist sicher ne Kinderfrage, aber ich find dazu leider nix... Und zwar programmiere ich grad einen AT90CAN128 (=Atmega128+CAN?) in C bzw. dem AVR-Studio, der Code ist schon ziemlich groß, Variablen gibts sehr viele, allerdings nur Bytes und Words bzw. diese als Array. Jetzt stell ich gerade fest, dass eine Variable, die am Anfang mit einem Wert (0) initialisiert wird und ansonsten nicht verändert (soweit bin ich noch nicht), einfach ihren Wert ändert. Das stelle ich über ein Pin fest, an das die Variable ausgegeben wird. Ursprünglich hab ich die Variable während dem Programmablauf initialisiert (=0) Wenn ich die Variable über ein Display ausgebe, ändert sich allerdings nichts mehr. Wenn ich die Variable bei der Variablendeklaration schon initialisiere, ändert sich auch nichts mehr. Jedoch "volatile" vor der Variablendeklaration zu setzen bringt keine Abhilfe. Wodurch kommt das bzw. wie kann ich es sicher unterbinden? Grüße, Tobias
Tobias B. schrieb: > Jetzt stell ich gerade fest, dass eine Variable, die am Anfang mit einem > Wert (0) initialisiert wird und ansonsten nicht verändert (soweit bin > ich noch nicht), > einfach ihren Wert ändert. Das stelle ich über ein Pin fest, an das die > Variable ausgegeben wird. Das ist Deine Idee. Der Sourcecode (den wir bisher nicht sehen konnten) zeigt aber etwas anderes.
1 | uint8_t OUTP_READY; |
2 | uint8_t OUTP_LIMITER=0; // <--- So gehts, ohne =0 ändert sich es. |
3 | uint8_t OUTP_BUZZER; |
4 | |
5 | ....
|
6 | |
7 | void init_ports(void) |
8 | {
|
9 | OUTP_BUZZER = 0; |
10 | OUTP_READY = 0; |
11 | OUTP_LIMITER = 0; |
12 | DDRA = 0b00000111; // 3 Digitale Ausgänge an Port A |
13 | DDRF = 0b00000000; // ADCs nur lesen |
14 | PORTF = 0b00000000; // Keine Pullup-Widerstände am ADC |
15 | }
|
16 | |
17 | void write_pins(void) |
18 | {
|
19 | uint8_t out = 0; |
20 | if(OUTP_READY) |
21 | out |= (1<<PA0); |
22 | if(OUTP_LIMITER) |
23 | out |= (1<<PA1); |
24 | if(OUTP_BUZZER) |
25 | out |= (1<<PA2); |
26 | PORTA = out; |
27 | }
|
es geht um OUTP_LIMITER und die Variable wird sonst nirgends im Code verwendet... Letzte Funktion wird über eine Endlosschleife in der main() dauernd wiederholt
Vielleicht reicht das SRAM nicht für alle globalen Variablen + Stack. Dann überschreibt der Stack die Variablen. AFAIK wird das nicht durch eine Fehlermeldung abgefangen. Pro ineinandergeschachtelten Funktionsaufruf wird auf dem Stack Platz für die Rücksprungadresse plus alle lokalen Variablen der Funktion benötigt. HTH Randy
Sowas dachte ich mir auch schon, nur zeigt der Compiler das nicht an (wie er es beim Atmega8 z.B tut.
1 | AVR Memory Usage |
2 | ---------------- |
3 | Device: at90can128 |
4 | |
5 | Program: 18652 bytes (14.2% Full) |
6 | (.text + .data + .bootloader) |
7 | |
8 | Data: 3190 bytes (77.9% Full) |
9 | (.data + .bss + .noinit) |
10 | |
11 | EEPROM: 1610 bytes (39.3% Full) |
12 | (.eeprom) |
> Sowas dachte ich mir auch schon, nur zeigt der Compiler das nicht an > (wie er es beim Atmega8 z.B tut. ... > Data: 3190 bytes (77.9% Full) > (.data + .bss + .noinit) Tut er hier auch nicht. Die 3190 Bytes sind die Variablen die immer Speicher belegen (d.h. globale und static). Wie groß der Stack wird weiß der Complier nicht, das hängt ja davon ab wie tief verschachtelt die Funktionaufrufe stattfinden. Das stellt sich erst zur Laufzeit raus. AFAIK haben die AVRs keine (Hardware-)Logik eingebaut die überprüfen kann ob der Stack so groß geworden ist dass er in den Speicherbereich der globalen Variablen hineingewachen ist. Randy
Variablen, die aus unerfindlichen Gründen ihren Wert ändern, können auch ein Hinweis darauf sein, dass irgendwo ein Arrayzugriff in die Hose geht und du ausserhalb der definierten Arrayindizierung in das Array schreibst
1 | uint8_t i = 5; |
2 | uint8_t Array[5]; |
3 | uint8_t j = 8; |
4 | |
5 | int main() |
6 | {
|
7 | Array[5] = 4; |
8 | |
9 | // an dieser Stelle im Programm hat entweder i oder j,
|
10 | // je nach Compiler und in welcher Reihenfolge er die
|
11 | // Variablen im Speicher ablegt, seinen Wert geändert
|
12 | }
|
Dies ist eigentlich der häufigste Fall, dicht gefolgt vom Stacküberlauf, bei dem der Stack in den Variablenbereich hineinwächst.
Lag wohl an beidem... Hab nen String übergeben a eine Displayfunktion. String abgekürzt und jetzt funktioniert es. So muss ich wohl ein paar Arrays ins EEPROM auslagern bzw. drin lassen. Hatte bis jetzt das alle Daten beim Start aus dem EEPROM ins SRAM geladen, um bisschen Rechenzeit zu sparen. Danke für eure Hilfe!
Schau mal lieber erst mal nach, was du so an konstanten Strings im Programm hast, und stecke die ins Flash.
Tobias B. schrieb: > Lag wohl an beidem... > > Hab nen String übergeben a eine Displayfunktion. String abgekürzt und > jetzt funktioniert es. String, der in einem Array zwischengespeichert wird? Array zu klein dimensioniert? Das abschliessende \0 Zeichen nicht eingerechnet?
1 | void lcd_str8(const char *s) // Strings ausgeben, 8 Pixel Schrifthöhe |
2 | {
|
3 | uint8_t chr; |
4 | while ((chr = *s++)) |
5 | { lcd_chr8(chr); } |
6 | }
|
Ich bin mir nicht sicher was der Compiler hier macht, aber ich vermute, dass der String hier als Array an die Funktion übergeben wird. Glaube nicht dass der Compiler so clever ist, und die Zeichen einzeln aus dem Flash ausliest. Abgesehen davon ist der Platz im SRAM tatsächlich sehr begrenzt, daher werd ich ihn ausmisten müssen.
Problem erkannt und wie immer ists ganz einfach. Der Text geht aus dem Display hinaus... das stinkt verdächtig nach dem Array-Überlauf.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.