Leerzeilen im Code verändern Programmverhalten?!

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren