Forum: Compiler & IDEs ADC in C unter WinAVR ärgert


von Matthias W. (matt007)


Lesenswert?

ich habe ein Arduino nano3-Board und möchte darauf den ADC in Betrieb 
nehmen. Installiert ist WinAVR. Es gibt eine Datei main.c, eine adc.c 
und adc.h. Übersetzt wird durch Aufruf "make all" in einem DOS-Fenster.

Eine LED brachte ich zum Blinken. Die Umgebung scheint also 
grundsätzlich ok.

Seltsamerweise wird undefined reference to ADC_init gemeldet in Zeile 
64. Dabei steht der Funktionsaufruf "ADC_init" gar nicht in 64, sondern 
in 66.

Die Dateien sind hier
www.mweisser.50g.com/prog/main.c
www.mweisser.50g.com/prog/adc.c
www.mweisser.50g.com/prog/adc.h
www.mweisser.50g.com/prog/Makefile

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Matthias W. schrieb:
> Die Dateien sind hier

scheinbar nicht:

Fehler 404: Zugriffsfehler

kannst du sie nicht einfach hier hochladen?

von Matthias W. (matt007)


Lesenswert?

Peter II schrieb:
>> Die Dateien sind hier

Sorry Peter. Ich habe sie in einen Ordner prog gesteckt. Das habe ich 
nun oben ergänzt.

: Bearbeitet durch User
von Matthias W. (matt007)


Lesenswert?

ein neueres WinAVR scheint es nicht zu geben?

von Peter II (Gast)


Lesenswert?

Matthias W. schrieb:
> Sorry Peter. Ich habe sie in einen Ordner prog gesteckt. Das habe ich
> nun oben ergänzt.

geht immer noch nicht.


lade sie jetzt hier hoch - oder willst du nur traffic auf deiner Seite 
generieren und keine Hilfe?

von Matthias W. (matt007)


Lesenswert?

Peter II schrieb:
> geht immer noch nicht.

es geht nun. ADC war großgeschrieben. Nun ist es klein.

Es geht mir nicht um sinnlosen Traffic auf der Seite. Im Gegenteil. Die 
Fehler sollen raus und dazu möchte ich die Änderungen jedesmal gleich 
wieder online stellen, statt sie hier im Forum breitzutreten.

von Stefan E. (sternst)


Lesenswert?

Ich bezweifle, dass ADC.c überhaupt kompiliert und mitgelinkt wird, denn 
das hier
1
SRC += \
2
#usart.c \
3
#dataflash.c \
4
ADC.c \
5
delay.c \
funktioniert sicher nicht so, wie von dir gewünscht.

von Matthias W. (matt007)


Lesenswert?

Stefan Ernst schrieb:
> funktioniert sicher nicht so, wie von dir gewünscht.

Danke Stefan für den Hinweis. Du meinst die auskommentierten Zeilen 
funktionieren so nicht? Eigentlich sollte die Raute doch den Rest 
entwerten?

: Bearbeitet durch User
von Stefan E. (sternst)


Lesenswert?

Matthias W. schrieb:
> Eigentlich
> sollte die Raute doch den Rest entwerten?

Richtig, den Rest der Zeile.
Und was genau ist in dem Fall dieser "Rest"?

: Bearbeitet durch User
von Matthias W. (matt007)


Lesenswert?

Stefan Ernst schrieb:
> Richtig, den Rest der Zeile.
> Und was genau ist in dem Fall dieser "Rest"?

bei der einen Zeile ist es "usart.c \" was nicht beachtet wird und
bei der anderen Zeile ist es "dataflash.c \".
Beachtet werden sollte also "ADC.c \". Was ist so falsch daran?

Dieses Makefile funktionierte einwandfrei:
http://www.mweisser.50g.com/prog/Makefile_old

von Matthias W. (matt007)


Lesenswert?

Matthias W. schrieb:
> Dieses Makefile funktionierte einwandfrei:
> http://www.mweisser.50g.com/prog/Makefile_old

es steht da: "If there is more than one source file, append them above, 
or modify and uncomment the following."

kann man denn nicht zeilenweise "modifyen" oder "uncommenten"?

von Stefan E. (sternst)


Lesenswert?

Matthias W. schrieb:
> Beachtet werden sollte also "ADC.c \".

Und genau das bezweifle ich.
Welche Bedeutung hat das \ am Ende der Zeilen?
Wie sieht also die "logische" Zeile aus?
Was gehört demnach alles zum "Rest der Zeile" nach dem ersten #?


Außerdem müsstest du doch am Output des make all direkt sehen können, ob 
es nun kompiliert/gelinkt wird, oder nicht.

von Matthias W. (matt007)


Lesenswert?

Stefan Ernst schrieb:
> Außerdem müsstest du doch am Output des make all direkt sehen können, ob
> es nun kompiliert/gelinkt wird, oder nicht.

er bricht ja mit dem Fehler ab. Die Frage eingangs war warum der Fehler 
in der falschen Zeile gemeldet wird. Wie ist das möglich? Normalerweise 
sollte GCC soll den Fehler in der richtigen Zeile melden. Oder nicht?

