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.
Also hier der Code: #include <stdio.h> #include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> #define F_CPU 1000000 #define BAUD 9600 #include <util/setbaud.h> volatile uint16_t Mittelwert; void ADC_Konfig(void) { ADCSRA |= (1<< ADPS0) | (1<<ADPS1); ADMUX |= (1<< REFS0) | (1<<REFS1); } void USART_Konfig(void) { UBRR1H |= (UBRRH_VALUE) ; UBRR1L |= (UBRRL_VALUE) ; UCSR1C = (1<< UCSZ11) | (1<< UCSZ10); UCSR1B = (1<<TXEN1); } void Timer_Konfig(void) { TCCR1B |= (1<<WGM12); TCCR1B |= (1<<CS11); TIMSK1 |= (1<<OCIE1A); OCR1A = 1000; } void usart_putc ( unsigned char c) { while (UCSR1A != (UDRE1)) {} while (UCSR1A != (UDRE1)) {} while (UCSR1A != (UDRE1)) {} } void usart_puts (char *s) { while (*s !='\0') {usart_putc (*s); s++;} } int main(void) { DDRD |= (1<<PD3); char s[6]; ADC_Konfig(); USART_Konfig(); Timer_Konfig(); while (1) { if (Mittelwert == 0){} else { utoa(Mittelwert, s, 10); usart_puts (s); Mittelwert = 0; } } return 0; } ISR(TIMER1_COMPA_vect) { uint8_t i; uint16_t result; ADCSRA = (1<<ADEN); result = 0; for( i=0; i<10; i++ ) { ADCSRA |= (1<<ADSC); while ( ADCSRA & (1<<ADSC) ) { ; } result += ADC; } ADCSRA &= ~(1<<ADEN); Mittelwert = result / 10; }
Bin ich der Einzige, der in dem Quelltext weder "cli" noch "sei" findet?
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
Gibt der Compiler dann immer noch die gleiche Fehlermeldung aus? Also wenn Du es so wie von mir vorgeschlagen machst?
@ 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.
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.
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!
Und duch Setzen von I per Hand erkennt man, daß interrupt.h kaputt ist. Aha.
Ich bin so froh, daß mich niemand zwingt, mit "C" herumzufuhrwerken. Das mußte ich sagen, komme, was da wolle. MfG Paul
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.
1 | #include "paul.h" |
2 | int
|
3 | Meen Veut |
4 | Init heut |
5 | Weil
|
6 | Das ist geil |
7 | Taste rein |
8 | Lampe ein |
9 | Taste raus |
10 | Lampe aus |
11 | }}
|
mfg.
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:
1 | # define sei() __asm__ __volatile__ ("sei" ::: "memory")
|
2 | # define cli() __asm__ __volatile__ ("cli" ::: "memory")
|
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.