Nachdem ich nun wieder im "Padauk-Fieber" bin (ich habe keine Ahnung,
warum mich dieser derart kastrierte Mikrocontroller so fasziniert) habe
ich ein (kleines) "Schönheitsproblem" (wie ich glaube).
Etwas, das bisher problemlos mit SDCC 4.0.4 und SDCC 4.10 funktioniert
hat, gibt mir nun eine Assemblerwarnung aus:
1
?ASxxxx-Warning in line 88 of delay.asm
2
Forced IO address space for instruction without .io
3
?ASxxxx-Warning in line 109 of delay.asm
4
Forced IO address space for instruction without .io
und ich habe keine Ahnung wo das herkommt und wichtiger wie ich das
abgestellt bekomme.
Die Warnung wird von einer Verzögerungsschleife generiert, die in
Assembler codiert und nicht von mir ist. Quelle der delay-Funktion ist:
https://github.com/free-pdk/free-pdk-examples/blob/master/include/delay.h
Der Author dieser Funktion zählt die Taktimpulse der MCU (und macht das
sehr genau). Leider hat er Programmcode in die delay.h eingefügt, was
mir nicht so wirklich gefällt. Vor allen Dingen kann bei diesem Vorgehen
diese delay.h nur einmal im gesamten Programm inkludiert werden. Habe
ich andere *.h / *.c Dateien kann ich dort dann nicht auch #include
"delay.h" machen, weil ich hier dann doppelte Definitionen habe.
Also hatte ich diese Funktion geteilt in eine delay.c und eine delay.h
und habe die bisher meinem Programm hinzugelinkt.
Hat bisher klaglos funktioniert.
So wollte ich das auch mit SDCC4.4.4 machen. Wie oben beschrieben
erzeugt mir das eine Warnmeldung. Allerdings ist das "nur" eine Warnung,
das Programm verarbeitet die delay-funktion klaglos.
Bindet man die originale delay.h (ohne zu linken), die ich zu
Unterscheidungszwecke nach delay_inc.h umbenannt habe im Main-Programm
ein, wird diese Warnmeldung interessanterweise nicht erzeugt!
Im Zip-Anhang habe ich beide Programmversionen (mit und ohne Linken)
hinzugefügt.
Der Assemblercode der Delay-Funktion stößt sich an folgender Instruktion
(gleiche Befehle in Zeile 88 und 109:
1
t1sn f, z ; 1 cycle + 1 cycle for final skip
Diese Instruktion überspringt die nachfolgende Instruktion (ein goto)
und beendet somit die Warteschleife.
Wie bekomme ich die Warnmeldungen weg oder wie kann ich hier zumindest
diese Warnmeldung explizit unterdrücken? (und nur diese).
Ralph S. schrieb:> Vor allen Dingen kann bei diesem Vorgehen diese delay.h nur einmal im> gesamten Programm inkludiert werden.
Nein, die Datei hat ein "include guard", d. h. der Inhalt wird auch bei
mehrfachem Aufruf nur einmal eingebunden.
Klaus R. schrieb:> Könnte es möglicherweise sein
Das wird es sein. Der Patch vom 24. May auf delay.h fügt u.a. das ".io"
an die Instruktion an:
https://github.com/free-pdk/free-pdk-examples/commit/768a1790e786084a56ddb37d0f670e33618db102Ralph S. schrieb:> Bindet man die originale delay.h (ohne zu linken), die ich zu> Unterscheidungszwecke nach delay_inc.h umbenannt habe im Main-Programm> ein, wird diese Warnmeldung interessanterweise nicht erzeugt!
Ist auch logisch, denn dort steht ja auch "t1sn.io f, z" (mit .io).
Ralph S. schrieb:> Vor allen Dingen kann bei diesem Vorgehen> diese delay.h nur einmal im gesamten Programm inkludiert werden.
Wobei der "include guard", den Mario erwähnt hat, schon in der ersten
Version in der Datei war (zumindest der auf github).
Klaus R. schrieb:> Wenn ich da Zeile 81 ansehe, steht da: t1sn.io f, z>> Könnte es möglicherweise sein, das (ganz banal) ein> t1sn.io f, z ; 1 cycle + 1 cycle for final skip
So banal wie das klingt ... :-)
DAS WAR ES !
Ich hatte diese Funktion vor längerer Zeit aus diesem Github kopiert und
nicht mitbekommen, dass der Besitzer des Githubs, genau dieses geändert
hatte.
Vielen Dank
Klaus R. schrieb:> Wobei der "include guard", den Mario erwähnt hat, schon in der ersten> Version in der Datei war (zumindest der auf github).
Na ja, ich brauch den include guard jetzt nicht, weil das mit *.h / *.c
und linken jetzt auch ohne Warnung funktioniert.
Und nochmal: vielen Dank an euch beide !
Mario M. schrieb:> Nein, die Datei hat ein "include guard", d. h. der Inhalt wird auch bei> mehrfachem Aufruf nur einmal eingebunden.
Ein Include Guard funktioniert nur für eine "translation unit", d.h., er
schützt nur vor mehrfachem Einbinden in ein und dasselbe Sourcefile. Bei
Projekten, die aus mehreren Sourcefiles bestehen, funktioniert das
nicht, denn jedes Sourcefile wird separat übersetzt.
Und damit wird, wenn der via #include eingebundene Kram globale Symbole
definiert (sei es durch Variablen oder aber eben Funktionen), der Linker
zu Recht über Mehrfachdefinitionen klagen.
Harald K. schrieb:> nd damit wird, wenn der via #include eingebundene Kram globale Symbole> definiert (sei es durch Variablen oder aber eben Funktionen), der Linker> zu Recht über Mehrfachdefinitionen klagen.
... und das ist der Grund, warum die originale delay.h in delay.h (ohne
globale Symbole) und in delay.c (den Codedefinitionen) aufgeteilt wurde.
Dein Post hat das super beschrieben!
Ralph S. schrieb:> Dein Post hat das super beschrieben!
Danke für die Blumen. Mit altem C mache ich halt auch schon 'ne Weile
rum, auch wenn der Erstkontakt erst mal sehr abschreckend war (ein
K&R-Compiler und schlechte Dokumentation). Der Zweitkontakt erfolgte
dann mit Borlands Turbo C 2.0 (damals von Heimsoeth mit einem
exzellenten deutschsprachigen Handbuch verkauft), das kam noch vor dem
offiziellen C89-Standard auf den Markt (war aber anhand von "drafts"
daran angepasst).
Mein Erstkontakt war auf einem Schneider CPC6128 (Compiler weiß ich
nicht mehr) und dann auch Turbo C von Borland. Es hätte mich gewundert,
wenn Programmcode im Headerfile von mehreren Sourcen keine
Multidefinition hervorrufen würde. :-) aus diesem Grund eben linken.
Ralph S. schrieb:> Es hätte mich gewundert,> wenn Programmcode im Headerfile von mehreren Sourcen keine> Multidefinition hervorrufen würde.
Geht - wenn der als static definiert wird. Dann sieht der Linker
nichts davon.
Harald K. schrieb:> Geht - wenn der als static definiert wird. Dann sieht der Linker> nichts davon.
okay, stimmt ! Allerdings: static verwende ich - in aller Regel - nur
innerhalb einer Funktion, wenn beim Wiedereintritt der Wert einer
Variablen den Inhalt haben soll, den er bei einer vorherigen Verwendung
besessen hat.
Ansonsten überlasse ich schon dem Compiler/Linker die beste Aufteilung
im Speicher!
Ralph S. schrieb:> Allerdings: static verwende ich - in aller Regel - nur> innerhalb einer Funktion
Das ist dann was komplett anderes. Das Schlüsselwort static hat zwei
komplett unterschiedliche Bedeutungen - in einer Funktion kann man es
für eine Variablendefinition verwenden, so, wie Du es tust, aber
außerhalb einer Funktion bewirkt es etwas anderes, nämlich die
"Unsichtbarkeit" des jeweiligen Symbols für den Linker. Das Symbol
kann hier eine Variable, aber auch ein Funktion sein.
Und in C++ hat static noch eine weitere Bedeutung, eine als static
deklarierte Memberfunktion einer Klasse wird ohne impliziten this
-Pointer aufgerufen, d.h. kann auch ohne Instanziierung eines Objektes
verwendet werden.
Harald K. schrieb:> Geht - wenn der als static definiert wird.
Kann man machen, ist aber auf einem PFS154 nicht sehr sinnvoll. Damit
kommt der Code nämlich N-fach in den Speicher, wenn Du delay.h in N
Übersetzungseinheiten includierst. Der kleine PFS154 wird dann
irgendwann platzen.
Ralph S. schrieb:> Leider hat er Programmcode in die delay.h eingefügt, was mir nicht so> wirklich gefällt.
Schreib dem Autor doch eine Nachricht mit der Begründung, dass der
Programmcode in delay.h die Usablilty doch sehr einschränkt.
Frank M. schrieb:> Kann man machen, ist aber auf einem PFS154 nicht sehr sinnvoll.
Allerdings, das wollte ich auch nicht behaupten. Es ist im Grunde
genommen nirgends sinnvoll.
Ich hab' das halt nur erwähnt, weil es möglich ist.
Frank M. schrieb:> Schreib dem Autor doch eine Nachricht mit der Begründung, dass der> Programmcode in delay.h die Usablilty doch sehr einschränkt.
:-) ich für mich habe das ja geändert in *.c / *.h Datei geändert und
linke das bei Bedarf hinzu. Hm, auf dem Github des Authors sind noch
andere Fehler enthalten (auch was das Initialisieren der Hardware
angeht). Außerdem führt er in jeder *.h Datei Code mit sich herum und
linkt nie etwas hinzu.
Von daher glaube ich macht es wenig Sinn ihn darauf aufmerksam zu
machen. Abgesehen davon sind seine Taktzählungen und das Aufteilen in
8-, 16- und 32-Bit Zählschleifen relativ gut gelungen. :-) so gut, dass
ich das nicht selbst machen wollte.