Das war die Frage ganz oben:
"Seltsamerweise wird undefined reference to ADC_init gemeldet in Zeile
64. Dabei steht der Funktionsaufruf "ADC_init" gar nicht in 64, sondern
in 66."

von Paul (Gast)


Lesenswert?

Ohne einen Quellcode in diesem Thread ist der Thread für die Zukunft 
wertlos. Oft kommen Leute nach Jahren über einen Thread auf die Lösung 
Ihres Problems. Alleine aus diesem Grund würde ich mich schon weigern 
hier zu helfen.

von Peter II (Gast)


Lesenswert?

Matthias W. schrieb:
> "Seltsamerweise wird undefined reference to ADC_init gemeldet in Zeile
> 64. Dabei steht der Funktionsaufruf "ADC_init" gar nicht in 64, sondern
> in 66."

poste mal den genauen Output.

von Stefan E. (sternst)


Lesenswert?

Matthias W. schrieb:
> er bricht ja mit dem Fehler ab.

Aber davor ist doch noch diverser Output, z.B. auch die Kommandozeile 
fürs Linken. Da kann man dann doch sehen, ob da adc.o mit auftaucht, 
oder nicht.

Matthias W. schrieb:
> Die Frage eingangs war warum der Fehler
> in der falschen Zeile gemeldet wird.

Sorry, mein Fehler, ich dachte du wärst an der Beseitung des Fehlers 
interessiert.

von Matthias W. (matt007)


Lesenswert?

Peter II schrieb:
> poste mal den genauen Output.

mit make all>text1.txt habe ich die Ausgabe umgeleitet:
siehe http://www.mweisser.50g.com/prog/text1.txt
leider fehlt am Ende etwas. Da steht
main.o: In function 'main':
C:\doc...../main.c:64 undefined reference to 'ADC_init'
make: *** [main.elf] Error 1.

von Matthias W. (matt007)


Lesenswert?

Stefan Ernst schrieb:
> Aber davor ist doch noch diverser Output, z.B. auch die Kommandozeile
> fürs Linken. Da kann man dann doch sehen, ob da adc.o mit auftaucht,
> oder nicht.

ado.o sehe ich da nicht. Das liegt schon an der Stelle wo Du vermutet 
hast. Wenn ich adc.c ganz oben hinschreibe geht es weiter bis zum 
nächsten Fehler.

> Sorry, mein Fehler, ich dachte du wärst an der Beseitung des Fehlers
> interessiert.

ist nicht Dein Fehler. Mich interessiert beides. Der Fehler muss weg. Da 
bin ich dran und dank Dir ein Stück weiter.

Außerdem würde ich gerne wissen warum der Fehler in der falschen Zeile 
gemeldet wird. Solche Fehler erschweren die Fehlersuche. Wenn es nur 2 
Zeilen falsch ist wie hier mag es noch gehen.

Wenn es jedoch 10 Zeilen sind oder mehr kann man sich ggf. totsuchen.

von Peter II (Gast)


Lesenswert?

dort sieh man schön, das adc.c nicht kompiliert wird und auch dem linker 
nicht übergeben wird.

von Peter II (Gast)


Lesenswert?

Matthias W. schrieb:
> Außerdem würde ich gerne wissen warum der Fehler in der falschen Zeile
> gemeldet wird. Solche Fehler erschweren die Fehlersuche.

hier helfen sie aber nicht weiter. Du hast ein linker-Fehler. Da spielt 
der Quellcode zu 99% keine rolle mehr.

Fehler mit "undefined reference" deuten auf eine fehlende lib oder ein 
fehlende Objekt hin.

von Matthias W. (matt007)


Lesenswert?

Paul schrieb:
> Ohne einen Quellcode in diesem Thread ist der Thread für die Zukunft
> wertlos. Oft kommen Leute nach Jahren über einen Thread auf die Lösung
> Ihres Problems. Alleine aus diesem Grund würde ich mich schon weigern
> hier zu helfen.

ich verstehe Deine Ansicht Paul. Es steht halt jede Menge Mist noch in 
meinem Code. Viel davon muss noch geklärt und bereinigt werden. Daran 
arbeite ich. Daher wollte ich das Forum nicht mit alledem dauerhaft 
belasten und hier nur das Wesentliche bringen das auch andere dann 
weiterbringt.

In der main.c steht beispielsweise eine Menge auskommentierter 
Assembler. Wem nützt das später? Das kann raus wenn der Teil in C steht 
und arbeitet. Für mich ist das momentan eine Gedächtnisstütze.

Ebenso steht eine Interruptvektortabelle in Assembler da. Da weiß ich 
noch gar nicht wie ich das brauchbar in C implementieren soll. Auch den 
UART-Teil muss ich noch machen. Das soll mit Interrupt gehen.

Wenn ein Zeichen kommt wie z.B. "S", so soll der Wandler gestartet 
werden und z.B. 200 Zeichen hintereinander ins RAM ablegen. Das kann 
freilaufend sein - also z.B. alle 104us ein 10bit Datenwort ins RAM. 
Oder es wird über einen Timer gemacht. Freilaufend reicht mir am Anfang.

