Hallo. Ich habe eine Atmega32 mit einem S65 LCD und einer SD karte am laufen. Die SD karte läuft mit dem Code von Ulrich R. Leider habe ich seit ein paar Wochen sehr komische Probleme mit der Schaltung. Mein Code ist mit der zeit am wachsen. logisch. aber jetzt das komische verhalten vom avr. Es ist so, das wenn ich eine neue Funktion "hinzufügen" in der lib fürs LCD, funktionier mein gesamtes Programm nicht mehr sauber. das LCD zeigt nur noch schrott an. Und das, obwohl die Funktion gar nicht aufgerufen wird? Wenn ich in der Main Funktion hinter der LCD Ausgabe etwas auf der uart ausgeben möchte, habe ich ähnliche Fehler verhalten. nehme ich die uart Geschichte wieder raus, läuft es. Achso, das Bild wird auf der SD karte gefunden, und auch geladen. Kann es sein, das mein RAM im AVR defekt ist vom (vielen) programmieren? Oder kann es am AVR Studio liegen? Habe die Version 4.14. Achso, sobald ich den compiler aus eine andere optimierung einstelle, bekomme ich auch ein ähnliches verhalten, das das LCD nur noch mist anzeigt, bzw. er den Bild bereich ändert. vieleicht hat jemand eine lösung für mich. ich weiß nicht wirklich, wo ich anfangen soll zu suchen.
Klingt nach einer möglichen ursache. Bedeutet das ein Programmier fehler? Oder defekter RAM? Wie kann ich es überprüfen, und falls es der fall sein sollte, beheben?
laut ockhams razor wirds an deinem code liegen ;).. hast du keine simulationsmöglichkeit? oder hardware debugger? in der software irgendwelche debug-ausgabe möglichkeit? ich habe für debug ziemlich viel code investiert, damit ich per uart alles mögliche an internen zuständen ausgeben kann, sowie umfangreiche exception try-catch konstrukte (allerdings in asm).. ohne alles das wäre ich nie weitergekommen, und auch mit diesen möglichkeiten hilft manchmal nur das simulieren. wenn fehler sich eingrenzen lassen, in dem du bestimmte programmteile rausnimmst, weißt du ja schon wo du anfangen musst. weiter eingrenzen lässt sich es in dem du zu debugzwecken den code weiter veränderst, und die auswirkung auf das fehlerbild analysierst. oft zeigt sich z.b. am zeitpunkt des auftretens was der auslöser sein könnte. wenn dein programm sofort beim einschalten abschmiert kommt man mit dem simulator schnell weiter, da man nicht viele taktzyklen warten muss. wie immer gilt, ohne weitere infos, quellcode, kann man kaum mehr als das orakel befragen...
>Bedeutet das ein Programmier fehler? In gewisser Weise schon ;) >Oder defekter RAM? Nein. >Wie kann ich es überprüfen, und falls es der fall sein sollte, beheben? Man kann durch exzessive Nutzung von z.B. printf() ganz schön viel RAM verbrauchen. Da liegen die auszugebenden Strings im RAM. Wenn man printf_P() nimmt liegen sie im Flash. Ist aber nur ein Beispiel. Wo du RAM vernichtest kann uns nur dein Code verraten.
OK, hier meine "main"
1 | int main(void){ |
2 | |
3 | usart_init(38400); |
4 | DDRD |= (1 << PD7); // PD0 als Ausgang festlegen |
5 | |
6 | display_init(); |
7 | init_sd(); |
8 | |
9 | //____________________________________
|
10 | // Drehgeber Anschluß
|
11 | DDRC &= ~(_BV(PC1) | _BV(PC0)); // Pin's als Eingang |
12 | PORTC = (_BV(PC1) | _BV(PC0)); // PullUp's ein |
13 | DDRB = 0xFF; // Port als Ausgang |
14 | |
15 | // Timer0 einstellen
|
16 | // TCCR0 = 1<<CS01 | 1<<CS00; // Teilung durch 256 * 64 Int. alle 2ms bei 8MHz CLK
|
17 | TCCR0 = 1<<CS02; // Teilung durch 256 * 256 Int. alle 8,2ms bei 8MHz CLK |
18 | TIMSK = 1<<TOIE0; // enable timer interrupt |
19 | sei(); |
20 | //______________________________________________
|
21 | |
22 | |
23 | unsigned int Clustervar; |
24 | unsigned char Dir_Attrib = 0; |
25 | unsigned long Size = 0; |
26 | |
27 | //Ausgabe des Root Directory
|
28 | usart_write("\n\nDirectory\n\n"); |
29 | for (char a = 1;a < 240;a++) |
30 | {
|
31 | Clustervar = fat_read_dir_ent(0,a,&Size,&Dir_Attrib,Buffer); |
32 | if (Clustervar == 0xffff) |
33 | {
|
34 | break; |
35 | }
|
36 | tmp = (Size & 0x0000FFFF); |
37 | usart_write("Cluster = %4x DirA = %2x FileName = ",Clustervar,Dir_Attrib); |
38 | usart_write(&Buffer); |
39 | usart_write("\n"); |
40 | }
|
41 | usart_write("\nDirectory Ende\n\n");*/ |
42 | |
43 | |
44 | |
45 | ////////////////////////////////
|
46 | char picname[20]; |
47 | char npicnamen3[20] = "conf.txt"; |
48 | |
49 | |
50 | strcpy(picname, "16.bmp"); |
51 | S65_PutBmpFromSD(0,0, &picname[0]); |
52 | _delay_ms(1000); |
53 | |
54 | |
55 | S65_Fillscreen(0000); |
56 | s65_mainsplit(); |
57 | |
58 | |
59 | S65_SetTextColor(0x07E0); |
60 | char e[20] = {'U','h','r',0}; |
61 | S65_PutStr(30,108, &e[0]); |
62 | |
63 | _delay_ms(2000); |
64 | strcpy(picname, "door_o.bmp"); |
65 | S65_PutBmpFromSD(0,20, &picname[0]); |
66 | _delay_ms(1000); |
67 | |
68 | |
69 | while (1) { |
70 | |
71 | //__________________________________________
|
72 | //Ausgabe = richtung;
|
73 | //cls(1);
|
74 | //S65_PutByte(80,40, richtung);
|
75 | Ausgabe = ~richtung; // Nur beim STK500 |
76 | //usart_write(richtung);
|
77 | usart_write("Drehrichtung: %i \n",richtung); |
78 | usart_write("\n"); |
79 | //____________________________________________
|
80 | |
81 | |
82 | PORTD |= (1 << PD7); // PD0 aktivieren |
83 | _delay_ms(500); |
84 | PORTD &= ~(1 << PD7); // PD0 deaktivieren |
85 | _delay_ms(500); |
86 | |
87 | }
|
88 | }
|
Und hier die andere funktion:
1 | int S65_lese_konfig(char *picname3) |
2 | {
|
3 | uint8_t tmp3; |
4 | unsigned int Clustervar3; |
5 | unsigned char Dir_Attrib3 = 0; |
6 | unsigned char Buffa3[512]; |
7 | unsigned long Size3 = 0; |
8 | //char picname3[20];
|
9 | // --------------------------------------------------------------------------
|
10 | // Konfig datei lesen:
|
11 | usart_write("------------------------------------------\n\n"); |
12 | usart_write("\n\nlese konfig file\n\n"); |
13 | mmc_read_csd (Buffa3); |
14 | usart_write_str (picname3); |
15 | |
16 | |
17 | /*Clustervar3 = 0;
|
18 | if (fat_search_file(picname3,&Clustervar3,&Size3,&Dir_Attrib3,Buffa3) == 1)
|
19 | {
|
20 | usart_write("\n--------------------------------\n\n");
|
21 | usart_write("\nKonfig File Found!!\n\n");
|
22 | usart_write("Size = %i \n",&Size3);
|
23 | //char filefound[20] = {'F','i','l','e',' ','f','o',' ',0};
|
24 | //S65_PutStr(10,50, &filefound[0]);
|
25 | //Lese File und gibt es auf der seriellen Schnittstelle aus
|
26 | |
27 | fat_read_file (Clustervar3,Buffa3,0);
|
28 | _delay_ms(400);
|
29 | |
30 | for (tmp3 = 0;tmp3<160;tmp3++)
|
31 | {
|
32 | usart_write("Buffer: %x ",Buffa3[tmp3]);
|
33 | // char e[20] = {'B','u','f',0};
|
34 | // S65_PutStr(10,30, &e[0]);
|
35 | };
|
36 | |
37 | usart_write("\n--------------------------------\n\n");
|
38 | }
|
39 | |
40 | else
|
41 | {
|
42 | usart_write("File Not Found - conf.txt");
|
43 | }*/
|
44 | // ------------------------------------------------------------------------
|
45 | usart_write("\n\nende lese konfig file\n\n"); |
46 | usart_write("------------------------------------------\n\n"); |
47 | return(1); // Alles klar, keine Fehler |
48 | }
|
Sobald ich das kommentar bei "if (fat_search_file" raus werfe spinnt mein programm rum.
Schmeiss doch mal alle usart_write("------------------------------------------\n\n"); raus. Funktioniert es dann ?
gast wrote: > Klingt nach einer möglichen ursache. > Bedeutet das ein Programmier fehler? > Oder defekter RAM? Nein, das bedeutet, dass dein Programm mehr RAM-Speicher benötigt als der Baustein zur Verfügung stellt, der ATmega32 hat "nur" 2-Kbyte SRAM dein Programm bräuchte aber möglicherweise 3KB, 4KB oder noch mehr SRAM. > Wie kann ich es überprüfen, Du könntest dir evt. an bestimmten Stellen den Inhalt des Stackpointers ausgeben lassen, also wenn der Stack beim AVR von oben nach unten wächst und der Stackpointer plötzlich "ganz unten" ankommt, also z.B. bei 0000 oder 0002, (läuft das so beim ATmega?), dann spricht vieles dafür, dass du zu wenig SRAM hast, dann kann alles durcheinander kommen: Variablen werden überschrieben, Unterprogramm und Interruptrücksprungadressen gehen verloren, usw. ... > und falls es der fall sein sollte, beheben? Einen Prozessor mit mehr SRAM besorgen z.B. den ATmega644 (mit 4KB SRAM), oder externes RAM verwenden, (eher unpraktisch). Oder mal dein Programm durchschauen: Rekursive oder sehr verschachtelte Unterprogrammaufrufe brauchen viel RAM, und, (da hab ich leider noch nicht allzu viel Ahnung von Win-AVR-C), möglicherweise kannst du was retten wenn du darauf schaust, dass alle Funktionsparameter "By Reference" d.h. als Pointer und nicht als Speicherkopie d.h. "By Value" übergibst. Umfangreiche Stringmanipulationen sind bei 2KB Ram wohl auch nicht drin. Im Prinzip musst du dir bei jeder Funktion, bei jeder Schleife und bei jeder zur Laufzeit angelegten Variable überlegen wieviel RAM dafür wohl verbraucht wird. Nachtrag: Gerade mal kurz in deinen Code reingeschaut, (wie gesagt, hab da nicht viel Ahnung von), aber wenn ich nur 2KB SRAM hätte, würde ich nicht so verschwenderisch mit den "char filefound[20]" etc. um mich werfen... Alle Stringkonstanten müssen ins Flash, (oder optimiert das der Compiler?). Und der "unsigned char Buffa3[512];" da ist ja schon mal von vornerein ein Viertel des RAMs auf einen Schlag weg.
> Alle Stringkonstanten müssen ins Flash, (oder optimiert das der > Compiler?). Der Compiler optimiert das nicht. Die Stringkonstanten sind zwar im Flash, werden sie aber nicht auf eine spezielle Weise deklariert und über eine Spezialfunktion gelesen, sondern einfach nach der Methode "usart_write("------------------------------------------\n\n");" eingetragen, dann werden diese Konstanten beim Programmstart ins RAM umgeladen. Da bleibt dann für den Stack nichts mehr übrig. Besser man macht es so: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Array_aus_Zeichenketten_im_Flash-Speicher Gruß Jadeclaw.
Schade, ich dachte der compiler meldet sich mal, wenn er merkt falls es eng wird. Der hätte ja nun wirklich den überblick. "Buffa3[512];" wird in einer Funktion deklariert. Wenn ich diese Funktion jetzt dreimal aufrufe, belegt sie doch nur einmal den speicher, oder habe ich da grundsätzlich irgendwas noch nicht verstanden?
nein, der speicher wird jedesmal reserviert. er wird zwar (im normalfall) wieder freigegeben, aber wenn z.b. nur mehr 300 kB ram übrig sind, es werden aber 512 benötigt gibts schon probleme. wie die speicherverwaltung auf dem avr in c funktioniert weiß ich leider nicht genau, programmiere in asm...
Zweiter Gast wrote:
> Hmm, hilft da "static unsigned char Buffa3[512];" ?
Dann werden die 512 Bytes eben dauerhaft belegt, (könnte aber
vielleicht, in anderen Situationen, unter gewissen Umständen, wenn man
das gleich beim Programmstart mit allen dauerhaft benötigten Buffern
macht, dabei helfen, die Speicherfragmentierung zu verringern).
Aber das Grundproblem bleibt dasselbe: Nur 2024 Bytes RAM die sich
Variablen und Stack teilen müssen.
Zweiter Gast wrote: > Hmm, hilft da "static unsigned char Buffa3[512];" ? Wurde doch schon gepostet: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Array_aus_Zeichenketten_im_Flash-Speicher
Erstaunlich. Durch ein wenig optimierung und ausklammern von "usart_write" funktioniert es jetzt. An einen Stacküberlauf habe ich überhaupt nicht gedacht. Ein "Danke" an alle beteiligten.
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.