Forum: Mikrocontroller und Digitale Elektronik uC führt Code nicht aus, wenn in if-Abfrage zuvor zu viel Code ist?


von Jonathan K. (burgerohnealles)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin momentan dabei, einen Programm für ein uC zu schreiben, dass 
Daten von einer IR-Fernbedienung empfängt und diese auswertet (ein 
PIN-Code muss eingeben werden, wenn dieser richtig ist, soll eine LED 
angehen). Das funktionierte soweit, bis ich das Program so erweitert 
habe, dass man die PIN ändern kann. Seit dem wird die LED je nach Status 
nicht mehr umgeschaltet. Wenn ich einen Teil des Codes aus der 
if-Abfrage zuvor wegmache, funktioniert wieder alles. Welchen Teil ich 
weg mache (den neuen, um die PIN zu ändern, oder den alten, der die 
PIN-Eingabe erkennt), ist egal. Warum funktioniert das nicht, wenn der 
ganze Code da ist?

Und falls das jemand wissen will, welche IR-Lib das ist: 
http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html 
-> daraus die nötigen Funktionen um IR-Daten des NEC-Protokolls zu lesen 
(und für uC umgeschrieben, da diese Lib eigentlich für den Arduino ist).

Und in code.h sind nur Definitionen für die einzelnen Tasten der 
verwendeten Fernbedienung.

EDIT: Also so wie der Code angehängt ist, schafft es der ATtiny84A bis 
zu dem Punkt, wo die LED gesteuert wird. Wenn ich aber den 
auskommentierten Teil wieder aktiviere, gehts net mehr.

EDIT2:
1
  while (1) {
2
    if (test = irrecv_decode(&res)) {
3
      if (res.decode_type != NEC || res.value == REPEAT) {
4
        irrecv_resume();
5
        continue;
6
      }
7
      
8
      
9
      //*
10
      if (state & STATE_ENTER_NEW_CODE) {
11
        if (res.value == KEY_B) {
12
          if (new_code_pos >= CODE_MIN_LEN) {
13
            code_len = new_code_pos;
14
            for (uint8_t i=0; i<code_len; i++)
15
              code[i] = new_code[i];
16
          
17
            eeprom_w8(0, code_len);
18
            for (uint8_t i=0; i<code_len; i++)
19
              eeprom_w32(1+sizeof(uint32_t)*i, code[i]);
20
          }
21
          
22
          new_code_pos = 0;
23
          state &= ~STATE_ENTER_NEW_CODE;
24
        } else if (res.value == KEY_POWER || new_code_pos == CODE_MAX_LEN) {
25
          state &= ~STATE_ENTER_NEW_CODE;
26
        } else {
27
          new_code[new_code_pos++] = res.value;
28
        }
29
      } else {
30
        //*
31
        if (res.value == code[code_pos]) {
32
          if (++code_pos == code_len) {
33
            code_pos = 0;
34
            state |= STATE_CODE_OK;
35
          }
36
        } else {
37
          code_pos = 0;
38
        }
39
        //*/
40
        
41
        //*
42
        if (res.value == KEY_POWER)
43
          state &= ~STATE_CODE_OK;
44
        else if (res.value == KEY_B && (state & STATE_CODE_OK))
45
          state |= STATE_ENTER_NEW_CODE;
46
        //*/
47
      }
48
      
49
      
50
      irrecv_resume();
51
    }
52
    
53
    // so würde ich hier nie ankommen
54
    PORTB |= (1<<1);
55
    delay_ms(test*500);
56
    PORTB &= ~(1<<1);
57
    delay_ms(50);
58
    
59
    /*
60
    if (state & STATE_CODE_OK)
61
      PORTB |= (1<<1);
62
    else
63
      PORTB &= ~(1<<1);
64
    //*/
65
  }
1
  while (1) {
2
    if (test = irrecv_decode(&res)) {
3
      if (res.decode_type != NEC || res.value == REPEAT) {
4
        irrecv_resume();
5
        continue;
6
      }
7
      
8
      
9
      //*
10
      /*if (state & STATE_ENTER_NEW_CODE) {
11
        if (res.value == KEY_B) {
12
          if (new_code_pos >= CODE_MIN_LEN) {
13
            code_len = new_code_pos;
14
            for (uint8_t i=0; i<code_len; i++)
15
              code[i] = new_code[i];
16
          
17
            eeprom_w8(0, code_len);
18
            for (uint8_t i=0; i<code_len; i++)
19
              eeprom_w32(1+sizeof(uint32_t)*i, code[i]);
20
          }
21
          
22
          new_code_pos = 0;
23
          state &= ~STATE_ENTER_NEW_CODE;
24
        } else if (res.value == KEY_POWER || new_code_pos == CODE_MAX_LEN) {
25
          state &= ~STATE_ENTER_NEW_CODE;
26
        } else {
27
          new_code[new_code_pos++] = res.value;
28
        }
29
      } else {*/
30
        //*
31
        if (res.value == code[code_pos]) {
32
          if (++code_pos == code_len) {
33
            code_pos = 0;
34
            state |= STATE_CODE_OK;
35
          }
36
        } else {
37
          code_pos = 0;
38
        }
39
        //*/
40
        
41
        //*
42
        if (res.value == KEY_POWER)
43
          state &= ~STATE_CODE_OK;
44
        else if (res.value == KEY_B && (state & STATE_CODE_OK))
45
          state |= STATE_ENTER_NEW_CODE;
46
        //*/
47
      //}
48
      
49
      
50
      irrecv_resume();
51
    }
52
    
53
    // das geht wiederum
54
    PORTB |= (1<<1);
55
    delay_ms(test*500);
56
    PORTB &= ~(1<<1);
57
    delay_ms(50);
58
    
59
    /*
60
    if (state & STATE_CODE_OK)
61
      PORTB |= (1<<1);
62
    else
63
      PORTB &= ~(1<<1);
64
    //*/
65
  }