Ich möchte die Zeitbasis des Oszis damit vermessen. Da ich kein DSO habe 
möchte ich es damit machen.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Matthias W. schrieb:
> Ebenso steht eine Interruptvektortabelle in Assembler da. Da weiß ich
> noch gar nicht wie ich das brauchbar in C implementieren soll. Auch den
> UART-Teil muss ich noch machen. Das soll mit Interrupt gehen.

wäre es nicht sinnvoll sich vorher mal ein paar Grundlagen anzulesen?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

von Matthias W. (matt007)


Lesenswert?

Peter II schrieb:
> hier helfen sie aber nicht weiter. Du hast ein linker-Fehler. Da spielt
> der Quellcode zu 99% keine rolle mehr.

und warum kommt dann die Meldung main.c:64?

Ist mit 64 nicht die Zeile gemeint wo das Problem ist?

> Fehler mit "undefined reference" deuten auf eine fehlende lib oder ein
> fehlende Objekt hin.

ja Peter, das ist ja auch so. Da hat der GCC recht. Dieser Fehler 
lag/liegt darin daß die Auskommentierungen die ich im Makefile machte so 
nicht verstanden werden. Daher habe ich nun die Zeile mit adc.c ganz 
nach oben über die Auskommentierungen geschoben. Da geht es.

von Matthias W. (matt007)


Lesenswert?

Peter II schrieb:
> wäre es nicht sinnvoll sich vorher mal ein paar Grundlagen anzulesen?
> http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

Danke für den Link Peter. Mit Assembler lief das ja alles schon mal 
prima. Es ist mir auch klar daß man mit
#include <avr/interrupt.h> das Include hinzunimmt. sei(); ist klar und 
cli();

Also nutze ich mit WinAVR2010 die neuen defines?
#define INT0_vect  _VECTOR(1)
#define INT1_vect  _VECTOR(2)
#define TIMER2_COMP_vect  _VECTOR(3) usw.

und statt der Interrupttabelle nehme ich dann diese Funktionen?
ISR(INT0_vect)
{
    /* Interrupt Code */
}

ISR(TIMER0_OVF_vect)
{
    /* Interrupt Code */
}

ISR(USART_RXC_vect)
{
    /* Interrupt Code */
}

so weit ist das dann klar.

Macht es Sinn das erst mal mit WINAVR2010 zu machen oder ist es besser 
eine neuere Version zu nehmen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wahrscheinlich gammelt irgendwo noch ain altes main.o rum, weil durch 
das fehlerhafte Makefile auch main.c nicht compiliert wird.

Der Linker zieht sich dann die Zeile zum undefinierten Symbols ADC_init 
aus dem alten main.o.

von Matthias W. (matt007)


Lesenswert?

Johann L. schrieb:
> Wahrscheinlich gammelt irgendwo noch ain altes main.o rum, weil durch
> das fehlerhafte Makefile auch main.c nicht compiliert wird.

Danke für den Hinweis Johann !

> Der Linker zieht sich dann die Zeile zum undefinierten Symbols ADC_init
> aus dem alten main.o.

das wäre denkbar. Nur dachte ich halt wenn man "make clean" macht - wird
damit nicht das alte "main.o" gelöscht? Komisch.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mit deinen komischen Kommentaren ist das Makefile nicht mehr valide. 
make bricht also bei ADC.c mit einem Fehler ab.  Wo kein gültig 
Makefile, da auch kein make clean...

von Matthias W. (matt007)


Lesenswert?

Johann L. schrieb:
> Mit deinen komischen Kommentaren

das war aus Auskommentierung gedacht. Viele Zeilen werden so 
auskommentiert im Makefile.

> make bricht also bei ADC.c mit einem Fehler ab. Wo kein gültig
> Makefile, da auch kein make clean...

abgebrochen hat das "Makefile" nicht. Es wurde kompiliert und gelinkt. 
Nur eben ohne Einbeziehung von adc.c.

Daher kam dann die Fehlermeldung mit Angabe der falschen Zeilennummer. 
Warum diese falsche Nummer?

make clean arbeitet. Das löscht die main.o etc.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Matthias W. schrieb:
> das war aus Auskommentierung gedacht. Viele Zeilen werden so
> auskommentiert im Makefile.

Aber wenn die Zeile mit \ abgeschlossen wird, dann sagst Du damit aus, 
dass die logische Zeile in der nächsten physikalischen Zeile fortgeführt 
wird.

Und damit hast Du den folgenden Rest auch auskommentiert.

Ergo: Der Fehler sitzt zwischen den Ohren und nicht beim make.

von Matthias W. (matt007)


Lesenswert?

Frank M. schrieb:
> Und damit hast Du den folgenden Rest auch auskommentiert.

ok.

> Ergo: Der Fehler sitzt zwischen den Ohren und nicht beim make.

