Forum: Mikrocontroller und Digitale Elektronik attiny85: gleiches Programm - unterschiedliche Geschwindigkeit


von Stephan E. (loetzinn02)


Lesenswert?

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:
1
avr-gcc -c -mmcu=attiny85 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -DF_OSC=128000 -MD -MP -MF .dep/main.o.d main.c -o main.o
2
In file included from main.c:17:0:
3
/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?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Axel S. (a-za-z0-9)


Lesenswert?

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?

von Stephan E. (loetzinn02)


Lesenswert?

> 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.

von Stefan F. (Gast)


Lesenswert?

> -DF_OSC=128000

Da ist der Tippfehler, es muss F_CPU heissen.

von Axel S. (a-za-z0-9)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stephan E. schrieb:
> avr-gcc ... -DF_OSC=128000 ...

Versuch stattdessen mal

> avr-gcc ... -DF_OSC=128000 -DF_CPU=F_OSC ...

damit F_CPU define'd ist.

von Stephan E. (loetzinn02)


Lesenswert?

> 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.

von Carl D. (jcw2)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.