Datum:
Hallo zusammen, ich beginne gerade mich mit AVR uz beschäftigen. In meinem ersten Programm wollte ich einen LED an PB5 im Viersekundentakt blinken lassen, d.h. 4 Sekunde an und 4 Sekunde aus. Das Programm sieht so aus:
#include <avr/io.h> #include <util/delay.h> int main( void ) { DDRB = ( 1 << PB5 ); while( 1 ) { PORTB ^= ( 1 << PB5); _delay_ms(4000.0); } return 0; } |
F_CPU ist auf 8000000UL gesetzt:
avr-gcc -mmcu=atmega328p -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT LED.o -MF dep/LED.o.d -c ../LED.c |
Unerwarteterweise ist die LED jedoch nur ca 1 Sekunde an und aus. Ich benutze einen ATMega 328p. Als Takt ist der interne Oszillator mit 8 MHz konfiguriert. Folgende Fuses sind programmiert: SUT0, CKSEL3, CKSEL2, CKSEL0. Avrdude sagt beim Auslesen der Fuses folgendes: lfuse=0xe2, hfuse=0xd9, efuse=0x04. Wenn ich
_delay_ms(4000.0);
|
durch
for(int i=0; i<4000; i++) {
_delay_ms(1.0);
}
|
ersetze ändert sich nichts am zeitlichen Verhalten. Was mache ich falsch?
Datum:
Thomas Boeck schrieb: > lfuse=0xe2 Wenn ich nichts übersehen habe, sollte er damit mit ~8 MHz (interner Osz.) laufen. Sicher, daß der Wert von lfuse stimmt? Es riecht ja irgendwie nach programmiertem CKDIV8...
Datum:
So etwas macht man immer mit einem Timer! Die util/delay.h Funktionen sind als kurze Warteschleifen für Entprellung, LCds, ... gedacht und kein bisschen genau!!! Mit freundlichen Grüßen, Valentin Buck
Datum:
Aber wenn _delay nicht stimmt, stimmt der Timer genauso wenig.
Datum:
Hi If you are sure the AVR is running woth the correct clockfrequency. There is a bug in the delay.h library in avr-libc-1.7.0 Are you using WinAVR2010 (it uses avr-libc-1.7.0)? http://www.avrfreaks.net/index.php?name=PNphpBB2&f... Maybe try this library , for a test. http://www.avrfreaks.net/index.php?module=Freaks%2... mfg Bingo
Datum:
Hello Bingo, i used the actual AVR toolchain from the atmel website. This toolchain seems to contain the _delay_ms() bug.
#define __HAS_DELAY_CYCLES 0 |
and also
#include "delay_x.h" |
resovled the problem. Thanks for the clue. Thomas
Datum:
Jörg has released a fixed delay.h , you can use it until avr-libc-1.7.1 is released. http://www.avrfreaks.net/index.php?name=PNphpBB2&f... /Bingo
Datum:
Angehängte Dateien:Bingo schrieb: > Jörg has released a fixed delay.h , you can use it until avr-libc-1.7.1 > is released. Der Einfachheit halber hier nochmal als Anhang (ich glaube, die Anhänge bei avrfreaks.net bekommt man nur zu sehen, wenn man sich dort anmeldet). Sorry für die vergurkte Version von delay.h in avr-libc 1.7.0, die geht auf meine Kappe.
Datum:
Atmel lässt die Leute da ja wirklich eiskalt auflaufen. Da gibts nämlich sogar heute noch die kaputte Version zum Download. Wenn ich jetzt nicht zufällig auf diese Seite hier getoßen wäre, hätte ich langsam angefangen an mir zu zweifeln. Gibts da sonst noch irgendwelche Bugs, die Atmel verschweigt?
Datum:
Naja, die kaputte Version des avr-libc-Quellcodes bekommst du ja auch nach wie vor zum Download angeboten. Release ist release, einen Bug kann man in einem existierenden Release nicht mehr nachträglich reparieren. Im Rahmen von AVR Studio 5 solltest du bei Atmel eine aktuelle Version bekommen können.
Datum:
Jürgen Hinze schrieb: > Atmel lässt die Leute da ja wirklich eiskalt auflaufen. Da gibts nämlich > sogar heute noch die kaputte Version zum Download. Sicher? Kannst Du mal den Link posten? Ein WINAVR mit avr-libc 1.7.0 existiert meines Wissens nicht. Der letzte WINAVR - 20100110 benutzt die avr-libc 1.6.7 und die enthält den Bug noch nicht. Der Bug ist also nur für Linux-er relevant, die sich ihren AVR-GCC selber compilieren können. Peter
Datum:
Peter Dannegger schrieb: > Jürgen Hinze schrieb: >> Atmel lässt die Leute da ja wirklich eiskalt auflaufen. Da gibts nämlich >> sogar heute noch die kaputte Version zum Download. > > Sicher? > Kannst Du mal den Link posten? Bin zwar nicht Jürgen, hab aber den Link :) http://www.atmel.com/dyn/resources/prod_documents/... Auch über die Webseiten von Atmel zu finden auf der Übersichtsseite zum AS4 (dort aber mit Registgrierung):
AVR Toolchain Installer (87 MB, updated 9/10) For use with AVR Studio 4.18 SP3 |
http://www.atmel.com/dyn/products/tools_card.asp?t...
Datum:
... schrieb: > Bin zwar nicht Jürgen, hab aber den Link :) > > http://www.atmel.com/dyn/resources/prod_documents/... Stimmt, die ist neuer als der letzte WINAVR. Gibt es ne Möglichkeit, sich die libc-Version anzeigen zu lassen, die der GCC verwendet? Peter
Datum:
Peter Dannegger schrieb: > Gibt es ne Möglichkeit, sich die libc-Version anzeigen zu lassen, die > der GCC verwendet? Bei WinAVR gibt es ein define: _AVR_LIBC_VERSION_STRING_ Edit: in avr/version.h
Datum:
@Jörg * Wer defniert __HAS_DELAY_CYCLES ? Ist das built-in? Um zu erkennen, ob eine Version ein bestimmtes Builtin mitbringt, mach ich ein entsprechendes uppercase Builtin-Define. Jedenfalls schien mir das als Name naheliegend; für __builtin_avr_swap also __BUILTIN_AVR_SWAP. * Funktioniert das __builtin_avr_delay_cycles auch mit -O0 zusammen? Das Builtin selbst funktioniert zwar, aber es verlangt eine Konstante. O0 faltet zwar Konstanten, aber wenn ich keine Konstante sehe, gebe ich in 4.7 einen Fehler aus.
Datum:
Johann L. schrieb: > @Jörg > > * Wer defniert __HAS_DELAY_CYCLES ? Der configure-Script der avr-libc. Das hat natürlich zur Folge, dass eine compilierte avr-libc nicht mehr portabel auf einen anderen Compiler ist als den, mit dem sie compiliert worden ist, aber die Einschränkung hielt ich für vertretbar, und was besseres hatte ich nicht gefunden. > ob eine Version ein bestimmtes Builtin mitbringt, mach ich ein > entsprechendes uppercase Builtin-Define. Hatte ich bei delay_cycles nicht gefunden. Gut, der Patch ist natürlich auch noch nicht drin, Anatolij mag den irgendwie nicht. > * Funktioniert das __builtin_avr_delay_cycles auch mit -O0 zusammen? Dachte ich zumindest. > Das Builtin selbst funktioniert zwar, aber es verlangt eine Konstante. > O0 faltet zwar Konstanten, aber wenn ich keine Konstante sehe, gebe > ich in 4.7 einen Fehler aus. Ja, einen Fehler für nicht-Konstanten fände ich sowieso gut. Die ganzen delay-Dinger sind ja per definitionem nur für Konstanten konzipiert, aber immer wieder kommt mal jemand daher, der das (meist aus Unwissenheit, wer liest schon Doku?) ignoriert.
Datum:
Jörg Wunsch schrieb: > Johann L. schrieb: >> @Jörg >> >> * Wer defniert __HAS_DELAY_CYCLES ? > > Der configure-Script der avr-libc. Das hat natürlich zur Folge, > dass eine compilierte avr-libc nicht mehr portabel auf einen anderen > Compiler ist als den, mit dem sie compiliert worden ist, aber die > Einschränkung hielt ich für vertretbar, und was besseres hatte ich > nicht gefunden. > >> ob eine Version ein bestimmtes Builtin mitbringt, mach ich ein >> entsprechendes uppercase Builtin-Define. > > Hatte ich bei delay_cycles nicht gefunden. Gut, der Patch ist > natürlich auch noch nicht drin, Anatolij mag den irgendwie nicht. Den Patch hab ich nicht 1:1 übernommen. http://gcc.gnu.org/onlinedocs/gcc/AVR-Built_002din... http://gcc.gnu.org/viewcvs?view=revision&revision=172416 Etwas seltsam finde ich manche Builtins schon; die gingen genauso in inline asm. Und Arithmetik wie FMUL wäre vor allem für Maschinen ohne Multiplikation sinnvoll (per libgcc), wo es ein FMUL gibt, ist das Builtin trivial... >> * Funktioniert das __builtin_avr_delay_cycles auch mit -O0 zusammen? > > Dachte ich zumindest. > >> Das Builtin selbst funktioniert zwar, aber es verlangt eine Konstante. >> O0 faltet zwar Konstanten, aber wenn ich keine Konstante sehe, gebe >> ich in 4.7 einen Fehler aus. > > Ja, einen Fehler für nicht-Konstanten fände ich sowieso gut. Die > ganzen delay-Dinger sind ja per definitionem nur für Konstanten > konzipiert, aber immer wieder kommt mal jemand daher, der das (meist > aus Unwissenheit, wer liest schon Doku?) ignoriert. Ich erinnere mich an Probleme bei Code wie
{
unsigned long i = 10;
__builtin_avr_delay_cycles (i); // oder i+4
} |
oder ähnlichen einfachen Fällen, wo der Wert des Arguments zwar prinzipiell zur Compilezeit bekannt ist, aber das Builtin aufgrund von O0 keine Konstante sieht. Das wäre ziemlich blöd, weil man den Code dann nicht einfach mal mit O0 testen könnte. Andererseits kann ich auch nicht in eine Funktion, die eine Konstante erwartet, ein Register geben. Einzige Lösung wäre eine Bibliotheksfunktion mit variablem fuzzy delay nebst einer gcc-Warnung, daß diese benutzt wird.
Datum:
Johann L. schrieb: > Den Patch hab ich nicht 1:1 übernommen. > > http://gcc.gnu.org/onlinedocs/gcc/AVR-Built_002din... > http://gcc.gnu.org/viewcvs?view=revision&revision=172416 OK. Vielleicht baue ich das nochmal um, wenn deine Version dann eine gewisse Verbreitung erreicht hat. Oder die Heuristik via ./configure, aber ein Überschreiben, falls _BUILTIN... dann zur Compilezeit der Applikation existiert. > Ich erinnere mich an Probleme bei Code wie >
{
> unsigned long i = 10;
> __builtin_avr_delay_cycles (i); // oder i+4
> } |
> > oder ähnlichen einfachen Fällen, wo der Wert des Arguments zwar > prinzipiell zur Compilezeit bekannt ist, aber das Builtin aufgrund von > O0 keine Konstante sieht. Ja, der ist aber eben auch nicht wirklich konstant, da beispiels- weise der Nutzer vor dem Debugger auf die Schnapsidee kommen könnte, i einen anderen Wert zuzuweisen. Wie sieht es aus, wenn `i' zusätzlich noch als `const' gekennzeichnet ist? Unter C++ wäre es ja dann eindeutig eine Konstante, aber unter C vermutlich nach wie vor nicht, oder? Naja, wer in C Konstanten braucht, muss halt nach wie vor #define benutzen, auch im 3. Jahr- tausend. :-/
Datum:
Jörg Wunsch schrieb: >> * Funktioniert das __builtin_avr_delay_cycles auch mit -O0 zusammen? > > Dachte ich zumindest. Wird das __builtin_avr_delay_cycles bei -O0 überhaupt benutzt? Aus delay.h (1.7.0)
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) extern void __builtin_avr_delay_cycles(unsigned long); __builtin_avr_delay_cycles(__tmp); #else |
Datum:
hey leute bin schon ne ganze weile auf dieser webside am surfen, danke für alle beiträge hat mir sehr geholfen!!! nun habe ich jedoch ein problem wo ich net mehr weiter weiß:
#include <avr/io.h> #ifndef F_CPU /* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert (z. B. durch Übergabe als Parameter zum Compiler innerhalb des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die "nachträgliche" Definition hinweist */ #warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert" #define F_CPU 3686400UL /* Quarz mit 3.6864 Mhz */ #endif #include <util/delay.h> int main( void ) { DDRB = ( 1 << PB0 ); // PB0 an PORTB als Ausgang setzen while( 1 ) { // Endlosschleife PORTB ^= ( 1 << PB0 ); // Toggle PB0 z. B. angeschlossene LED _delay_ms(1000); // Eine Sekunde +/-1/10000 Sekunde warten... // funktioniert nicht mit Bibliotheken vor 1.6 } return 0; } |
bei dem beispiel aus dem GCC TUT soll die led im 1-sekunden takt blinken das ist bei mir etwa 4-mal langsamer statt 4-mal schneller liegt es an der taktfrequenz oder ist das auch so ein "bug" oder hab ich schon die aktuelle version von WinAVR wo _delay_ms 4-mal langsamer gemacht worden ist obwohl ich des net brauch? wo bekomme ich die alte version her? ich benutze einen Attiny2313 plz help ;) MfG Titan
Datum:
Mit welcher Taktfrequenz läuft dein Attiny2313 - noch Werkseinstellung oder hast du was geändert, wenn ja was? Kam beim Kompilieren die Meldung "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"? Werkseinstellung 1 MHz und im Programm 3.7 MHz ist fast der Faktor 4 zu schnell...