Hallo Entwickler,
ich habe zum ersten Mal ein kleines Programm für einen uC geschrieben.
Bei mir kommen nach dem Debuggen folgende Fehlermeldungen:
undefined reference to `sei'
undefined reference to `cli'
ld returned 1 exit status
In einem Thread hier im Forum habe ich gelesen, dass sich die ersten
beiden Fehler dadurch beheben lassen, wenn ich
#include <avr/interrupt.h>
in mein Programm einbinde. Das habe ich bereits getan. Allerdings
besteht der Fehler weiterhin.
Hatte jmd. von euch schon ein mal das Problem? Kann mir jemand
weiterhelfen. Das wäre wirklich freundlich.
Ich verwende AtmelStudio 6.1
Ich kann euch auch den Code posten, wenn sich heraustellen sollte, dass
ihr mir auf Grund meiner bisherigen Angaben nicht helfen könnt. Lasst es
mich wissen, falls dem so ist.
Julian K.
Julian K. schrieb:> Ich kann euch auch den Code posten, wenn sich heraustellen sollte, dass> ihr mir auf Grund meiner bisherigen Angaben nicht helfen könnt. Lasst es> mich wissen, falls dem so ist.
Ich lass es Dich hiermit wissen.
------------
soll "sei" und "cli" C oder Assembler sein?
Winfried J. schrieb:> hat der GCC keinen Inlineassembler?
Hat er. Aber dann muß ihm auch gesagt werden ("asm volatile").
Oder eben die Makros cli() und sei() benutzen.
Schreib mal anstatt:
sei(); -> SREG |= ( 1 << I );
und anstatt:
cli(); -> SREG &= ~ ( 1 << I );
Das wäre der ausführlichere Weg... Compiliere das Ganze mal und schau
dann ob das Problem immer noch besteht.
Julian K. schrieb:> Also hier der Code:
Hm... Es mag an mir liegen, aber ich sehe hier weder ein "sei" noch ein
"cli"...
Bitte poste den vollständigen Quellcode, der den Fehler verursacht.
PS: Bitte hänge das nächste Mal den Quellcode in Form einer Datei mit
der Dateiendung .c an.
Das merkwürdige ist, dass die Fehlermeldung selbst dann auftauchen, wenn
ich vor bzw. nach OCRA1A = 1000; sei() und cli() auslasse, so wie im
Code oben zu sehen ist.
Ja sry: In Bezug auf das Fehlen von sei() und cli() seht bitte mein
letzte Posting.
@ christian karle: danke für den Alternativvorschlag. Den habe ich
vergebens versucht.
@ walter tarplan: Was meinst du mit ("asm volatile"). Da muss ich doch
gleich mal googlen
Am Programm liegt es nicht. Entweder ist da was bei der Installation des
Studios schiefgegangen, oder du hast beim Anlegen des Projektes was
falsch gemacht.
Kopier doch mal den kompletten Compileraufruf hier rein. Alles, was da
im Comsolenfenster erscheint.
Oliver
@ Christian Karle: ja trotzdem funktioniert es nicht.
@ Oliver: Jo, du hast die Lösung gebracht. Ich habe einfach ein neues
Prokjekt erstellt und den Code darein kopiert. Jetzt geht's. Danke dir.
Darauf wäre ich nicht so schnell gekommen.
Und auch allen anderen einen herzlichen Danke, die sich die Mühe gemacht
haben mir helfen zu wollen. Spitzen Forum!
wetten das der hund in io.lib liegt welche durch io.h eingebunden wird.
und wo cli() und Sei() aufgerufen werden um die soft_com gegen
interupts zu schützen?
versuch mal die Reihenfolge
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 1000000
#define BAUD 9600
#include <util/setbaud.h>
möglich das der Compiler stolpert bevor die Definition erfolgt
Was soll io.lib sein? Sowas gibt's nicht. avr/io.h ist ein Header, mehr
nicht.
sei() und cli() werden in avr/interrupt.h definiert, es sind Makros.
Fehler vom Linker wie ober geschehen dann, wenn man avr/interrupt nicht
includet und sei() und cli() als Funktionsaufrufe interpretiert werden.
Das sollte aber mindestens eine Warnung vom Compiler geben!
Der Vorschlag, das I-Bit in SREG von Hand zu setzen, ist nicht gut.
Christian Karle schrieb:> Wieso sollte man das I-Bit in SREG nicht selber setzten dürfen? Nichts> andres tut der Befehl sei();... Lediglich wird das Bit 3 Takte früher> gesetzt.
Andere Frage: Warum glaubst du, daß es besser ist als es mit sei();
und cli(); zu machen? Dein toller Tip war absolut wertlos.
sei(); und cli(); tun sehr Wohl was anderes. Sie benutzen nämlich die
Aseemblerbefehle SEI und CLI, die das Setzen bzw. Zurücksetzen in einem
Taktzyklus ausführen.
mfg.
Ich habe nirgendwo geschrieben das es besser sei! Durch das manuelle
Setzten des Bits sollte lediglich überprüft werden ob das Problem an
#include <avr/interrupt.h> liegt. Es hätte durchaus möglich sein können,
dass die Datei beschädigt oder verändert wurde!
Christian Karle schrieb:> Ich habe nirgendwo geschrieben das es besser sei! Durch das manuelle> Setzten des Bits sollte lediglich überprüft werden ob das Problem an> #include <avr/interrupt.h> liegt. Es hätte durchaus möglich sein können,> dass die Datei beschädigt oder verändert wurde!
interrupt.h gehört zur Toolchain. Es ist äusserst unwahrscheinlich, daß
diese beschädigt ist. Wenn es doch so ist, ist davon auszugehen, daß die
gesamte Installation Schrott ist und wiederholt werden muß.
Wenn man sie allerdings selbst verändert hat, hat man auch nichts
anderes verdient, als daß es danach nicht mehr läuft.
1
SREG|=(1<<I);
2
SREG&=~(1<<I);
Das sind Read-Modify-Write-Operationen, die aus mehreren Befehlen
bestehen. Das bedeutet, daß insbesondere der "cli" mittendrin durch
einen Interrupt unterbrochen werden kann, was widerum zu unerwünschtem
Verhalten führen kann.
Deswegen:
Johann L. schrieb:> Der Vorschlag, das I-Bit in SREG von Hand zu setzen, ist nicht gut.
Dafür hat Atmel den Controllern extra 2 Befehle spendiert, die in einem
Zyklus abgehandelt werden.
Man sollte Anfängern nicht solche Vorschläge machen. Die gewöhnen sich
das nur unnötigerweise an. Nach dem Motto: Was einmal gut war, ist immer
gut.
mfg.
Paul Baumann schrieb:> Ich bin so froh, daß mich niemand zwingt, mit "C" herumzufuhrwerken.> Das mußte ich sagen, komme, was da wolle.>> MfG Paul
Das reimt sich ja gar nicht.
Aber man könnte in C Programme schreiben, die sich reimen. Dann wäre C
doch noch was für dich.
Johann L. schrieb:> Sowas gibt's nicht.
mag sein. aber *.h sind dafür gedacht Funktionen zu deklarieren dies mus
vor dem ersten Aufruf geschehen. Die Definition findet üblicher Weise in
einer *.lib statt.
rufen nun *.h bereits Funktionen auf welche erst später deklariert
werden kommt es zu dieser Art Fehler.
Das setzen und löschen von Interruptenablebits in eigenen Funktionen
erscheint freilich als oversiced, zumindest für einen
Assemblerproggrammierer
Winfried J. schrieb:> Johann L. schrieb:>> Sowas gibt's nicht.>> mag sein. aber *.h sind dafür gedacht Funktionen zu deklarieren dies mus> vor dem ersten Aufruf geschehen. Die Definition findet üblicher Weise in> einer *.lib statt.
Headerdateien können Funktionsprototypen enthalten, müssen sie aber
nicht. Sie können genauso gut nur Defines und Makros enthalten. Z.B. die
Adressen der Register, auf die per Registernamen zugegriffen werden
soll.
> rufen nun *.h bereits Funktionen auf welche erst später deklariert> werden kommt es zu dieser Art Fehler.
Nur in Schrottprogrammen. Eine vernünftige Headerdatei, die das
Vorhandensein einer anderen Headerdatei voraussetzt, bindet diese selbst
ein. Damit durch mehrfaches Einbinden dieser Headerdatei nicht
massenhaft Redefines entstehen, baut man da für paul.h
1
#ifndef PAUL_H
2
#define PAUL_H
3
4
//Alles , was da reingehört
5
6
#endif /*PAUL_H*/
ein.
> Das setzen und löschen von Interruptenablebits in eigenen Funktionen> erscheint freilich als oversiced, zumindest für einen> Assemblerproggrammierer
Auch ein Assemblerprogrammierer muß manche Zugriffe atomar machen.
mfg.
Winfried J. schrieb:> Johann L. schrieb:>> Sowas gibt's nicht.>> mag sein. aber *.h sind dafür gedacht Funktionen zu deklarieren dies mus> vor dem ersten Aufruf geschehen. [...]>> rufen nun *.h bereits Funktionen auf welche erst später deklariert> werden kommt es zu dieser Art Fehler.>> Das setzen und löschen von Interruptenablebits in eigenen Funktionen> [...]
Es sind eben keine Funktionen sondern funktionsähnliche Makros, wie
man leicht in avr/interrupt.h nachlesen kann:
Als Funktionsaufrufe werden sie nur dann interpretiert, wenn diese
Makros nicht vorhanden sind, etwa weil avr/interrupt.h nicht includet
wird. Das hab ich aber alles bereits oben erklärt.