Danke Frank. Das ist mir eine Weile klar und der Fehler auch behoben.
Unklar ist mir nach wie vor die Fehlermeldung in main.c auf die falsche 
Zeile. Das ist mir noch immer nicht plausibel. Warum war das 2 Zeilen 
daneben? Das war die Anfangsfrage - siehe oben.

Erklärungsversuche lauteten - er nimmt ein altes .o file. Er löscht 
diese mit make clean jedoch.

Hat so ein Problem mit fehlerhafter Zeilennummer denn niemand jemals 
gehabt?

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Meine Erklärung wäre, daß durch Optimierung die Zeilenzuordnung nicht 
mehr stimmt. Der Linker muß die Infos über die Zeilennummer ja aus den 
Debug-Informationen holen, da es im o-File gar keine Zeilen mehr gibt. 
Und im Debugger ist es ja bekannt, daß bei eingeschalteten Optimierungen 
die Zeilen nicht mehr passen.

von Matthias W. (matt007)


Lesenswert?

Danke Rolf. Die Zeilennummern sind ja der einzige Weg zum Fehler. Wenn 
die nicht stimmen wird es schwerer zu finden wo das ist. Bei längerem 
Code könnte der Unterschied deutlich größer sein.

Dieser Code besteht bis zum Fehler ja nur ein ganz wenigen Zeilen. Eine 
LED wird an und ausgemacht - mehr nicht.

von Stefan E. (sternst)


Lesenswert?

Matthias W. schrieb:
> Die Zeilennummern sind ja der einzige Weg zum Fehler. Wenn
> die nicht stimmen wird es schwerer zu finden wo das ist.

Ach komm, jetzt übertreib mal nicht. Die Fehlermeldung enthält auch den 
Symbolnamen, und damit führt auch die Suchfunktion deines Editors zum 
Fehler.

von Matthias W. (matt007)


Lesenswert?

Danke Stefan. Das klärt leider nicht die Ursache.

von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

hier der aktuelle Stand. make clean arbeitet (siehe make_clean.txt). 
make all arbeitet (siehe make_all.txt und make_all.png) und erzeugt eine 
Warnung in usart.c: Zeile 229. USART_RXC_vect appears to be a misspelled 
signal handler. In der Zeile steht: ISR(USART_RXC_vect). Muss das 
USART_RXC0_vect heißen?

Weiter gibt es eine Fehlermeldung usart.o: In function USART_sendmsg:
C:\.... usart.c:255 undefined reference to ADC2RAW.

Der Fehler selbst ist klar. Die Funktion hatte ich auskommentiert. 
Unklar ist warum der Fehler in der falschen Funktion gemeldet wird - 19 
Zeilen daneben. Ein Bug oder ein Feature?

von Uwe (de0508)


Lesenswert?

Hallo Matthias,

ich würde alle Headerdateien noch mit
1
#ifdef _INCL_<HEADER_H>_INCL
2
#define _INCL_<HEADER_H>_INCL
3
:
4
#endif

erweitern, um mehrfaches laden und auswerten zu vermeiden !

von Matthias W. (matt007)


Lesenswert?

Danke für den Hinweis Uwe. Das baue ich ein.

von Rolf M. (rmagnus)


Lesenswert?

Uwe S. schrieb:
> ich würde alle Headerdateien noch mit#ifdef _INCL_<HEADER_H>_INCL
> #define _INCL_<HEADER_H>_INCL
> :
> #endif
> erweitern, um mehrfaches laden und auswerten zu vermeiden !

Wozu soll denn deru Unterstrich am Anfang gut sein? Der ist eigentlich 
verboten.

von Matthias W. (matt007)


Lesenswert?

Danke Magnus und Uwe !

Ich bin kein Fachmann für dies Mehrfach-Include-Thema. Auf der Seite 
http://stackoverflow.com/questions/14290026/linking-h-files-with-c-with-ifdef-header-guards 
steht ein Beispiel - hier angepasst an adc.h:

"You need to include adc.h in all files that uses the functions that are 
defined in adc.h. So you need to put a #include <adc.h> in both files. 
To avoid that adc.h is loaded several times, you need the directives 
#ifdef:

file adc.h

#ifndef ADC_H
#define ADC_H
...
void func(..);
void func(..);
#endif

und Datei adc.c:

#include "adc.h"

So müsste es doch gehen? Oder?

von Rolf M. (rmagnus)


Lesenswert?

Matthias W. schrieb:
> So müsste es doch gehen? Oder?

Ja, das ist der richtige Weg.
Manche machen würden vielleicht noch sowas wie ADC_H_included draus 
machen, um sicherzugehen, daß der Name nicht irgendwo schon für einen 
anderen Zweck verwendet wird. ADC_H könnte ja z.B. auch für das 
High-Byte des ADC-Ergebnisses stehen oder so. Bei solchen 
mehrfach-Belegungen wären schwer zu verstehende Fehlermeldungen des 
Compilers das Resultat.

von Matthias W. (matt007)


Lesenswert?

Rolf Magnus schrieb:
> Ja, das ist der richtige Weg.
> Manche machen würden vielleicht noch sowas wie ADC_H_included draus
> machen, um sicherzugehen

