Leerzeilen im Code verändern Programmverhalten?!

Gast #2822574
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...
(Firma: Basta) #2822586
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.
Moderator (Firma: Titel) Persönliche Seite #2822593
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...
Gast #2822619
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
Gast #2822629
#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);
Gast #2822643
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?
#2822650
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
#2822653
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.
Moderator Persönliche Seite #2822668
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").
Moderator #2822933
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.
Gast #2823645
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.
Gast #2824001
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.