Forum: Mikrocontroller und Digitale Elektronik Leerzeilen im Code verändern Programmverhalten?!


von W.B. (Gast)


Lesenswert?

Hallo.

Wie kann es sein, dass Leerzeilen in einer Header-Datei den Code 
beeinflussen?
Auch die größe der Hex-Datei ist anders und das LIST-File ist auch nicht 
ident.

Ich verwende den CCS-Compiler v4.013 und einen PIC16F688.


Das Problem dass auftritt, ist:

Normaler Code -> Zeichen würd über UART empfangen -> RESET (WDT ist aus)
Code mit Leerzeilen -> Alles Funktioniert


Ich werde den Code später noch posten.
Vielleicht kennt ja jemand diese Problem schon...

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

Die Glaskugel sagt, das kommt auf deinen Code an.

von W.B. (Gast)


Lesenswert?

Hier ist der Code:
http://pastebin.com/D5ft0Ak3

Wenn ich in Zeile 324 Leerzeilen einfüge (einfach ENTER), funktioniert 
der Code.
So wie er jetzt ist, nicht.

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

W.B. schrieb:
> Wenn ich in Zeile 324 Leerzeilen einfüge (einfach ENTER)

Fügst du jetzt ein Leerzeichen oder einen Zeilenumbruch ein?

So direkt würde ich sagen, dein Compiler ist Murks.
Schau dir doch mal den Unterschied in der Binärdatei an.
Hier sollte es eigentlich keinen Unterschied geben.

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


Lesenswert?

W.B. schrieb:
> Auch die größe der Hex-Datei ist anders und das LIST-File ist auch nicht
> ident.
Interessant wäre, was im Listing anders ist...


BTW: manche (alten) Compiler, deren Präprozessoren bei Makros nur 
stumpfe Textersetzung machen, haben damit Probleme:
#define ZIGBEE_BETR_TIMEOUT 600       // 6 sekunden
Aber dann dürfte der Code gar nicht compilieren...

von W.B. (Gast)


Lesenswert?

Probleme wegen dem Kommentar??

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

Ja Lothar hat Recht: Bevor du die Binärdaten vergleichst,
was ist der Unterschied im Listing?

Und ja, es gibt schlechte Compiler, die Kommentare nicht
richtig verarbeiten können.

von W.B. (Gast)


Lesenswert?

Hier die List-Datei:
http://pastebin.com/9Chcsxwb

Ich habe nicht alles durchgesehen, aber folgendes ist mir aufgefallen:

*) CodeZeile 0002:  GOTO   XXXX  (sprung ins MAIN)
*) Zeile  1280 und 3678 sind unterschiedlich.
*) Sprungadressen sind meist unterschiedlich
*) Benötigter ROM ist unterschiedlich

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

Ein Diff wäre schöner.

von Noname (Gast)


Lesenswert?

#define ZIGBEE_BETR_TIMEOUT 600       // 6 sekunden

Beim Aufruf

Funktion(ZIGBEE_BETR_TIMEOUT);

Vergleiche

Funktion(600       // 6 sekunden);

(-> hier sollte dann eigentlich beim Übersetzen die Klammer ')' 
fehlen...)

im Gegensatz zu

Funktion(600);

von W.B. (Gast)


Lesenswert?

Es gibt keine Compiler Errors/Warnings...
Also solche Fehler kann man ziemlich sicher ausschließen

von Peter (Gast)


Lesenswert?

1
#define DEFINES_H
hat doch keinen Wert dahinter, ist das evtl. der Fehler, dass er die 
Leerzeile als Wert nimmt bzw. ohne Leerzeile die nächste Zeile als Wert?

von Christian G. (christian_g83)


Lesenswert?

W.B. schrieb:

> Also solche Fehler kann man ziemlich sicher ausschließen

Sieht auch eher nach kaputtem Compiler aus. Die Zeile
1
case INIT_TMR0_AKT:      at_send(ATS18); break;
wird so übersetzt:
1
nicht OK:      OK
2
---------      ---------
3
CLRF   22      CLRF   22
4
CLRF   21      MOVLW  0B
5
               MOVWF  21
6
MOVLW  A0      MOVLW  A0
7
MOVWF  04      MOVWF  04
8
...            ...

Leide spreche ich nicht genug AVR, um hier mehr Hilfestellung zu geben.

Christian

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
>
1
> #define DEFINES_H
2
>
> hat doch keinen Wert dahinter, ist das evtl. der Fehler, dass er die
> Leerzeile als Wert nimmt bzw. ohne Leerzeile die nächste Zeile als Wert?

Das wäre ein Fehler im Präprozessor. Und der wär schon längst 
aufgefallen. Damit würde kein einziger Include-Guard mehr funktionieren.

von Christian G. (christian_g83)


Lesenswert?

Peter schrieb:

>
1
> #define DEFINES_H
2
>
> hat doch keinen Wert dahinter

Den braucht's auch nicht.

Christian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christian Gudrian schrieb:
1
> nicht OK:      OK
2
> ---------      ---------
3
> CLRF   22      CLRF   22
4
> CLRF   21      MOVLW  0B
5
>                MOVWF  21
6
> MOVLW  A0      MOVLW  A0
7
> MOVWF  04      MOVWF  04
8
> ...            ...

> Leide spreche ich nicht genug AVR, um hier mehr Hilfestellung zu geben.

Ist gar kein AVR, sondern PIC. ;-)