Da hast Du sicher recht. Daher hat Uwe wohl das "_INCL" angehängt. Das 
kann ich ja machen.

Weißt Du zufällig etwas zu dieser Warnung in usart.c: Zeile 229. 
"USART_RXC_vect appears to be a misspelled signal handler". In Zeile 
steht: ISR(USART_RXC_vect). Sollte das USART_RXC0_vect heißen? Es müsste 
doch eine Include-Datei geben wo das definiert ist?

von Uwe (de0508)


Lesenswert?

Matthias W. schrieb:
> Weißt Du zufällig etwas zu dieser Warnung in usart.c: Zeile 229.
> "USART_RXC_vect appears to be a misspelled signal handler". In Zeile
> steht: ISR(USART_RXC_vect). Sollte das USART_RXC0_vect heißen? Es müsste
> doch eine Include-Datei geben wo das definiert ist?

Suche mal in <avr/io.h> dann kommst Du zum Ziel oder schaust im 
Datenblatt nach.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Matthias W. schrieb:
> hier der aktuelle Stand. make clean arbeitet (siehe make_clean.txt).
> make all arbeitet (siehe make_all.txt und make_all.png) und erzeugt eine
> Warnung in usart.c: Zeile 229. USART_RXC_vect appears to be a misspelled
> signal handler. In der Zeile steht: ISR(USART_RXC_vect). Muss das
> USART_RXC0_vect heißen?

Warum probierst Du es nicht einfach aus? Was für einen µC hast Du denn? 
Der Source scheint jedenfalls für einen ATmega328 zu sein. Für diesen 
stimmt das so. Welche Version von avr-gcc benutzt Du? Die Version 4.8.1 
hat die Macke, bei jeder ISR diesen Fehler auszugeben, obwohl es kein 
Fehler ist.

Also: Welcher µC?

> Weiter gibt es eine Fehlermeldung usart.o: In function USART_sendmsg:
> C:\.... usart.c:255 undefined reference to ADC2RAW.

> Der Fehler selbst ist klar. Die Funktion hatte ich auskommentiert.

Ja, in adc.c.

> Unklar ist warum der Fehler in der falschen Funktion gemeldet wird - 19
> Zeilen daneben. Ein Bug oder ein Feature?

Füge doch mal in usart.c oben ein paar Leerzeilen ein und schaue dann, 
ob sich die Fehlermeldung zeilenmäßig verschiebt. Wenn nicht, dann liegt 
bei Dir noch irgendwo ein anderes usart.o rum.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Folgende Ursachen fallen mir noch ein:

- Header, die nicht mit einem Zeilenumbruch enden.

- Alte Compilerversion (4.3). Die älteste noch unterstützte GCC-Version
  ist die 4.8.  WinAVR selbst ist (fast komplett) tot.

- -Wl,--relax wirkt auch auf Debug-info und evtl. Adresszuordnungen.
  Wenn der Assembler bekannte Symboldifferenzen aufglöst hat, können
  diese vom Linker natürlich nicht mehr angepasst werden.
  --> -mrelax anstatt -Wl,--relax nebst hinreichend neuen avr-Tools.
      Mit -v überprüfen, ob as mit relax aufgerufen wird.

Überprüf mal ob mit -save-temps -P die Zeilennummer zum .i stimmt.

von Matthias W. (matt007)


Lesenswert?

Uwe S. schrieb:
> Suche mal in <avr/io.h> dann kommst Du zum Ziel

prima Hinweis Uwe. Diese io.h bindet die iom328p.h ein. Am Ende steht 
die Vektortabelle. Die hatte ich gesucht. Schade daß die so nicht im 
Datenblatt steht.

> oder schaust im Datenblatt nach.

da fand ich leider nichts brauchbares. Das was da stand hat nicht 
funktioniert.

von Justus S. (jussa)


Lesenswert?

Matthias W. schrieb:
> Schade daß die so nicht im
> Datenblatt steht.

nicht schade, denn die hätte da nix zu suchen. "USART_RXC0_vect" ist 
schließlich nur ein Name, der für einen µC in jeder Programmierumgebung 
anders sein kann...

von Matthias W. (matt007)


Lesenswert?

Frank M. schrieb:
> Matthias W. schrieb:
>> Es steht: ISR(USART_RXC_vect). Muss das USART_RXC0_vect heißen?
> Warum probierst Du es nicht einfach aus?

das habe ich gemacht. So kam ich recht zäh voran. Weder das eine noch 
das andere klappte.

> Was für einen µC hast Du denn?

den ATmega328p. Standardbestückung Arduino nano3.

> Der Source scheint jedenfalls für einen ATmega328 zu sein. Für diesen
> stimmt das so.

das dachte ich auch. Nur leider . . .
ich fand dann eine Datei group__avr__interrupts.html im WinAVR-Ordner. 
Da steht das drin was ich wissen wollte.

> Welche Version von avr-gcc benutzt Du?

avr-gcc (WinAVR 20100110) 4.3.3 wird gemeldet.

