Hallo in die Expertenrunde,
ich bin auf eine Unstimmigkeit gestoßen, die ich mir nicht erklären
kann.
Ich verwende einen attiny85 mit dem internen 125KHz-Oszillator.
Die Fuses passen, der attiny läuft mit 128KHz (ohne zusätzlichen
Vorteiler).
und in den Projekteigenschaften in eclipse ist in der toolchain als
target die richtige MCU "attiny85" mit 128000 als Frequenz gesetzt.
Wenn ich jetzt ein Programm über eclipse kompiliere (keine warnings oder
errors) und auf den attiny lade, läuft das Programm wie erwartet.
Wenn ich exakt dasselbe Programm auf der Konsole mit einem Makefile und
make (gnu make 5.2.1) kompiliere und hochlade, läuft es deutlich
langsamer - ich könnte wetten, daß es um den Faktor 8 langsamer ist. Ich
bekomme hier auch entsprechende Warnings:
/usr/lib/avr/include/util/delay.h:92:3: warning: #warning "F_CPU not defined for <util/delay.h>" [-Wcpp]
4
# warning "F_CPU not defined for <util/delay.h>"
5
^
6
main.c:18:0: warning: "F_CPU" redefined
7
#define F_CPU 128000UL
8
^
9
In file included from main.c:17:0:
10
/usr/lib/avr/include/util/delay.h:108:0: note: this is the location of the previous definition
11
# define F_CPU 1000000UL
12
^
Im Makefile sind die korrekte MCU und F_OSC mit 128000 angegeben, und
auch im Programm selbst ist F_CPU aus der eclipse-Umgebung mit 128000
gesetzt.
Am Programm selbst wird nichts verändert, es ist exakt dasselbe.
Könnte das was mit dem Makefile sein? In eclipse erhalte ich keine
Warnings, und irgendwo auf Konsolenebene scheinen die 128000 ignoriert
und stattdessen der attiny85-default von 1MHz verwendet zu werden.
Wo kann ich noch nachschauen?
Stephan E. schrieb:> /usr/lib/avr/include/util/delay.h:92:3: warning: #warning "F_CPU not> defined for <util/delay.h>"
Definiere F_CPU im Makefile, nicht im Source. Dann hat es für alle
compilierten Sources denselben Wert.
Wenn doch im Source, dann muss das #define vor dem include von delay.h
stehen.
Stephan E. schrieb:> ich bin auf eine Unstimmigkeit gestoßen, die ich mir nicht erklären> kann.> Wenn ich exakt dasselbe Programm auf der Konsole mit einem Makefile und> make (gnu make 5.2.1) kompiliere und hochlade, läuft es deutlich> langsamer - ich könnte wetten, daß es um den Faktor 8 langsamer ist.
Naja. Das Programm läuft nicht langsamer. Aber die Wartezeiten mit
_delay(...) dauern wohl länger.
> Ich bekomme hier auch entsprechende Warnings:
...
> /usr/lib/avr/include/util/delay.h:92:3: warning: #warning "F_CPU not> defined for <util/delay.h>" [-Wcpp]
Guckstu. delay.h braucht die CPU-Frequenz im Makro F_CPU. Hast du nicht
gesetzt, deswegen nimmt es einen Standardwert an.
> main.c:18:0: warning: "F_CPU" redefined> #define F_CPU 128000UL> In file included from main.c:17:0:> /usr/lib/avr/include/util/delay.h:108:0: note: this is the location of> the previous definition> # define F_CPU 1000000UL
Guckstu: weil delay.h kein F_CPU bekommen hat, setzt es das selber. Und
zwar auf 1MHz. Wenn du F_CPU danach selber nochmal zu setzen
versuchst, gibt das natürlich eine Warnung.
> Im Makefile sind die korrekte MCU und F_OSC mit 128000 angegeben
Blöd halt, daß das Makro das allerorten verwendet wird, nicht F_OSC
heißt, sondern F_CPU.
> und auch im Programm selbst ist F_CPU aus der eclipse-Umgebung> mit 128000 gesetzt.
Nur eben zu spät. Das F_CPU Makro muß definiert sein, bevor delay.h
(auch indirekt) #included wird. Im Zweifel ist man am sichersten, wenn
man es dem Compiler per -D Option mitgibt.
> Könnte das was mit dem Makefile sein?
Es wäre wohl am einfachsten, im Makefile ein "-D F_CPU=128000L"
unterzubringen. In der Nähe der Stelle, wo F_OSC definiert wird. Woher
kommt eigentlich dieses ominöse Makro F_OSC? Wer wertet das aus? Warum
nimmt derjenige nicht das standardmäßige F_CPU statt dessen?
> Nur eben zu spät. Das F_CPU Makro muß definiert sein, bevor delay.h> (auch indirekt) #included wird. Im Zweifel ist man am sichersten, wenn> man es dem Compiler per -D Option mitgibt.
Das war der entscheidende Hinweis, danke.
Ich bin bislang fälschlicherweise immer davon ausgegangen, daß das
maneulle define den vorhandenen Wert überschreibt statt daß er dadurch
gesetzt und dann eben nicht mehr überschrieben wird. Wieder was gelernt.
Stephan E. schrieb:> Ich bin bislang fälschlicherweise immer davon ausgegangen, daß das> maneulle define den vorhandenen Wert überschreibt statt daß er dadurch> gesetzt und dann eben nicht mehr überschrieben wird. Wieder was gelernt.
Ich bin mir nicht sicher, ob du das verstanden hast. Ein C-Makro wird
vom Präprozessor einfach im Quelltext ersetzt. Genauso wie Suchen &
Ersetzen im Texteditor. Auch #include arbeitet rein auf Quelltext-Ebene.
Die Anweisung wird durch den Inhalt des Includefiles ersetzt.
Das passiert genau einmal. Bei der Expansion wird von einem Makro immer
die gerade gültige Definition verwendet. Wenn es keine gibt, dann wird
das Makro einfach gar nicht expandiert. Es ist auch möglich (aber
seltenst sinnvoll) ein Makro mehrfach, gar unterschiedlich zu
definieren. Dann wird es an verschiedenen Stellen des Quellcodes nämlich
entsprechend unterschiedlich expandiert. Der Präprozessor weist darauf
auch deutlich mit seiner Warnung hin.
Z.B. in diesem "Programm"
1
#define F_CPU 1000000UL
2
#include"foo.h"
3
4
#define F_CPU 128000UL
5
#include"bar.h"
Wird an allen Stellen, wo Code in foo.h sich auf F_CPU bezieht, der Wert
1000000UL verwendet. In bar.h dann allerdings 128000UL. Bei dem zweiten
#define wirft der Präprozessor eine Warnung.
Das ist ziemlich genau deine Konstellation. Außer daß das erste #define
in delay.h steckt. Da wird nämlich am Anfang geschaut, ob F_CPU
überhaupt gesetzt ist. Und wenn nicht, setzt delay.h es selber. Hier:
less /usr/lib/avr/include/util/delay.h
1
#ifndef F_CPU
2
/* prevent compiler error by supplying a default */
3
# warning "F_CPU not defined for <util/delay.h>"
4
# define F_CPU 1000000UL
5
#endif
Wenn du sehen willst, was der Präprozessor aus deinem .c File macht, gib
dem Compiler auf der Kommandozeile ein --save-temps mit. Dann findest du
zu jedem <file>.c ein <file>.i mit der Ausgabe des Präprozessors.
> Ich bin mir nicht sicher, ob du das verstanden hast.
Du hast Recht. Der Wert wurde in meinem Programm überschrieben, aber
halt zu spät. Deshalb hat's nicht wie erwartet funktioniert. Aber das
mit dem Ersatz als reiner Text war mir nicht klar.
Danke für Deine ausführliche Beschreibung, und den Tipp mit
"--save-temps" werde ich mir anschauen. Du hast einem Hobbybastler
weitergeholfen. :)
Ich frage mich nur noch, warum in eclipse dieselbe Konstellation von
"define" und "include" in falscher Reihenfolge keine Folgen hatte.
Stephan E. schrieb im Beitrag #6499975
>> Ich frage mich nur noch, warum in eclipse dieselbe Konstellation von> "define" und "include" in falscher Reihenfolge keine Folgen hatte.
Weil Eclipse das "-DF_CPU=128000" richtig in die Commandline des
Compilers einfügt und damit das Makro F_CPU global definiert ist.
Eine eigene Frage?
Dieser Thread ist über 5 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.