In einem Fall wird Speicherstelle 0x21 gelöscht, im anderen auf 0x0b
gesetzt (über den PIC-typischen Umweg des Akkumulators, genannt "W").

von Peter D. (peda)


Lesenswert?

Christian Gudrian schrieb:
> Leide spreche ich nicht genug AVR

Macht nichts, ist eh PIC.
Der Unterschied ist, daß einmal Adresse 21 mit 0 geladen wird und einmal 
mit 0xB.


Peter

von Yalu X. (yalu) (Moderator)


Lesenswert?

Der Wert, der in Register 21 geladen wird, ist die Größe des jeweiligen
Arrays (in diesem Fall ATS18 mit 10 Zeichen plus NUL am Ende, also
insgesamt 11 Bytes), das an at_send() übergeben werden soll. Offensicht-
lich werden die Daten jedesmal vor Benutzung ins RAM ab Adresse 0x00A0
kopiert und diese Adresse dann an at_send() übergeben.

Wenn nun in Register 21 statt der 11 eine 0 steht, werden statt der 11
Bytes 256 Bytes kopiert, was sehr wahrscheinlich mit anderen Daten im
RAM kollidiert und damit zum Fehler führt.

Das Problem tritt in jedem Case der Switch-Anweisung außer dem ersten
(INIT_RESET) auf. Dort ist der auszugebende String (ATF="AT&F") so kurz,
dass der Compiler keine Schleife anlegt, um die Daten zu kopieren,
sondern dan RAM-Bereich mit mehreren aufeinanderfolgenden MOV*-Befehlen
mit den Daten füllt.

Wie jetzt aber die einzelne zusätzliche Leerzeile im Zusammenhang mit
der fehlerhaften Anzahl der Schleifendurchläufe bei der Kopieraktion
steht, erschließt sich mir auch nicht. Möglicherweise ist es ein Compi-
ler-Bug.

Nebenbei: Deine Include-Hierarchie ist ziemlich krumm:
1
funk.c
2
 |
3
 +——16f688.h
4
 |
5
 +——defines.h
6
 |
7
 +——globals.h
8
 |
9
 +——int.c
10
 |   |
11
 |   +——globals.h
12
 |   |
13
 |   +——defines.h
14
 |
15
 +——string.h

Von int.c werden defines.h und globals.h in der verkehrten Reihenfolge
includiert (globals.h benutzt eine Definition aus defines.h). Das Ganze
funktioniert aber zufälligerweise trotzdem, da beide Header zuvor schon
von funk.c in der richtigen Reihenfolge aufgerufen wurden.

Jede Quellcodedatei sollte immer alle Header includieren, von denen sie
direkt abhängig ist. Dann ist auch die Reihenfolge der Include-Direkti-
ven egal.

Folgende Hierarchie wäre also besser:

funk.c:
1
#include <string.h>
2
#include <16f688.h>
3
#include "defines.h"
4
#include "globals.h"
5
#include "int.c"

int.c:
1
#include <16f688.h>
2
#include "defines.h"
3
#include "globals.h"

defines.h:
1
#include <16f688.h>

globals.h:
1
#include "defines.h"

Wenn int.c getrennt kompiliert wird, was sinnvoll ist, fällt das letzte
Include in funk.c weg, der Rest bleibt gleich.

von W.B. (Gast)


Lesenswert?

Hallo Yalu X.

Vielen Dank für deine Antwort.
Deine Erklärung kling sehr überzeugend. Ich verwende das #device 
PASS_STRINGS=IN_RAM, was genau das machen SOLLTE, was du beschrieben 
hast.

Es wird wohl wirklich ein Compiler-Bug sein.
Das ist echt zäh sowas zu finden wenn man nicht 100% mit Compiler, 
Controller und Assembler vertraut ist...

Normalerweise arbeite ich mit AVR ;)


Ich werde mein Programm mal anders aufbauen, ohne String-Konstanten, und 
es dann probieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.B. schrieb:
> Normalerweise arbeite ich mit AVR ;)

Dann tausche den PIC16F688 doch heimlich gegen einen ATtiny84 aus. :-))

von W.B. (Gast)


Lesenswert?

Es funktioniert! Super.

danke an alle!

von fonsana (Gast)


Lesenswert?

Die Empfehlung war:

Jörg Wunsch schrieb:
> Dann tausche den PIC16F688 doch heimlich gegen einen ATtiny84 aus. :-))

und das Ergebnis:

W.B. schrieb:
> Es funktioniert! Super.

Sicher?????????????????????????????????????????????????????????????????

fonsana

von W.B. (Gast)


Lesenswert?

Nein, ich hab nicht den PIC gegen einen AVR getauscht...
Aber ich hab das mit den String-Konstanten anders gelöst und somit 
brauche ich das #device PASS_STRINGS=IN_RAM  nicht mehr.
Ergebnis: PIC stürzt nicht mehr ab und Dateigröße der .HEX Datei ist 
gleich, egal wieviele Leerzeilen ich einfüge.

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.