Danke im Vorraus
burgerohnealles

: Bearbeitet durch User
von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Gibt es vielleicht zu wenig Stack?

von Jonathan K. (burgerohnealles)


Lesenswert?

Ah, und wenn ich alles "aktiviere" (nicht auskommentiere), dann hängt es 
von folgendem Teil ab, ob der uC bis zu dem Teil, wo die LED gesteuert 
wird, ankommt.
1
        if (res.value == KEY_POWER)
2
          state &= ~STATE_CODE_OK;
3
        else if (res.value == KEY_B && (state & STATE_CODE_OK))
4
          state |= STATE_ENTER_NEW_CODE;

Aber hier wird nicht irgendwie neuer Speicher gebraucht, weshalb der uC 
"kein Bock" mehr hat ..

Wo ist der Fehler? Oder mein Denkfehle?

von Georg G. (df2au)


Lesenswert?

Lass es doch einfach mal im Simulator laufen, Schritt für Schritt. Dann 
siehst du, wo es nicht nach deinen Wünschen weiter geht (und warum).

von Gerti (Gast)


Lesenswert?

Lieblingsbeschäftigung sich an einem Sonntagnachmittag durch einen 
unkommentierten Code durchzuwurschteln.

von Thomas E. (thomase)


Lesenswert?

Vielleicht solltest du Bit0 in state auch mal setzen, anstatt es immer 
nur zu löschen.
Dann würde diese Bedingung:
> if (res.value == KEY_B && (state & STATE_CODE_OK))
> state |= STATE_ENTER_NEW_CODE;

auch einmal true werden und ermöglichen, daß Bit1 in state gesetzt wird, 
damit die if-Bedingung
> if (state & STATE_ENTER_NEW_CODE)

ebenfalls mal true ist.

mfg.

von Jonathan K. (burgerohnealles)


Lesenswert?

Georg G. schrieb:
> Lass es doch einfach mal im Simulator laufen, Schritt für Schritt. Dann
> siehst du, wo es nicht nach deinen Wünschen weiter geht (und warum).

Eigentlich gute Idee, aber ich kann das ankommende IR-Signal nicht 
simulieren .. wenn ich den Code so ändere, dass die Funktion 
"irrecv_decode" immer einen bestimmten Wert zurückgibt funktioniert es 
wieder (Code dahinter wird ausgeführt) -> Simulaion sinnlos .. :|


Thomas Eckmann schrieb:
> Vielleicht solltest du Bit0 in state auch mal setzen

Wird gemacht, wenn der PIN-Code richtig eingeben wurde (momentan 
auskommentiert). Aber eigentlich ist das egal, es geht darum, dass wenn 
anscheinend "zu viel" Code in der if-Abfrage drin ist, das hintendran 
nicht mehr ausgeführt wird. Mometan ist dieser Code "hintendran" so:
1
    PORTB |= (1<<1);
2
    delay_ms(test*500);
3
    PORTB &= ~(1<<1);
4
    delay_ms(50);
5
    
6
    /*
7
    if (state & STATE_CODE_OK)
8
      PORTB |= (1<<1);
9
    else
10
      PORTB &= ~(1<<1);
11
    //*/

.. also egal welchen Wert state hat, die LED sollte blinken (sofern ein 
IR-Signal dekodiert werden konnte und da weiß ich, dass es 
funktioniert). Oder steh ich grad so richtig aufm Schlauch !??

: Bearbeitet durch User
von Jonathan K. (burgerohnealles)


Angehängte Dateien:

Lesenswert?

Also dieser "Test", den ich vorher gemacht hatte, war nicht soo 
sinnvoll. Aber was ist jetzt das Problem? Ich hab mal diese ganzen alten 
"Test" aus dem Code rausgemacht und ein paar Kommentare hinzugefügt.

Mein Problem jetzt ist in dem Code als Kommentar (der längste von allen) 
beschrieben. Was ist da falsch?

von Achim K. (aks)


Lesenswert?

Ergänze mal für einen Test
1
state |= STATE_ENTER_NEW_CODE;

in
1
if (++code_pos == code_len) {
2
// pin code ok
3
code_pos = 0;
4
state |= STATE_CODE_OK | STATE_ENTER_NEW_CODE; // just for test
5
}

ich würde mal tippen, es tut dann auch nicht mehr.
Obwohl der Code nicht mehr wurde, sondern nur eine Konstante sich 
geändert hat.

von Jonathan K. (burgerohnealles)


Lesenswert?

@aks
Das hab ich mal ausprobiert -> es ändert nichts.

Aber ich habe noch was getestet ... so langsam versteh ich GAR NICHTS 
mehr!
Also:

In meinem "neuen Code" ist einfach das
1
          if (res.value == KEY_POWER)
2
            state &= ~STATE_CODE_OK;
3
          else if (res.value == KEY_B && (state & STATE_CODE_OK)) // pin entered and key for new pin code pressed ?
4
            state |= STATE_ENTER_NEW_CODE;
durch folgendes ersetzt:
1
          if (res.value == KEY_POWER)
2
            state &= ~STATE_CODE_OK;
3
          else if (res.value == KEY_B && (state & STATE_CODE_OK)) {
4
            state |= STATE_ENTER_NEW_CODE;
5
            //for(;;); // wenn ich diese zeile auskommentiere, geht es nicht; sonst schon !!?????
6
          }

...... in dem Kommentar steht eigentlich alles drin ...
Wenn ich diese Endlosschleife (habe einfach irgendwas genommen) 
miteinbaue funktioniert das Programm einwandfrei. Also PIN-Code wird 
erkannt, LED geht an, ich kann die LED mit dem Power-Button wieder 
ausschalten .. nur wenn ich den Knopf B drücke hängt der AVR .. logisch 
(wegen der Endlosschleife) ....
Aber wenn ich die Endlosschleife wegmache, geht wieder NIX !?? (LED geht 
nicht an)


WARUM !?? Ich versteh grad NICHTS mehr !??




EDIT: Ich hab mir gedacht, wenn es mit einer Endlosschleife hintendran 
geht, teste ichs mal mit einem NOP-Befehl .. also:
1
          if (res.value == KEY_POWER)
2
            state &= ~STATE_CODE_OK;
3
          else if (res.value == KEY_B && (state & STATE_CODE_OK)) {
4
            state |= STATE_ENTER_NEW_CODE;
5
            asm volatile ("nop");
6
            //for(;;); // wenn ich diese zeile auskommentiere, geht es nicht; sonst schon !!?????
7
          }

.. funktioniert aber leider wieder nicht ...

: Bearbeitet durch User
von kopfkratzer (Gast)


Lesenswert?

kopfkratz
Ganz ehrlich statt nun solange im Code herumzufummeln bis entweder was 
halbwegs geht oder gar nicht mehr, setz Dich hin und zeichne Dir eine 
Statemachine auf.
Dann selbige mit switch/case umsetzen und passende Funktionen für das 
Lernen und Auswertung schreiben.
Du hast ja aktuell folgende Zustände:
LERNEN -> empfangene PINs in EEPROM ablegen
AUSWERTEN -> empfangene PINs mit EEPROM vergleichen
Welche Übergänge hast Du zwischen diesen Zuständen und welche Funktionen 
müßtest Du implementieren ?
Jetzt machst Du erstmal eine Auszeit und schaust morgen Abend nochmal 
drüber wenn Du keine Statemachine aufsetzen willst.

von Jonathan K. (burgerohnealles)


Angehängte Dateien:

Lesenswert?

Ich will einfach nur wissen warum ein uC etwas bestimmtes nur dann 
macht, wenn hinter einer Anweisung in einer if-Abfrage, die aufgrund 
ihrer Bedingung nicht mal "ausgeführt" wird, eine Endlosschleife ist.

WARUM?? Steht ich irgendwie total aufm Schlauch oder wie?


EDIT: Bei dem Code selbes Problem ..

: Bearbeitet durch User
von kopfkratzer (Gast)


Lesenswert?

Jonathan K. schrieb:
> Ich will einfach nur wissen warum ein uC etwas bestimmtes nur dann
> macht, wenn hinter einer Anweisung in einer if-Abfrage, die aufgrund
> ihrer Bedingung nicht mal "ausgeführt" wird, eine Endlosschleife ist.
>
> WARUM?? Steht ich irgendwie total aufm Schlauch oder wie?

Bist Du Dir sicher das die Endlosschleife nicht ausgeführt wird ?
Bei vielen verschachtelten ifs kommt es schon mal vor das eine 
Klammerung sinnvoller wäre, von switch mal ganz abgesehen.
Aktuell bist Du nicht mehr in der Lage objektiv das Problem zu lösen, 
z.B. via Debugger.
Daher mein Rat einfach aufzuhören, Dir einen schönen Abend zu machen und 
wenn Du morgen dann nicht mehr irritiert und genervt bist das ganze 
nochmal Punkt für Punkt durchzugehen.
Und mein Vorschlag mit der Statemachine kommt auch nicht von ungefähr 
;-)
Ums mal direkt zu sagen: "GAAAAAANZ RUHIG Brauner !" ;-)
Mach was komplett anderes und wenn Du dann wieder unten bist gehe es 
systematisch an ...