> Die Version 4.8.1
> hat die Macke, bei jeder ISR diesen Fehler auszugeben, obwohl es kein
> Fehler ist.

ok. Macht es dann einen Sinn für mich ein neueres WINAVR anzustreben?

> Füge doch mal in usart.c oben ein paar Leerzeilen ein und schaue dann,
> ob sich die Fehlermeldung zeilenmäßig verschiebt. Wenn nicht, dann liegt
> bei Dir noch irgendwo ein anderes usart.o rum.

Danke für den Hinweis Frank !

Mit dem heutigen Stand wird der Fehler undefined reference to ADC2RAW in 
usart.c:252 gemeldet. Notepad++ zeigt Zeile 268 an. Das sind 16 Zeilen 
Differenz.

Wenn ich oben 10 weitere Leerzeilen einfüge meldet er den Fehler in 
usart.c:262. Notepad++ zeigt Zeile 278 an. Also noch immer 16 Zeilen 
Differenz.

von Matthias W. (matt007)


Lesenswert?

Johann L. schrieb:
> Folgende Ursachen fallen mir noch ein:

Danke Johann.

> - Header, die nicht mit einem Zeilenumbruch enden.

das war bei mir der Fall. Nun ist überall ein "LF" am Ende. Gebracht hat 
das nichts.

> - Alte Compilerversion (4.3).

meine ist die AVR GCC 4.3.3.

> Die älteste noch unterstützte GCC-Version
> ist die 4.8.  WinAVR selbst ist (fast komplett) tot.

schaut so aus als ob es momentan keine offizielle neue Fassung gibt? Im 
Wiki ist nichts dazu eingetragen.

> - -Wl,--relax wirkt auch auf Debug-info und evtl. Adresszuordnungen.
>   Wenn der Assembler bekannte Symboldifferenzen aufglöst hat, können
>   diese vom Linker natürlich nicht mehr angepasst werden.
>   --> -mrelax anstatt -Wl,--relax nebst hinreichend neuen avr-Tools.
>       Mit -v überprüfen, ob as mit relax aufgerufen wird.

Du meinst die Zeilen 75-78 im Makefile verändern?
CFLAGS = -g -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-Wa,-adhlns=$(<:.c=.lst) \

> Überprüf mal ob mit -save-temps -P die Zeilennummer zum .i stimmt.

Du meinst "-save-temps -P" bei den CFLAGS als neue Zeile hinzufügen?

von Matthias W. (matt007)


Lesenswert?

Justus Skorps schrieb:
> nicht schade, denn die hätte da nix zu suchen. "USART_RXC0_vect" ist
> schließlich nur ein Name, der für einen µC in jeder Programmierumgebung
> anders sein kann...

ok. Das war das Schöne beim Assembler. Die Beispiele konnte man direkt 
nutzen.

von Rolf M. (rmagnus)


Lesenswert?

Justus Skorps schrieb:
> Matthias W. schrieb:
>> Schade daß die so nicht im
>> Datenblatt steht.
>
> nicht schade, denn die hätte da nix zu suchen. "USART_RXC0_vect" ist
> schließlich nur ein Name, der für einen µC in jeder Programmierumgebung
> anders sein kann...

Es steht dafür in der Doku der avr-libc, wo es auch hingehört.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Oder per Einzeiler:
 
1
$ echo | avr-gcc -mmcu=atmega328 -g3 -xc - -include avr/io.h -E -dM | grep _vect\b | sort

Das ergibt, schön alphabetisch sortiert, und ohne Tippfehler in der Doku 
oder Inkonsistenz weil Atmel mal wieder aus Langeweile die IRQ-Namen 
geändert hat:
 
1
#define ADC_vect _VECTOR(21)
2
#define ANALOG_COMP_vect _VECTOR(23)
3
#define EE_READY_vect _VECTOR(22)
4
#define INT0_vect _VECTOR(1)
5
#define INT1_vect _VECTOR(2)
6
#define PCINT0_vect _VECTOR(3)
7
#define PCINT1_vect _VECTOR(4)
8
#define PCINT2_vect _VECTOR(5)
9
#define SPI_STC_vect _VECTOR(17)
10
#define SPM_READY_vect _VECTOR(25)
11
#define TIMER0_COMPA_vect _VECTOR(14)
12
#define TIMER0_COMPB_vect _VECTOR(15)
13
#define TIMER0_OVF_vect _VECTOR(16)
14
#define TIMER1_CAPT_vect _VECTOR(10)
15
#define TIMER1_COMPA_vect _VECTOR(11)
16
#define TIMER1_COMPB_vect _VECTOR(12)
17
#define TIMER1_OVF_vect _VECTOR(13)
18
#define TIMER2_COMPA_vect _VECTOR(7)
19
#define TIMER2_COMPB_vect _VECTOR(8)
20
#define TIMER2_OVF_vect _VECTOR(9)
21
#define TWI_vect _VECTOR(24)
22
#define USART_RX_vect _VECTOR(18)
23
#define USART_TX_vect _VECTOR(20)
24
#define USART_UDRE_vect _VECTOR(19)
25
#define WDT_vect _VECTOR(6)

