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...
Die Glaskugel sagt, das kommt auf deinen Code an.
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.
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.
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...
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.
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
#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);
Es gibt keine Compiler Errors/Warnings... Also solche Fehler kann man ziemlich sicher ausschließen
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?
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
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.
Peter schrieb: >
1 | > #define DEFINES_H |
2 | >
|
> hat doch keinen Wert dahinter
Den braucht's auch nicht.
Christian
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").
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
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.
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.
W.B. schrieb: > Normalerweise arbeite ich mit AVR ;) Dann tausche den PIC16F688 doch heimlich gegen einen ATtiny84 aus. :-))
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.