von Jonathan K. (burgerohnealles)


Angehängte Dateien:

Lesenswert?

kopfkratzer schrieb:
> Bist Du Dir sicher das die Endlosschleife nicht ausgeführt wird ?
> Bei vielen verschachtelten ifs kommt es schon mal vor das eine
> Klammerung sinnvoller wäre, von switch mal ganz abgesehen.
> Aktuell bist Du nicht mehr in der Lage objektiv das Problem zu lösen,
> z.B. via Debugger.

Also nochmal: Die Bedinung "res.value == KEY_B && code_ok" ergibt 
false!! Weder der gesendete "IR-Code" ist die Taste B und der Code muss 
dafür ja auch richtig eingeben sein. Also der Teil wird garantiert nicht 
ausgeführt. Das habe ich auch schona anders getestet. Ich habe den uC so 
programmiert, dass wenn "enter_new_code" true ist, eine LED angeht und 
der uC in einer Endlosschleife landet. Dies ist aber nicht passiert; 
daher bin ich mir zu 100% sicher, dass dieser Teil nicht ausgeführt 
wird. Deshalb wunderts mich, dass dieser Teil das ganze Programm 
beinflusst. Und ich wollte das ganze ja simulieren, aber dafür müsste 
ich die Funktion "irrecv_decode" so verändern, dass sie den PIN-Code 
richtig zurückgibt .. dann hört der Code aber nicht so auf so arbeiten, 
wie er es machen würde, wenn diese eine "for(;;);"-Schleife fehlt ..

EDIT: Und wenn dieser Code ausgeführt werden würde, dann würde der uC ja 
bereits bei der PIN-Code-Eingabe hängen bleiben (wegen der 
Endlosscheleife) ..

Nochmal die Frage von vorher: Warum macht ein uC etwas bestimmtes nur 
dann, wenn hinter einer Anweisung in einer if-Abfrage, die aufgrund
ihrer Bedingung nicht mal "ausgeführt" wird, eine Endlosschleife ist???



EDIT2: Was sagt ihr dazu (siehe neue Kommentare im Code)?

: Bearbeitet durch User
von kopfkratzer (Gast)


Lesenswert?

Jonathan K. schrieb:
> kopfkratzer schrieb:
>> Bist Du Dir sicher das die Endlosschleife nicht ausgeführt wird ?
>> Bei vielen verschachtelten ifs kommt es schon mal vor das eine
>> Klammerung sinnvoller wäre, von switch mal ganz abgesehen.
>> Aktuell bist Du nicht mehr in der Lage objektiv das Problem zu lösen,
>> z.B. via Debugger.
>
> Also nochmal: Die Bedinung "res.value == KEY_B && code_ok" ergibt
> false!! Weder der gesendete "IR-Code" ist die Taste B und der Code muss
> dafür ja auch richtig eingeben sein. Also der Teil wird garantiert nicht
> ausgeführt. Das habe ich auch schona anders getestet. Ich habe den uC so
> programmiert, dass wenn "enter_new_code" true ist, eine LED angeht und
> der uC in einer Endlosschleife landet. Dies ist aber nicht passiert;
> daher bin ich mir zu 100% sicher, dass dieser Teil nicht ausgeführt
> wird. Deshalb wunderts mich, dass dieser Teil das ganze Programm
> beinflusst. Und ich wollte das ganze ja simulieren, aber dafür müsste
> ich die Funktion "irrecv_decode" so verändern, dass sie den PIN-Code
> richtig zurückgibt .. dann hört der Code aber nicht so auf so arbeiten,
> wie er es machen würde, wenn diese eine "for(;;);"-Schleife fehlt ..
>
> EDIT: Und wenn dieser Code ausgeführt werden würde, dann würde der uC ja
> bereits bei der PIN-Code-Eingabe hängen bleiben (wegen der
> Endlosscheleife) ..
>
> Nochmal die Frage von vorher: Warum macht ein uC etwas bestimmtes nur
> dann, wenn hinter einer Anweisung in einer if-Abfrage, die aufgrund
> ihrer Bedingung nicht mal "ausgeführt" wird, eine Endlosschleife ist???

OK,
dann poste doch mal bitte Deinen aktuellen Code als Anhang.
Ich schau dann morgen Abend drüber, denn ich bin gerade auch nicht in 
der Lage objektiv Zeile für Zeile durchzugehen ;-)
Karl-Heinz ist wahrscheinlich im verdienten Urlaub ;-)
Achja und wie "simulierst" Du das Ganze denn eigentlich ?
Debug via LED ist OK, kannst Du das einfach erweitern, so das Du siehst 
in welchem Programmteil es hängen bleibt ?
Ansonsten kennst Du jemanden mit Hardwaredebugger bzw. kannst Du nicht 
einfach im "Simulator" die Variable beim Debuggen ändern ?
Oder Du nimmst meinen Vorschlag an und fängst komplett neu an mit einer 
Statemachine ...

