oberallgeier
28.12.2012, 11:19
oder
Rauhnächte, C und andere Mysterien
Nachdem wir den Weltuntergang überstanden haben, müssen wir nun aufräumen.
Aufräumen hatte bei mir u.a. auch mit ner geänderten Pinbelegung an einer RNControl zu tun, bei der ich den RC-5-Decoder vom Pollen an einem allgemeinen Eingangspin auf einen externen Interrupt umgelegt und softwareseitig entsprechend umgearbeitet hatte. Der Decoder funktioniert prächtig.
Die Fernsteuerung hat bei mir noch (seit MiniD0) die Funktion, die Akkuüberwachung bei Bedarf/auf Wunsch beim Programmstart ausser Kraft zu setzen, um im Notfall noch Aktionen durchführen zu können. Dafür läuft als dritter Arbeitsschritt im main - nach der Portinitialisierung und einem delay-gesteuerten Reset-LED-Blinken die Abfrage des RC-5-Pinns. Bis dahin ist also kein anderes Modul aktiv, kein Interrupt, kein Watchdog, keine sonstige Controlleraktivität aktiviert. Wird zu diesem Zeitpunkt am RC-5-Eingangspin ein low erkannt, dann wird die Akkuüberwachung auf ADC=2 gestellt - also fast ausgeschaltet. Nochmal: es läuft noch kein Interrupt, kein sonstiger Schritt, kein Watchdog, kein garnix.
Die genannte Pinänderung hatte ich beim Übergang auf den internen Interrupt vergessen und bin dieser Tage (am 26. Dezember) zufällig draufgekommen.
Also wird der Code geändert, der früherer Anschluss von PC2 auf den aktuell auch tatsächlich benutzten PINB2 gelegt (was in der Interruptroutine bestens funktioniert):
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Abfrage ob ADC-Wert-Prüfung abgeschaltet werden soll
// ###>>> Zum Abschalten IRGENDEINE Fernsteuerungstaste drücken
/*
ADC5MM = 500; // Setze ADCMiniMum auf MiniMalwert
for (uint8_t k=0; k<1000; k++ ) // Eingang/SFH5110 abfragen => low ?
{ // RC-5-Signal hängt am PB2
if (!(PINB & (1<<2))) ADC5MM = 2;// Wenn Sensor auf LOW steht <=> IR ist on
} // Ende von for ( i=0; i<1000; i++ )
*/
// - - - - - - - - - - - - - - -
Und schon schlägt einer der Rauhnacht-Geister zu. Das Programm bleibt hängen. Nach dem Auskommentieren - wie im Codezitat oben gezeigt - läuft das Programm wie üblich. Als Ergänzung noch ein drittes Mal folgendes: es werden davor a) die Pinne definiert als Ein-/Ausgang und mit/ohne Pullup, danach kommt die wait-gesteuerte Blinkerei (10 mal).
Ich habe diesen Codeschnippsel völlig gelöscht, neu geschrieben, die Schaltung kontrolliert, den Kopf gekratzt, mich geärgert, mich gewundert - es hatte alles nix geholfen. Das Programm, das mit Kommentaren mittlerweile insgesamt an die tausend Codezeilen umfasst, läuft ohne diesem Schnippsel (ok, mit Auskommentierung) wie üblich, mit aktivem Schnippsel bleibt es zwischen diesem Codeteil und der ersten UART-Ausgabe hängen. Wo - ist EXAKT nicht nachgewiesen.
Langer Rede kurzer Sinn (und um meinen Groll über die ganze Sache nicht allzu hoch kochen zu lassen): Ich habe die letzte Sicherung vom Tag davor genommen, neu eingespielt, die Pinabfrage wie oben skizziert eingefügt/geändert, kompiliert, geflasht - und es funktioniert.
Nun bleibt eine unmystische Frage offen: gibt es irgendwelche Suchkriterien um solche Vorkommnisse aufzuklären? Klar, die *.lls durcharbeiten - 4720 Zeilen - irgendwie ist mir das zu viel Arbeit. VERMUTLICH liegt der Fallstrick schon in den ersten Abläufen, aber . . . wenn nicht? Simulator? Ich habe den Simulator vor Jahren mit Assembler erfolgreich benutzt, aber bereits dort die Problematik bei nur einem Interrupt eigentlich nicht in den Griff bekommen, ich habe kein ICE (und müsste mich da auch lange einarbeiten) - sprich: ich fürchte, dass ich erstmal mit dem Simulator und verwandten Hilfen nicht wirkliche Hilfe bekäme.
Vermutlich passiert das dem einen oder anderen von Euch auch gelegentlich: nicht nachvollziehbare Fehlfunktionen. Vor ein paar Tagen hatte ein Kollege, der seinen Roboter mit nem ARM betreibt, mir geschrieben, dass er seit etlichen Stunden eine LED nicht angeknippst bekommt . . .
Mich stört hinter "meiner" Störung das ungute Gefühl, dass es vielleicht eine Unsauberkeit im Restcode ist, eine Unverträglichkeit, die beim Husten eines Schmetterlings in China zur Fehlfunktion meines Roboters führt oder führen kann. Wie sucht man so etwas (wenn die eigenen C-Kenntnisse nicht wirklich umfassend und nicht annähernd perfekt sind). Oder - macht Ihr das so wie ich - alte Sicherung her, anpassen an die Änderungen seit der Sicherung - und wenns dann funktioniert - dann ists gut?
Oder vielleicht die Frage einfach so: was überwiegt bei Euch? Die kritische, möglichst genaue Analyse auch dann, wenn der Code "ewig" lang geworden war (und wie macht ihr das?) - oder die experimentelle Lösung - wenns klappt ists gut?
Rauhnächte, C und andere Mysterien
Nachdem wir den Weltuntergang überstanden haben, müssen wir nun aufräumen.
Aufräumen hatte bei mir u.a. auch mit ner geänderten Pinbelegung an einer RNControl zu tun, bei der ich den RC-5-Decoder vom Pollen an einem allgemeinen Eingangspin auf einen externen Interrupt umgelegt und softwareseitig entsprechend umgearbeitet hatte. Der Decoder funktioniert prächtig.
Die Fernsteuerung hat bei mir noch (seit MiniD0) die Funktion, die Akkuüberwachung bei Bedarf/auf Wunsch beim Programmstart ausser Kraft zu setzen, um im Notfall noch Aktionen durchführen zu können. Dafür läuft als dritter Arbeitsschritt im main - nach der Portinitialisierung und einem delay-gesteuerten Reset-LED-Blinken die Abfrage des RC-5-Pinns. Bis dahin ist also kein anderes Modul aktiv, kein Interrupt, kein Watchdog, keine sonstige Controlleraktivität aktiviert. Wird zu diesem Zeitpunkt am RC-5-Eingangspin ein low erkannt, dann wird die Akkuüberwachung auf ADC=2 gestellt - also fast ausgeschaltet. Nochmal: es läuft noch kein Interrupt, kein sonstiger Schritt, kein Watchdog, kein garnix.
Die genannte Pinänderung hatte ich beim Übergang auf den internen Interrupt vergessen und bin dieser Tage (am 26. Dezember) zufällig draufgekommen.
Also wird der Code geändert, der früherer Anschluss von PC2 auf den aktuell auch tatsächlich benutzten PINB2 gelegt (was in der Interruptroutine bestens funktioniert):
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Abfrage ob ADC-Wert-Prüfung abgeschaltet werden soll
// ###>>> Zum Abschalten IRGENDEINE Fernsteuerungstaste drücken
/*
ADC5MM = 500; // Setze ADCMiniMum auf MiniMalwert
for (uint8_t k=0; k<1000; k++ ) // Eingang/SFH5110 abfragen => low ?
{ // RC-5-Signal hängt am PB2
if (!(PINB & (1<<2))) ADC5MM = 2;// Wenn Sensor auf LOW steht <=> IR ist on
} // Ende von for ( i=0; i<1000; i++ )
*/
// - - - - - - - - - - - - - - -
Und schon schlägt einer der Rauhnacht-Geister zu. Das Programm bleibt hängen. Nach dem Auskommentieren - wie im Codezitat oben gezeigt - läuft das Programm wie üblich. Als Ergänzung noch ein drittes Mal folgendes: es werden davor a) die Pinne definiert als Ein-/Ausgang und mit/ohne Pullup, danach kommt die wait-gesteuerte Blinkerei (10 mal).
Ich habe diesen Codeschnippsel völlig gelöscht, neu geschrieben, die Schaltung kontrolliert, den Kopf gekratzt, mich geärgert, mich gewundert - es hatte alles nix geholfen. Das Programm, das mit Kommentaren mittlerweile insgesamt an die tausend Codezeilen umfasst, läuft ohne diesem Schnippsel (ok, mit Auskommentierung) wie üblich, mit aktivem Schnippsel bleibt es zwischen diesem Codeteil und der ersten UART-Ausgabe hängen. Wo - ist EXAKT nicht nachgewiesen.
Langer Rede kurzer Sinn (und um meinen Groll über die ganze Sache nicht allzu hoch kochen zu lassen): Ich habe die letzte Sicherung vom Tag davor genommen, neu eingespielt, die Pinabfrage wie oben skizziert eingefügt/geändert, kompiliert, geflasht - und es funktioniert.
Nun bleibt eine unmystische Frage offen: gibt es irgendwelche Suchkriterien um solche Vorkommnisse aufzuklären? Klar, die *.lls durcharbeiten - 4720 Zeilen - irgendwie ist mir das zu viel Arbeit. VERMUTLICH liegt der Fallstrick schon in den ersten Abläufen, aber . . . wenn nicht? Simulator? Ich habe den Simulator vor Jahren mit Assembler erfolgreich benutzt, aber bereits dort die Problematik bei nur einem Interrupt eigentlich nicht in den Griff bekommen, ich habe kein ICE (und müsste mich da auch lange einarbeiten) - sprich: ich fürchte, dass ich erstmal mit dem Simulator und verwandten Hilfen nicht wirkliche Hilfe bekäme.
Vermutlich passiert das dem einen oder anderen von Euch auch gelegentlich: nicht nachvollziehbare Fehlfunktionen. Vor ein paar Tagen hatte ein Kollege, der seinen Roboter mit nem ARM betreibt, mir geschrieben, dass er seit etlichen Stunden eine LED nicht angeknippst bekommt . . .
Mich stört hinter "meiner" Störung das ungute Gefühl, dass es vielleicht eine Unsauberkeit im Restcode ist, eine Unverträglichkeit, die beim Husten eines Schmetterlings in China zur Fehlfunktion meines Roboters führt oder führen kann. Wie sucht man so etwas (wenn die eigenen C-Kenntnisse nicht wirklich umfassend und nicht annähernd perfekt sind). Oder - macht Ihr das so wie ich - alte Sicherung her, anpassen an die Änderungen seit der Sicherung - und wenns dann funktioniert - dann ists gut?
Oder vielleicht die Frage einfach so: was überwiegt bei Euch? Die kritische, möglichst genaue Analyse auch dann, wenn der Code "ewig" lang geworden war (und wie macht ihr das?) - oder die experimentelle Lösung - wenns klappt ists gut?