Oder mit
 
1
 ... | sort -n -k 2 -t(

falls man Sortierung nach IRQ-Nummer bevorzugt.

Und da im Jahre 2014 shell-Skripte bereits erfunden sind, muß man das 
auch nicht immer wieder eintippseln...

Matthias W. schrieb:
> Johann L. schrieb:
>> Überprüf mal ob mit -save-temps -P die Zeilennummer zum .i stimmt.
>
> Du meinst "-save-temps -P" bei den CFLAGS als neue Zeile hinzufügen?

Wo immer es deinem Makefile beliebt Optionen an den Compiler zu reichen. 
Oder das komplette Kommando per Hand eingeben — zum Beispiel bei 
esotherischen Plattformen, die nicht erlauben die Compileroptionen zu 
ändern.

von Matthias W. (matt007)


Lesenswert?

Justus Skorps schrieb:
> nicht schade, denn die hätte da nix zu suchen. "USART_RXC0_vect" ist
> schließlich nur ein Name, der für einen µC in jeder Programmierumgebung
> anders sein kann...

USART ist ein ziemlich eingebügerter Begriff. Der steht auch so im 
Datenblatt.

RXCO ist so wunderlich auch nicht. Steht auch im Datenblatt.

_vect. Deutet auf einen Vektor hin.

von Matthias W. (matt007)


Lesenswert?

Rolf Magnus schrieb:
>> "USART_RXC0_vect" ..
> Es steht dafür in der Doku der avr-libc, wo es auch hingehört.

Danke für den Hinweis Magnus. Dazu gehört laut 
http://nongnu.org/avr-libc/user-manual/modules.html zum Thema Interrupts 
<avr/interrupt.h>. Dies führt zu 
http://nongnu.org/avr-libc/user-manual/group__avr__interrupts.html.

Das war das was ich auch gefunden hatte.

Im Usermanual der avr-libc http://nongnu.org/avr-libc/user-manual/ steht 
auch etwas von Startup-Code:

"The AVR Libc package.. provides the basic startup code needed by most 
applications."

Startup-Code hatte ich selbst in die main.c geschrieben. Welche 
include-Datei hätte ich dazu nehmen sollen?

von Matthias W. (matt007)


Lesenswert?

Johann L. schrieb:
>
1
> $ echo | avr-gcc -mmcu=atmega328 -g3 -xc - -include avr/io.h -E -dM | 
2
> grep _vect\b | sort

vielen Dank Johann für den prima Hinweis !
Das ist ja toll wenn man das so herausbekommen kann. Genial.

von Peter II (Gast)


Lesenswert?

Matthias W. schrieb:
> Startup-Code hatte ich selbst in die main.c geschrieben. Welche
> include-Datei hätte ich dazu nehmen sollen?

warum sollte man für den Startup-Code eine include brauchen? Das ist 
mehr teil vom linker, er führ noch ein paar befehle vor main aus und 
initialisiert damit globale Variablen. Wie hast du denn so etwas selber 
geschrieben?

von Matthias W. (matt007)


Lesenswert?

Johann L. schrieb:
>>> Überprüf mal ob mit "-save-temps -P" die Zeilennummer zum .i stimmt.

Habe ich gemacht Johann:
ohne diese Zutaten im Makefile wird undefined reference in Zeile 278 
gemeldet. Der Fehler steht in Zeile 294.

mit den Zutaten im Makefile wird beim Linken gemeldet: uart.o: In 
function USART_Tx_msg  usart.i:207 undefined reference to ADC2RAW.

Die gemeldete Funktion ist falsch und die Zeilennummer passt nicht zur 
usart.c. In der neu entstandenen Datei usart.i ist die Zeile 207 die 
letzte Zeile der Funktion USART_Tx_msg (die Klammer zu).

von Matthias W. (matt007)


Lesenswert?

die positive Nachricht: Der ADC wandelt nun rasch (~alle 104us 
vermutlich) 500 ADC-Werte in Folge ins RAM. Die Werte werden dann per 
UART mit 115kbd als Integer zum PC geschickt. Das läuft - die Werte 
sehen recht plausibel aus. Damit habe ich nun den Anstieg der Zeitbasis 
erfasst.

von Matthias W. (matt007)


Lesenswert?

Peter II schrieb:
> warum sollte man für den Startup-Code eine include brauchen?

was ist überhaupt gemeint mit "Startup-Code"?
Warum steht dazu etwas in der avr-libc?

> Das ist
> mehr teil vom linker, er führ noch ein paar befehle vor main aus und
> initialisiert damit globale Variablen. Wie hast du denn so etwas selber
> geschrieben?

dann verstehen wir da unterschiedliches darunter. Ich verstand unter 
"Startup-Code" das Festlegen bestimmter Register damit der Chip 
brauchbar arbeiten kann mit der Beschaltung die er hat.

Offenbar ist der "Startup"-Code etwas was der Compiler für sich selbst 
benutzt. Damit habe ich als User also nichts zu tun.

von Karl H. (kbuchegg)


Lesenswert?

Matthias W. schrieb:

> Offenbar ist der "Startup"-Code etwas was der Compiler für sich selbst
> benutzt.

Ja. Aber nicht nur.
Startup-Code ist alles, was notwendig ist, damit main überhaupt arbeiten 
kann. Auf einem Embedded System ohne dahinter liegendes Betriebssystem 
gehört da zb auch die Initialisierung eines Stack-Pointers dazu, sofern 
die CPU so etwas hat. Initialisierung der MMU, um ein anderes Beispiel 
zu nennen. Kurz und gut: alles, was im Vorfeld ablaufen muss, damit 
main() eine gesicherte Arbeitsumgebung vorfindet. Gibt es kein 
Betriebssystem, dann umfasst der Startup Code natürlich auch die Teile, 
die ein Betriebssystem beim Hochfahren erledigt um den Computer als 
ganzes sauber 'hochzufahren'. OK, auf einem AVR ist das nicht viel, 
ändert aber nichts am Prinzip.

: Bearbeitet durch User
von Matthias W. (matt007)


Lesenswert?

Karl Heinz schrieb:
> Startup-Code ist alles, was notwendig ist, damit main überhaupt arbeiten
> kann. Auf einem Embedded System ohne dahinter liegendes Betriebssystem
> gehört da zb auch die Initialisierung eines Stack-Pointers dazu,

ok. Danke Karl-Heinz. Bei meinem Assembler-Programm für ATmega8535 hatte 
ich den Stack in den ersten Zeilen belegt. Im C-Code des AVR-Butterfly 
fand ich nichts dazu. Beim Arduino nano3 mit ATmega328p soll der Stack 
sinnvoll vorbelegt sein nach Reset. Also dazu nichts nötig.

> sofern die CPU so etwas hat.

der ATmega 328 hat einen Stack und auch eine Menge andere Register, die 
man nicht immer in der default-Stellung belassen möchte.

> Initialisierung der MMU, um ein anderes Beispiel zu nennen.

Ähnliches wie init ADC, UART rufe ich in der main.c mit Hilfe von 
eigenen Initialisierroutinen auf. Im Assembler gab es auch eine 
Initialisierung. Auch der Watchdog gehört ggf. dazu. Bisher habe ich ihn 
ignoriert. Vermutlich ist er über eine Fuse deaktiviert.

> Kurz und gut: alles, was im Vorfeld ablaufen muss, damit
> main() eine gesicherte Arbeitsumgebung vorfindet.

so sah ich das auch.

> OK, auf einem AVR ist das nicht viel, ändert aber nichts am Prinzip.

ok. Danke !

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Matthias W. schrieb:
> Johann L. schrieb:
>>>> Überprüf mal ob mit "-save-temps -P" die Zeilennummer zum .i stimmt.
>
> Habe ich gemacht Johann:
> ohne diese Zutaten im Makefile wird undefined reference in Zeile 278
> gemeldet. Der Fehler steht in Zeile 294.
>
> mit den Zutaten im Makefile wird beim Linken gemeldet: uart.o: In
> function USART_Tx_msg  usart.i:207 undefined reference to ADC2RAW.
>
> Die gemeldete Funktion ist falsch und die Zeilennummer passt nicht zur
> usart.c.

Die Meldung bezieht sich auf uart.i, nicht auf uart.c.  Vergleiche also 
die Meldung für uart.i mit uart.i, nicht mit uart.c ;-)