von Achim K. (aks)


Lesenswert?

Und poste bitte ALLE Source Dateien!
Welche Toolchain benutzt Du?
Tritt das Problem umabhägig von der verwendeten "Optimierungsoption" 
auf?

Erfahrungsgemäß sind "solche Effekte" die Auswirkung von ganz anderen 
Stellen im Program :-). Auch wenn man denkt, das Problem "isoliert" zu 
haben und glaubt einen Compiler Bug gefunden zu haben, stellt es sich 
dann doch zu oft als Programmierfehler raus.

von Jonathan K. (burgerohnealles)


Lesenswert?

kopfkratzer schrieb:
> Achja und wie "simulierst" Du das Ganze denn eigentlich ?

Ich hatte vor das in SimulAVR zu simulieren ..


Achim K. schrieb:
> Tritt das Problem umabhägig von der verwendeten "Optimierungsoption"
> auf?

Danke für den Tip!! Hab zuerst net dran geglaubt, aber es hat mein 
Problem gelöst!!! Habe zuerst -Os und -O1 ausprobiert - selbes Ergebnis, 
wie vorher .. aber mit -O2 funktioniert es; auch wenn das ganze jetzt 
ein bisschen größer ist, es funktioniert!

Aber warum verhält sich ein Programm bei unterschiedlichen Optimierungen 
komplett anders? :O

von Achim K. (aks)


Lesenswert?

Jonathan K. schrieb:

> Aber warum verhält sich ein Programm bei unterschiedlichen Optimierungen
> komplett anders? :O

Wie "komplett anders" es ist, wird sich ja noch zeigen. Aber im Ernst:
Poste alle Source Dateien. Dann kann man sehen, wo es "kritisch ist".

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jonathan K. schrieb:
> Aber warum verhält sich ein Programm bei unterschiedlichen Optimierungen
> komplett anders? :O
Häufigstes Problem: du hast ein "volatile" vergessen und der Compiler 
optimiert anders...

von Karl H. (kbuchegg)


Lesenswert?

> Warum funktioniert das nicht, wenn der ganze Code da ist?

Weil du einen Programmfehler hast.
Vergiss bitte die Idee, dass dich der Compiler ärgern will und den 
Bedingungsteil in einem if nur bis zu einer bestimmten Code-größe in 
diesem if macht. Er tut es nicht.
Du hast einen Fehler im Programm - Punkt. So wie 99% aller anderer 
Programmierer, die den Compiler verantwortlich machen wollen. Natürlich 
kommt es vor, dass auch in einem Compiler Fehler enthalten sind. Ein 
Compiler ist schliesslich auch nur ein Programm. Aber die 
Wahrscheinlichkeit ist eher gering. Einen Compilerfehler fasst man erst 
ins Auge, wenn man genau weiß, welche gewisse Funktionalität nicht 
gegeben ist, was da eigentlich schief geht und wenn man keine Erklärung 
für dieses Verhalten im Code finden kann. Wobei es meistens speziell an 
letzterem scheitert - denn oft genug stellt sich heraus, dass der 
Compiler recht hat und nur das C Wissen des Programmierers nicht gut 
genug ist. So entstehen dann auch die 99% in denen der Compiler recht 
hat obwohl der Programmierer die Sache ganz anders sieht.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jonathan K. schrieb:
> Danke für den Tip!! Hab zuerst net dran geglaubt, aber es hat mein
> Problem gelöst!!!

Nein, Du hast Dein Problem nicht gelöst, Du hast es nur woanders hin 
verschoben. Durch die Änderung der Optimierung hat der Compiler Deinen 
Programmfehler (z.B. Überschreiben von Speicher, u.U. von Variablen) nur 
woanders hingelegt.

Wenn es nun augenscheinlich nicht mehr auftritt, ist die Chance groß, 
dass es nun woanders krachen wird. Und wenn Du gaaaaaanz viel Glück 
hast, ist der Fehler nun tatsächlich im gesamten Programmablauf 
irrelevant, weil Du zum Beispiel nun lediglich Speicher überschreibst, 
wo gerade keine Variablen gehalten werden.

So löst man aber keine Programmfehler-Probleme, denn man kommt damit 
nicht weit. Sobald Du irgendwann mal was änderst im Programm, ist ... 
schwuppdiewupp ... der Fehler wieder da und Du kannst von vorn anfangen.

Fazit: Augen-zu-und-durch beim Programmieren ist tödlich! Sei froh, dass 
Du den Fehler überhaupt reproduzieren kannst. Dann jage ihn denn auch!

von Jonathan K. (burgerohnealles)


Lesenswert?

Lothar Miller schrieb:
> Häufigstes Problem: du hast ein "volatile" vergessen und der Compiler
> optimiert anders...

