Tachchen ihr Dioden;) Heut hab ich mal ein Prob, welches ich nun seit 24h nicht gelöst bekomm und hoffe auf Eure Hilfe. Zum System: Atmega32 AVR STUDIO 4.13 SP1 F_CPU 8000000UL Optimierung -01 Zum Prob: Ich habe ein Menue, in dem ich eine einfache Zahl ( als volatile uint8_t gespeichert ) inkrementieren lassen kann und sie über itoa aufs lcd angezeigt wird. Alles funkt, wenn ich den Controller quasi beim Start ( vor der while(1) ) in dieses Menue gehen lass und dann den Wert per Taste ändere. Rufe ich ein anderes ( z.B. das Hauptmenue ) erst auf und "springe" dann in besagtes Menue, verursacht mir itoa nach genau neun Tasterzyklen ein Reset und es wird auch keine Änderung der uint8-Zahl angezeigt. Hier mal die Routine was abgespeckt fürs Menue: ExIvOn ist volatile uint8_t und wird in get_ExIv_EEdata() mit dem eeprom gefüllt. Eine Kontrolle des Integer brauch ich nicht, da die 255 und der Überlauf gewollt wären. void Menue_Ex_IV(void) { get_ExIv_EEdata(); STHM_yn = 0; //Auswahlschalter On/Off 0 = On lcd_command(0x0C); //Cursor löschen lcd_command(0x01); //Clear Display lcd_pos(0,0); lcd_text( (u8*) "Ex Interval:"); lcd_pos(1,9); lcd_text( (u8*) "ON: "); //Minuten lcd_pos(1,13); volatile char EXOnSekAsk[4]; itoa(ExIvOn,EXOnSekAsk,10); lcd_text((u8*)EXOnSekAsk); lcd_pos(1,15); lcd_command(0x0F); //Cursor setzen } Hier mal der Code der Tasterroutine: switch(STHM_yn){ default: STHM_yn = 0; break; case 0: ExIvOn++; lcd_pos(1,13); volatile char EXOnSekAsk[10]; itoa(ExIvOn,EXOnSekAsk,10); lcd_text((u8*)EXOnSekAsk); lcd_pos(1,15); break; case 1: // kommt später break; } Mein Prog verursacht keine Fehler oder Warnungen beim Compilieren. Kommentiere ich itoa in der Tasterabfrage aus, zählt sie ExIvOn auch hoch. MIT itoa wird ( sobald ich von wo anders aus das Menue aufruf ) nach 9 Zyklen ein Reset ausgelöst und itoa auch scheinbar garnicht abgearbeitet. Optimierung -00 kann und will ich mir nicht leisten, weil mein Prog sonst nicht inne Flash passt unds hilft auch nich ab. Wie im QT zu sehen hab ich schon alles mögliche volatilisiert g aber hilft nix:( Bitte helft mir. Wie kann dieses Verhalten auftreten? Beim einen Mal korrekt, beim anderen mal ERROR?
Gast
#1975441
> Ich habe ein Menue,
mhhhh .... legger ^^
Gast
#1975480
Matthias T. schrieb: > QT zu sehen hab ich schon alles mögliche volatilisiert Alle Volatiles die ich oben sehe sind falsch. Versuch lieber zu verstehen, was volatile genau macht, und setz es dann "richtig" ein. Als zweite Stufe: Verstehen, warum volatile zwar hilft, aber eigentlich doch nicht "Das Richtige"™ ist, und stattdessen mit Atomic_blocks und Memory barriers arbeiten. Zum Problem: Ich vermute einen Überlauf. Entweder der Stack ist zu klein, oder der buffer "EXOnSekAsk[4];"
Gast
#1975485
Schorsch schrieb: > klein, oder der buffer "EXOnSekAsk[4];" Zur Erklärung: Du verwendest itoa, das ist für Signed Integers. d.H. aus deinem uin8_t wird bei der Parameterübergabe ein (auch gerne negativer) int. und "-100\0" passt nicht mehr in die 4 Characters des Buffers.
Dank dir Schorsch! Das Volatile versteh ich soweit ich auch die Controllerstruktur verstehe ( und das noch nicht so ganz! ) Allerdings vermutete ich eine Rationalisierung des Optimierers und versuchte so den Compiler daran zu hindern, Code anders zu interpretieren als ich es vorsah. Deshalb die volatiles und es hat ja auch nix geändert. Warum nur falsch gesetzt? daran hätte es doch liegen können, wenn der Compiler die Variablen hätte erst im Zwischenspeicher abgelegt und so der unkontrollierten Manipulation freigegeben. Wo hätten die volatiles denn Sinn? Das mit dem Stack werd ich gleich mal testen, obwohl ExIvOn nie >255 und kleiner als 0 sein kann ( uint8 halt ) und daher EXOnSekAsk[4] auch nur zum einen positiv und zum anderen nicht überlaufen sein kann. leider versteh ich von Atomic_blocks und Memory barriers noch nix. wenn es aber dem Prob dienlich ist werd ich mich daran setzen. Mein Verständnis kommt aus der PC-Programmierung und tut sich daher bissi was schwer mit SRAM Register, Flag und dergleichen. Man lernt! das mit itoa und unsigned ist mir schon klar, nur w.o. beschrieben kann der Wert von EXOnSekAsk nicht außerhalb 0-255 liegen...meines Wissens! aber daaaanke erstmal ich bin hier am zweifeln:(
Gast
#1975519
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
> > Bitte helft mir. 1. raus mit dem volatile. Ist nur wichtig, wenn du nicht direkt drauf zugreifst bzw. der Compiler die Verwendung nicht erahnen kann. 2. keine Magic Numbers. Gewöhn dir mal
1 | |
en. 3. ein array ist 4, eins 10 gross. Hmm?? Mach ein globales
1 | |
und fertich. Ist auch besser, und du sparst sogar 4 (nein, 10) Bytes RAM. Ausserdem:
1 | |
Vielleicht auch
1 | |
benutze kein itoa. VG, /th.
klasse - danke! hab ich geändert. nur leider der Fehler bleibt:( Die "Magic Number" ist "Schnicklschmack" und kann ich später sicher anpassen. Ich versteh ja, das es ins Dec wandelt. Und wie bitte soll ich ohne itoa arbeiten? zumal es beim direkten ansteuern ( noch vor der while(1) ) funkt?! übrigens...das itoa wird abgearbeitet (laut neuester Tests;). Nur verursacht genau das den Absturz?! verbeug
Gast
#1975570
Hi, sry, zu schnell getippt, ich meinte: ICH verwende kein itoa() :-) hast mal geschaut, ob itoa den string auch terminiert? VG, /th.
Gast
#1975571
> und kann ich später sicher anpassen.
macht man nie **grins**
Gast
#1975577
Matthias T. schrieb: > übrigens...das itoa wird abgearbeitet (laut neuester Tests;). Du hast gelesen, was ich dir oben geschrieben hab? itoa ist FALSCH. Du brauchst utoa. Das ist nämlich extra für Unsigned Variablen gedacht, wie es dein uint8_t ist.
es gibt mir den wert ( ASCII ) aufs DISPLAY und zeigt mir eigene Zeichen aus meiner ASCII-Tabelle an, die den Werten 0x00-0x09 entsprechen. Danach - also nach 9 inkrements resetet er. Über lcd_text ist aber gewährleistet, dass der String auch terminiert sein muss. Sonst käme ja der ganze Speicher aufs Display.
das mit utoa und itoa ist mir klar. nur ändert es am Ergebnis leider nix!
Und dein neuer, geänderter Code sieht jetzt wie aus?
PS. Deine lcd_text Funktion ist falsch definiert. Die sollte keinen u8* übernehmen, sondern einen ordinären char*
So - gelöst ******breitgrins********** hab die char EXOnSekAsk[4]; laut thorstendb mal global gemacht und alles funzt. Sparen kann ich daran allerdings nicht. die Variante lokal hat die Vars ja nach beenden immer wieder aufgelöst und nun nich mehr. Warum nun der Fehler behoben ist...ich würde es Euch gern sagen; Aber weiss es auch nicht. Danke aller Hilfe eurerseits!
Matthias T. schrieb: > So - gelöst ******breitgrins********** > > hab die char EXOnSekAsk[4]; laut thorstendb mal global gemacht und alles > funzt. Sieht nur so aus. Du hast das eigentliche Problem höchst wahrscheinlich nicht behoben, sondern nur an eine andere Stelle verfrachtet. > Sparen kann ich daran allerdings nicht. die Variante lokal hat > die Vars ja nach beenden immer wieder aufgelöst und nun nich mehr. > > Warum nun der Fehler behoben ist...ich würde es Euch gern sagen; Aber > weiss es auch nicht. Und genau ds ist das bedenkliche an der Situation.
Gast
#1975613
Wieviel Platz hast du am Stack noch frei? geht sich das genau um das
Byte nicht mehr aus, wenn das "innere" utoa ein char mehr schreiben muss
("9" => "10")
MAch mal ein paar bytes mehr platz im Ram, z.B. duch kürzen des Strings1 | |
in "ExI" o.Ä. Saubere Lösung: pgmspace.h, PSTR, lcd_text_P.
global: uint8_t ExIvOff; unsigned char EXOnSekAsk[4]; Menuecode: get_ExIv_EEdata(); STHM_yn = 0; //Auswahlschalter On/Off 0 = On lcd_command(0x0C); //Cursor löschen lcd_command(0x01); //Clear Display lcd_pos(0,0); lcd_text( (u8*) "Ex Interval:"); lcd_pos(1,9); lcd_text( (u8*) "ON: "); //Minuten lcd_pos(1,13); utoa(ExIvOn,EXOnSekAsk,10); lcd_text((u8*)EXOnSekAsk); Tastercode: ExIvOn++; lcd_pos(1,13); utoa(ExIvOn,EXOnSekAsk,10); lcd_text((u8*)EXOnSekAsk); lcd_pos(1,15); ist natürlich nur der heilwegs relevante Text!
Schorsch schrieb: > Wieviel Platz hast du am Stack noch frei? geht sich das genau um das > Byte nicht mehr aus, wenn das "innere" utoa ein char mehr schreiben muss > ("9" => "10") > > MAch mal ein paar bytes mehr platz im Ram, z.B. duch kürzen des Strings >
1 | |
2 | |
> in > "ExI" o.Ä. > > Saubere Lösung: pgmspace.h, PSTR, lcd_text_P. genau, PROGMEM für diese Konstanten verwenden, dann landen die im Flash. Dann ggf. den Pointer drauf holen und weiterverwenden: char *pText = .... Strings sind - wie mein Vorredner schon sagte - immer (char *). VG, /th.
AVR Memory Usage ---------------- Device: atmega32 Program: 14596 bytes (44.5% Full) (.text + .data + .bootloader) Data: 435 bytes (21.2% Full) (.data + .bss + .noinit) EEPROM: 16 bytes (1.6% Full) (.eeprom) Mit - im Stack platz machen - kenne ich mich noch nicht aus. Was es ist und wie er funkt weiß ich heilwegs. Aber wie lese ich den Stand des Stack zur Runtime aus?
Random ... schrieb: > Strings sind - wie mein Vorredner schon sagte - immer (char *). ich verwende Peter F.s LCD-Routinen und ( ohne es zu ändern ) die verlangen bei lcd_text ein u8 ??!
Matthias T. schrieb: > Data: 435 bytes (21.2% Full) > (.data + .bss + .noinit) wenn da nicht exzessiv große Arrays am Stack allokiert werden, ist der Speicher kein Problem
Random ... schrieb: > genau, PROGMEM für diese Konstanten verwenden, dann landen die im Flash. > Dann ggf. den Pointer drauf holen und weiterverwenden: > char *pText = .... joi - da bin ich an nen Fachmann geraten ;) Keeeeine Ahnung im Mom wovon du sprichst. Aber ich verfolge es weiter!
Gast
#1975638
Matthias T. schrieb: > Aber wie lese ich den Stand des > Stack zur Runtime aus? Gibts ein kleines C-Schnippselchen für, z.B. in diesem Thread: Beitrag "Compilerfehler bei mem-check"
Matthias T. schrieb: > Random ... schrieb: >> Strings sind - wie mein Vorredner schon sagte - immer (char *). > > ich verwende Peter F.s LCD-Routinen und ( ohne es zu ändern ) die > verlangen bei lcd_text ein u8 ??! Das kann ich mir nicht wirklich vorstellen. Schon alleine deswegen, weil die entsprechende Routine beim Peter Fleury
1 | |
2 | |
3 | |
4 | |
heißt und nicht lcd_text
ups
Matthias T. schrieb: > global: > uint8_t ExIvOff; > utoa(ExIvOn,EXOnSekAsk,10); > ist natürlich nur der heilwegs relevante Text! Glaub ich nicht. Die Variablen heißen ganz anders. Poste ALLES Dein Code ist ein einziger Saustall! > Die "Magic Number" ist "Schnicklschmack" und kann ich später > sicher anpassen. Das sagen sie immer. Hinten nach, hinten nach Nur eigenartigerweise sind es immer genau die Progammierer mit dem scheuslichsten Code, die die meisten Fehler haben.
Matthias T. schrieb: > global: > uint8_t ExIvOff; > unsigned char EXOnSekAsk[4]; Bei derartigen Arrays definiert man die Länge nie auf 'passt genau', sondern man lässt sich immer einen kleinen Überhang, damit sich Fehler nicht gleich in Desaster auswirken.
ah - ok! das kann ich berücksichtigen. Danke! geb ich da besser mehr Bytes ( also zb [10]) oder gleich []?
Matthias T. schrieb: > ah - ok! das kann ich berücksichtigen. Danke! > > geb ich da besser mehr Bytes ( also zb [10]) oder gleich []? Du brauchst ein C-Buch Wie willst du denn ein Array mit[] definieren? In C muss alles eine definierte Größe haben. Von alleine wächst da gar nichts.
Karl heinz Buchegger schrieb: > Du brauchst ein C-Buch > > Wie willst du denn ein Array mit[] definieren? > In C muss alles eine definierte Größe haben. Von alleine wächst da gar > nichts. "Jetzt lerne ich C" S.210 Z.007 ( mit 1 beginnend ) ISBN 3-8272-5361-6 Verlag Markt&Technik. Zugegeben etwas älter und ob es auf µC funkt weiß ich auch nicht.
Matthias T. schrieb: > Karl heinz Buchegger schrieb: >> Du brauchst ein C-Buch >> >> Wie willst du denn ein Array mit[] definieren? >> In C muss alles eine definierte Größe haben. Von alleine wächst da gar >> nichts. > > "Jetzt lerne ich C" S.210 Z.007 ( mit 1 beginnend ) ISBN 3-8272-5361-6 > Verlag Markt&Technik. Zugegeben etwas älter und ob es auf µC funkt weiß > ich auch nicht. OK. Jetzt musst du es nur noch durcharbeiten :-)
ich will ja hier kein konfrogespräch entfachen und mein text ist ( erstrecht ) insgesamt sicher lausig. Es gibt VIELES was ich noch nicht weiß und sich als Fehler herausstellen wird. Aber hast du auch vor 15 Monaten begonnen und weißt jetzt alles? Mir geht es um lernen und das geht nur nach und nach. Meines Wissens hast Du Karl Heinz mir vor nem halben Jahr schonmal mit meinem LCD geholfen und ich bin dir sehr dankbar, denn auch da hab ich ja viel gelernt. Hier soll es genau so sein. C hab ich gelesen ( auch in Ruhe ) Aber die Praxis muss noch wachsen. Hinzu kommen ja die ganzen Controllerarchitekturen, Datenblätter u.u. Muss ich auch alles lernen nach und nach. bitte immer sachlich bleiben:)
Matthias T. schrieb: > Random ... schrieb: >> genau, PROGMEM für diese Konstanten verwenden, dann landen die im Flash. >> Dann ggf. den Pointer drauf holen und weiterverwenden: >> char *pText = .... > > joi - da bin ich an nen Fachmann geraten ;) Keeeeine Ahnung im Mom wovon > du sprichst. Aber ich verfolge es weiter! Naja, genau das, was da steht. Der AVR ist ein Harvard-Modell, d.h. er hat getrennte Busse für Befehle (Flash) und Daten (SRAM). Konstante Strings kann man aus Platzgründen am besten im Flash ablegen. Wenn man auf diese Strings zugreifen muss, holt man sich die in einen char pointer, und übergibt diesen an print....(was auch immer). Dazu braucht man bestimmte Funktionen, die den Zugriff auf den Flash umlenken. ARMs / Cortex Prozessoren z.B. basieren ebenfalls auf einem Harvard-Modell, aber da bei 32Bit (4Gig) mehr als genug Adressen da sind, ist der Flash mit in den Datenbereich gemapped, kurzum: der ganze Adressraum ist linearisiert ('Von Neumann' Programmiermodell). Dort braucht man diese Konstrukte nicht. Der AVR ist aber nur 8Bit (16Bit Adressen?), und daher muss man diese Klimmzüge machen. Hoffe, ich hab mich jetzt nirgendwo auf die Schnelle vertan :-) Weiterhin: Strings sind stets mit '\0' (DEC 0) terminiert, das kennzeichnet das Stringende. Bedeutet, dass in 'char text[10]' neun Zeichen plus '\0' passen, mit dem Index von [0...9]. Die Array-Klammern ohne Grössenangabe kann man zum Init eines Strings verwenden, z.B. char text[] = "Hallo, Welt" oder besser: char *text = "Hallo, Welt" Dabei wird Speicher für den String angelegt, und die Adresse des Strings im pointer 'text' gespeichert. Will man (unsauber) diesen Text ändern, braucht man die Länge. VG, /th.
vielen Dank! Ich werde mich damit beschäftigen!
Karl heinz Buchegger schrieb: > Bei derartigen Arrays definiert man die Länge nie auf 'passt genau', > sondern man lässt sich immer einen kleinen Überhang, damit sich Fehler > nicht gleich in Desaster auswirken. Das ist Unsinn. Besser ist immer, man weiß, was man tut. Und wenn ich weiß, daß ich max 30 Byte benötige, dann nehme ich auch genau 30. Mehr bringt nämlich genau 0,nix. Hier mal ein Beispiel für einen Puffer für eine 32Bit-Zahl:
1 | |
Peter
Peter Dannegger schrieb: > Karl heinz Buchegger schrieb: >> Bei derartigen Arrays definiert man die Länge nie auf 'passt genau', >> sondern man lässt sich immer einen kleinen Überhang, damit sich Fehler >> nicht gleich in Desaster auswirken. > > Das ist Unsinn. Ja. Bis dann in 3 Monaten man auf die Idee kommt, dass man da noch einen kleinen Text davor haben will. Alles schon gesehen, alles schon gehabt, schon öfter drauf reingefallen. > Besser ist immer, man weiß, was man tut. Als ob Neulinge das im Regelfall tun. > Und wenn ich weiß, daß ich max 30 Byte benötige, dann nehme ich auch > genau 30. Mehr bringt nämlich genau 0,nix. Wenn ich einen globalen Buffer zur Textwandlung habe, dann mach ich den nicht auf Knirsch, denn irgendwann in nächster Zeit fällt man nämlich drauf rein, dass 3 Zeichen bei einer int-Wandlung zu wenig ist. Und sei es nur, weil die Zahl aus irgendeinem Grund tatsächlich mal größer als 255 wird. Ist auch im Regelfall völlig wurscht, wenn ich dem noch 7 Bytes dazuspendiere. Das kostet nichts. 2 Stunden Fehlersuche wegen so einem Blödsinn hingegen kosten Geld. Nennt sich defensives Programmierern.
Karl heinz Buchegger schrieb: > Wenn ich einen globalen Buffer zur Textwandlung habe, dann mach ich den > nicht auf Knirsch, denn irgendwann in nächster Zeit fällt man nämlich > drauf rein, dass 3 Zeichen bei einer int-Wandlung zu wenig ist. Ist es ja auch. Du brauchst für 16Bit genau:
1 | |
Peter
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.