> In der neu entstandenen Datei usart.i ist die Zeile 207 die
> letzte Zeile der Funktion USART_Tx_msg (die Klammer zu).

Dann kann die Zeile nicht mehr bestimmt werden; in dem Fall ist die 
Angezeigte Stelle dann das Ende der Funktion; üblicherweise die 
schließende }.

Ist mit der Location für die C-Datei wohl auch so.

: Bearbeitet durch User
von Matthias W. (matt007)


Lesenswert?

Johann L. schrieb:
> Die Meldung bezieht sich auf uart.i, nicht auf uart.c.  Vergleiche also
> die Meldung für uart.i mit uart.i, nicht mit uart.c ;-)

das habe ich gemacht Johann.

>> In der neu entstandenen Datei usart.i ist die Zeile 207 die
>> letzte Zeile der Funktion USART_Tx_msg (die Klammer zu).

leider wird auch in usart.i der Fehlerort scheinbar falsch gemeldet. Ich 
verstehe den Mechanismus nicht nach dem dies geschieht.

> Dann kann die Zeile nicht mehr bestimmt werden; in dem Fall ist die
> Angezeigte Stelle dann das Ende der Funktion; üblicherweise die
> schließende }.

die Fehlermeldung hat mit der Funktion USART_Tx_msg nichts zu tun.

> Ist mit der Location für die C-Datei wohl auch so.

auch in der C-Datei wird das Ende der Funktion USART_Tx_msg als 
Fehlerort angegeben. Dasselbe Problem also.

: Bearbeitet durch User
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.