Hmm, also die einzigste Variable, die in dem Interrupt-Handler 
"gebraucht" wird, ist "irparams". Da hab ich aber kein volatile 
vergessen .. und bei den anderen Variablen hab ich auch mal getestet 
überall ein volatile dazuzuschreiben, was nichts gebracht hat.


Achim K. schrieb:
> Poste alle Source Dateien.

Ist im Anhang.


Karl Heinz schrieb:
> Weil du einen Programmfehler hast.

Frank M. schrieb:
> Nein, Du hast Dein Problem nicht gelöst, Du hast es nur woanders hin
> verschoben.

Hmm, da habt ihr Recht .. das hatte ich mir auch schon irgendwie 
gedacht, wusste aber nicht wo der Fehler ist. Code ist im Anhang, wäre 
nett, wenn ihr mal gucken könnt ... momentan ist in dem Makefile die 
Option -O2 drin, um den Fehler zu reproduzieren, einfach "-O2" 
wegmachen; ich habe einen ATtiny84A (Fuses: L:0xE2; H:0xDF; E:0xFF) 
verwendet und als IR-Receiver TSOP31238.

von Jonas B. (jibi)


Lesenswert?

>Code ist im Anhang?

Wo?

von Jonas B. (jibi)


Lesenswert?

>if (irrecv_decode(&res)) { // decode
>      // hier "landet" man, wenn ein IR-Code empfangen wurde ....

Aber nur wenn du nicht hier unten dich in der Endlossschleife fängst, 
wie willst du hier jemals rauskommen?

>for(;;); // wenn ich diese zeile auskommentiere, geht es nicht; sonst schon 
>!!?????

Wenn du hier unten schon auf die Änderung eines flags wartest (was im 
interrupt gesetzt wird) musst du hier auch eine Prüfung darauf machen, 
einfach so empfängst du genau einmal einen code und hängst dann für 
immer in der for schleife du nase.

Gruß Jonas

: Bearbeitet durch User
von Hans (Gast)


Lesenswert?

Wahrscheinlich fehlt Dir hier

for (uint8_t i=0; i<code_len; i++)
              eeprom_w32(1+sizeof(uint32_t)*i, code[i]);
noch ein eeprom_busy_wait nach der Schleife

von Da D. (dieter)


Lesenswert?

Jonathan K. schrieb:
> und bei den anderen Variablen hab ich auch mal getestet
> überall ein volatile dazuzuschreiben, was nichts gebracht hat.

Meine Güte, wie oft denn noch?!? Programmieren tut man nicht durch 
blindes Rumexperimentieren, sondern man muss schon mitdenken und 
verstehen was man tut!

von Jonas B. (jibi)


Lesenswert?

>Meine Güte, wie oft denn noch?!? Programmieren tut man nicht durch
>blindes Rumexperimentieren, sondern man muss schon mitdenken und
>verstehen was man tut!

Das muss es noch üben, sonst hätte er sich auch nicht so ne Falle gebaut 
mit der for-schleife, ob das dann der letzte Fehler ist...

GRuß Jonas

von Jonathan K. (burgerohnealles)


Angehängte Dateien:

Lesenswert?

Jonas Biensack schrieb:
>>Code ist im Anhang?
>
> Wo?

Sorry hab ich vergessen.


Jonas Biensack schrieb:
>>if (irrecv_decode(&res)) { // decode
>>      // hier "landet" man, wenn ein IR-Code empfangen wurde ....
>
> Aber nur wenn du nicht hier unten dich in der Endlossschleife fängst,
> wie willst du hier jemals rauskommen?

Wie oft noch? In diese Endlosschleife kommt man erst gar nicht (weil man 
dazu 1. den PIN-Code richtig eingeben müsste und 2. dann noch eine 
bestimmte Taste drücken muss)!


Jonas Biensack schrieb:
>>if (irrecv_decode(&res)) { // decode
>>      // hier "landet" man, wenn ein IR-Code empfangen wurde ....
>
> Aber nur wenn du nicht hier unten dich in der Endlossschleife fängst,
> wie willst du hier jemals rauskommen?


Hans schrieb:
> Wahrscheinlich fehlt Dir hier
>
> for (uint8_t i=0; i<code_len; i++)
>               eeprom_w32(1+sizeof(uint32_t)*i, code[i]);
> noch ein eeprom_busy_wait nach der Schleife

In der Funktion eeprom_w32 ist doch ein eeprom_busy_wait!?


Da Dieter schrieb:
> Meine Güte, wie oft denn noch?!? Programmieren tut man nicht durch
> blindes Rumexperimentieren, sondern man muss schon mitdenken und
> verstehen was man tut!

Mir ist schon klar wozu z.B. volatile ist! Ich hatte mir auch schon 
gedacht, dass dieser "Test" nichts bringt. Ich hatte aber nur keine 
Ahnung wo der Fehler war, sodass ich so ziemlich alles (egal ob sinnvol 
oder nicht) ausprobiert hab. Sont weiß ich, wann ich z.B. volatile 
benutzen muss!

: Bearbeitet durch User
von kopfkratzer (Gast)


Lesenswert?

kopftisch
Code als tar.gz m(
OK da ich hier definitiv Lernresistenz sehe werde ich mir das nicht mehr 
antun.
Was das sinnvollste wäre habe ich schon oben gepostet, da es aber 
niemals nicht an dem "Ding" zwischen Stuhl und Tastatur liegen kann 
holen wir uns mal die neue Version 
"Jetzmachwasicheigentlichwillabernichtselberkann" ...
Besser wäre es natürlich wenn sich der OP mal hinsetzt und wirklich eine 
einfachste Statemachine daraus macht, die entweder den Status "LERNEN" 
oder den Status "ERKENNEN" hat.
Den IR Empfang braucht's für beides kann man also als eigene 
Funktion/Prozedur implementieren ...

von Hans (Gast)


Lesenswert?

Jonathan K. schrieb:
> In der Funktion eeprom_w32 ist doch ein eeprom_busy_wait!?

Wenn Du Deinen Kopf einschaltest, dann siehst Du das beim letzten 
Zugriff kein Wait kommt, weil es in Deinen Funktionen am Anfang steht. 
Offenbar bist Du Beratungs- und Lernresistent.

von Jonathan K. (burgerohnealles)


Lesenswert?

Hans schrieb:
> Jonathan K. schrieb:
>> In der Funktion eeprom_w32 ist doch ein eeprom_busy_wait!?
>
> Wenn Du Deinen Kopf einschaltest, dann siehst Du das beim letzten
> Zugriff kein Wait kommt, weil es in Deinen Funktionen am Anfang steht.
> Offenbar bist Du Beratungs- und Lernresistent.

Achsoo, hab da was falsch verstanden; du hast Recht!

von Karl H. (kbuchegg)


Lesenswert?

Ganz ehrlich.,
Ich hab jetzt 20 Minuten damit verbracht, deine Codestruktur zu 
analysieren.

Ohne es genau festmachen zu können: der Code ist irgendwie 
unübersichtlich. Wenn ich den Code warten müsste, dann würde ich den mal 
insofern überarbeiten, als ich ihn in Funktionen aufteile.

Das einzige, was mir ein bischen unkoscher aufgefallen ist, das ist die 
Diskrepanz hier
1
  uint32_t code[CODE_MAX_LEN];
2
...  
3
  uint32_t new_code[CODE_MAX_LEN+1];
new_code ist um 1 Element länger, was eigentlich nicht notwendig sein 
sollte, wenn der Überlauf auf CODE_MAX_LEN korrekt abgefangen wird.


Lösch doch mal dein EEPROM, bzw. schreib da einen bekannten Code rein.
Im Sourcecode ist mir jetzt nichts großartiges aufgefallen, ausser das 
ich ihn extrem unübersichtlich finde. Ich denke er funktioniert.
Was ich allerdings auch denke: du hast dich irgendwann mal mit einem 
Code im EEPROM ausgesperrt, so dass du es jetzt nicht mehr schaffst, die 
ein Code_ok zu holen, so dass du den Code wieder ändern kannst. Und da 
du kein code_ok bekommst, siehst du deine LED auch nie leuchten.
Das ist meine momentane Arbeitshyopthese, wenn ich davon ausgehe, dass 
es kein SRAM Overflow ist.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:
> Jonathan K. schrieb:
>> In der Funktion eeprom_w32 ist doch ein eeprom_busy_wait!?
>
> Wenn Du Deinen Kopf einschaltest, dann siehst Du das beim letzten
> Zugriff kein Wait kommt, weil es in Deinen Funktionen am Anfang steht.

Und?
Wenn kümmerts?

Das Busy Wait hat genau die Aufgabe, eine momentan gerade laufende 
EEPROM Aktion abzuwarten. Abfrage davor ist also ok.

Im Grunde braucht er sich um solche Sachen auch überhaupt nicht kümmern. 
Das machen die EEPROM-Funktionen aus eeprom.h schon ganz alleine.

: Bearbeitet durch User
von Jonathan K. (burgerohnealles)


Lesenswert?

Jonathan K. schrieb:
> Hans schrieb:
>> Jonathan K. schrieb:
>>> In der Funktion eeprom_w32 ist doch ein eeprom_busy_wait!?
>>
>> Wenn Du Deinen Kopf einschaltest, dann siehst Du das beim letzten
>> Zugriff kein Wait kommt, weil es in Deinen Funktionen am Anfang steht.
>> Offenbar bist Du Beratungs- und Lernresistent.
>
> Achsoo, hab da was falsch verstanden; du hast Recht!

Hab nochmal nachgelesen, eigentlich müsste es so wie ich es gemacht hab 
richtig sein .. wobei ich es wie Karl Heinz geschrieben hat auch hätte 
weglassen können.


Karl Heinz schrieb:
> new_code ist um 1 Element länger, was eigentlich nicht notwendig sein
> sollte, wenn der Überlauf auf CODE_MAX_LEN korrekt abgefangen wird.

Das ist deshalb, weil man als letztes ein "Prüfziffer" eingeben muss 
(Länge der neuen PIN). Das ist einfach sicherheitshalber, falls eine 
Ziffer nicht erkannt wird, dass man nicht ausgesperrt wird.


Karl Heinz schrieb:
> Lösch doch mal dein EEPROM, bzw. schreib da einen bekannten Code rein.

Habe ich bereits gemacht .. hab ihn auch keine Ahnung wie oft 
zwischendurch immer wieder ausgelesen, um zu gucken, was drin steht. Es 
war immer korrekt (in der Datei ir.tar.gz ist glaub ich auch noch eine 
Datei Namens "eeprom").


Aber wenn es ein SRAM Overflow ein sollte, warum funktioniert es dann, 
wenn in der Bedingung (die immer noch nicht zutrifft) eine 
Endlosschleife ist? o.O

: Bearbeitet durch User
von Achim K. (aks)


Lesenswert?

Der ATTiny hat 512 Bytes SRAM.

Wenn ich compiliere kommt:
"Data:        426 bytes (83.2% Full)
(.data + .bss + .noinit)"
Wenn man dann noch die zwei Arrays in main.c dazu nimmt, kommen 64 Bytes 
hinzu => 490 Bytes. Und die anderen Stack Variablen habe ich noch nicht 
drin !!!

!!! OUT OF RAM !!!

Der größte Brocken ist wohl
1
#define RAWBUF 100 // Length of raw duration buffer
2
3
...
4
5
typedef struct {
6
  volatile uint8_t *recv_pin;
7
  uint8_t recv_bit;
8
  
9
  uint8_t recv_state;
10
  uint8_t blink_flag;
11
  
12
  uint32_t timer;
13
  
14
  uint32_t raw_buf[RAWBUF];
15
  uint8_t raw_len;
16
} irparams_t;
17
18
...
19
20
volatile irparams_t irparams;

Versuch mal RAWBUF 50 oder so.

von Jonathan K. (burgerohnealles)


Lesenswert?

Achim K. schrieb:
> Versuch mal RAWBUF 50 oder so.

Hab ein bisschen rumprobiert für das von mir verwendete NEC-Protokoll 
muss RAWBUF mindestens 68 sein. Und damit funktionierts (unabhänhig von 
der Optimierung).


.. dass der AVR anfängt zu "spinnen" ist mir jetzt klar und ich weiß 
auch warum (.. ähnliche Probleme hatte ich schon öfters). Aber warum 
"spinnt" er nicht, wenn diese eine Endlosschleife im Code ist (deshalb 
bin ich auch davon ausgegangen, dass es nicht daran liegt, dass der RAM 
voll ist)?

von Achim K. (aks)


Lesenswert?

Jonathan K. schrieb:

>
> Hab ein bisschen rumprobiert für das von mir verwendete NEC-Protokoll
> muss RAWBUF mindestens 68 sein. Und damit funktionierts (unabhänhig von
> der Optimierung).
>
Na dann erstmal Gratulation!

> .. dass der AVR anfängt zu "spinnen" ist mir jetzt klar und ich weiß
> auch warum (.. ähnliche Probleme hatte ich schon öfters). Aber warum
> "spinnt" er nicht, wenn diese eine Endlosschleife im Code ist (deshalb
> bin ich auch davon ausgegangen, dass es nicht daran liegt, dass der RAM
> voll ist)?

Das Grundproblem von undeterministischem Verhalten ist, dass es 
undeterministisch ist :-).

von Pessimizer (Gast)


Lesenswert?

Jonathan K. schrieb:
> Aber warum
> "spinnt" er nicht, wenn diese eine Endlosschleife im Code ist

Vermutung: Weil der GCC erkennt, dass die Schleife nicht verlassen 
werden kann. Aller Code danach ist "unreachable", und wird wegoptimiert.
Zusammen mit dem Code alle Variablen daraus => Speicher reicht wieder.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jonathan K. schrieb:
> Hab ein bisschen rumprobiert für das von mir verwendete NEC-Protokoll
> muss RAWBUF mindestens 68 sein. Und damit funktionierts (unabhänhig von
> der Optimierung).

Das hört sich ziemlich knapp an. Hast Du Dir mal IRMP angeschaut? 
Das kommt mit wesentlich weniger RAM aus.

von Jonathan K. (burgerohnealles)


Lesenswert?

Pessimizer schrieb:
> Vermutung: Weil der GCC erkennt, dass die Schleife nicht verlassen
> werden kann. Aller Code danach ist "unreachable", und wird wegoptimiert.
> Zusammen mit dem Code alle Variablen daraus => Speicher reicht wieder.

Klingt logisch ..


Frank M. schrieb:
> Das hört sich ziemlich knapp an. Hast Du Dir mal IRMP angeschaut?
> Das kommt mit wesentlich weniger RAM aus.

Sieht interessant aus guck ich mir mal an.

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
Noch kein Account? Hier anmelden.