AVR-Entwicklung unter FreeBSD - das _delay_ms()-Problem


Zeit ist nicht gleich Zeit


Von Thorsten Geppert am 11.01.2011, geändert 01.01.2015.

Als mein Kollege und ich letztens ein kleins Programm für einen Atmega (in unserem Fall Atmega8 und Atmega16) programmierten, fiel uns auf, dass ein Lämpchen, dass im Sekundentakt blinken sollte, das etwa vier mal schneller tat. Kompiliert und gelinkt wurde es auf einem FreeBSD 8.1 mit dem zu dem Zeitpunkt aktuellen AVR-GCC sowie der aktuellen AVR-Toolchain. Eine Rekompilierung auf Linux brachte das korrekte Resultat.

Nach einigen Recherchen fand ich einen Foreneintrag, der genau auf das Problem eingeht. Tatsächlich scheint es so zu sein, dass in einigen AVR-Toolchains gravierendere Fehler vorhanden sind. Je nach Version auch unterschiedliche, die sich unterschiedlich behandeln lassen. In diesem konkreten Fall kann der Fehler mit der Präprozessordirektive __HAS_DELAY_CYCLES, die via define zu Beginn des Programms mit 0 definiert wird, korrigiert werden. Doch vorsicht: ändert sich die Version der AVR-Libc, kann unter Umständen dieser Workarround nicht mehr funktionieren. Ein zu diesem Zeitpunkt (11.01.2011) korrekt funktionierendes Programm sieht folgendermaßen aus:

#define __HAS_DELAY_CYCLES 0

#include <avr/io.h>
#include <util/delay.h>

int main(void) {
     DDRC
= 0xFF;

     while(1) {
          _delay_ms(1000.);
          PORTC = 0xFF;
          _delay_ms(1000.);
          PORTC = 0x00;
     }

     return 0;
}

[zurück]