<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=78.42.25.70</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=78.42.25.70"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/78.42.25.70"/>
	<updated>2026-04-11T03:16:37Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-GCC-Codeoptimierung&amp;diff=51213</id>
		<title>AVR-GCC-Codeoptimierung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-GCC-Codeoptimierung&amp;diff=51213"/>
		<updated>2010-10-07T23:33:00Z</updated>

		<summary type="html">&lt;p&gt;78.42.25.70: /* Laufzeit messen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Entstanden aus diesem [http://www.mikrocontroller.net/topic/66690 Thread] sollen hier ein paar Hinweise/Erfahrungen gegeben werden, um den Quellcode in Punkto Größe und Geschwindigkeit zu optimieren. &#039;&#039;En detail&#039;&#039; ist das Thema komplex, da es stark von der Codeoptimierung des Compilers abhängt. Es ist im Einzelfall ratsam zu prüfen, ob die eigenen Maßnahmen auch erfolgreich waren. Folgende Diskussionen können als Anhaltspunkt dienen, wie eine solche Prüfung ablaufen kann:&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/132624] &lt;br /&gt;
* [http://www.mikrocontroller.net/topic/180800#new]&lt;br /&gt;
&lt;br /&gt;
== Prinzipien der Optimierung ==&lt;br /&gt;
&lt;br /&gt;
Wie so oft sollte man nicht einfach wild drauf los optimieren und sich zunächst ein paar Dinge klar machen.&lt;br /&gt;
&lt;br /&gt;
* Warum will ich optimieren?&lt;br /&gt;
* Was kann man sinnvoll optimieren?&lt;br /&gt;
* Wieviel Rechenzeit oder Speicher soll dabei gespart werden?&lt;br /&gt;
* Wie kann optimiert werden?&lt;br /&gt;
* &amp;quot;Verfrühte Optimierung ist die Wurzel allen Übels&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Viele Optimierungen sind &amp;quot;Angst-Optimierungen&amp;quot;, die nicht wirklich nötig sind. Die Gefahr mit Optimierungen ist, den Code tot zu optimieren, sprich Lesbarkeit und ggf. Fehlerfreiheit sinken massgeblich. Kurz und knapp in diesem [http://blogs.msdn.com/b/audiofool/archive/2007/06/14/the-rules-of-code-optimization.aspx BLOG] formuliert.&lt;br /&gt;
&lt;br /&gt;
=== Warum ===&lt;br /&gt;
&lt;br /&gt;
Optimieren sollt man nur, wenn&lt;br /&gt;
* der Speicher nicht mehr ausreicht (RAM, Flash)&lt;br /&gt;
* Die Laufzeit für bestimmte Programmteile zu groß wird und somit die Funktion nicht mehr erreicht wird&lt;br /&gt;
&lt;br /&gt;
Weiter sollte man folgende Punkte gegeneinander abwägen:&lt;br /&gt;
&lt;br /&gt;
* Codeverbrauch&lt;br /&gt;
* Datenverbrauch. Statisch/Stack/Heap&lt;br /&gt;
* Mittlere/maximale Laufzeit&lt;br /&gt;
* Entwicklungszeit&lt;br /&gt;
* Portabilität (Compiler, Hardware, ...)&lt;br /&gt;
* Verständlichkeit der Quelle, siehe [[Strukturierte Programmierung auf Mikrocontrollern]] &lt;br /&gt;
* ABI-Konformität&lt;br /&gt;
&lt;br /&gt;
=== Was ===&lt;br /&gt;
&lt;br /&gt;
Die goldene Regle lautet: 90% der Rechenleistung werden in 10% des Codes verbraucht. Diese 10% muss man finden und zum richtigen Zeitpunkt optimieren. Der Rest muss nur sauber und lesbar geschrieben sein. Was jedoch nichts bringt, das ist eine Funktion um den Faktor 10 schneller zu machen, die von 1 Minute Programmlaufzeit lediglich 1 Sekunde verbraucht. Die Programmlaufzeit sinkt dann von 60 Sekunden auf 59.1 Sekunden. Der Aufwand, die Funktion um einen Faktor 10 schneller zu machen ist aber meistens beträchtlich!  Kann ich aber den Code, der für die 59 Sekunden verantwortlich ist um einen Faktor 10 schneller machen, dann sinkt die Gesamtlaufzeit von 60 Sekunden auf 6.9 Sekunden. Dort bringt Optimieren augenscheinlich viel mehr!&lt;br /&gt;
&lt;br /&gt;
Um die optimierungswürdigen Stellen zu finden, muss man sein Programm analysieren. Dazu gibt es verschiedene Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
====Speicherverbrauch nach Funktionen aufschlüsseln====&lt;br /&gt;
&lt;br /&gt;
*Map File anschauen&lt;br /&gt;
**dort sind alle globalen und statischen Variablen enthalten&lt;br /&gt;
**Aus der Differenz der Anfangsadressen kann man die Programmgröße der Funktionen berechnen&lt;br /&gt;
*Hilfsmittel einkaufen oder selber bauen. Es gilt rauszufinden, welche Funktion massig Stack durch lokale Variablen verbraucht. Stacktracer können das. Wenn man keinen hat, dann muss man sich eben selber einen bauen, indem man den Stackpointer mitlogt. Zur Not einen Code-Review machen: Alle Funktionen optisch durchgehen und die identifizieren, die viele Variablen anlegen. Dann die Aufrufhierarchie der Funktion feststellen: Wirken sich die vielen Variablen überhaupt aus oder ensteht mein Problem durch eine tiefe Funktionsaufrufhierarchie, bei der zwar wenige Variablen pro Funktion im Spiel sind, aber die Menge der ineinandergeschachtelten Aufrufe &#039;das Kraut fett macht&#039;&lt;br /&gt;
* Profitools können das alles fast auf Knopfdruck, kosten aber viel Geld&lt;br /&gt;
&lt;br /&gt;
====Laufzeit messen====&lt;br /&gt;
&lt;br /&gt;
*Simulator&lt;br /&gt;
*In Echtzeit mittels Testpin, welche an Anfang einer Funktion/Blocks gesetzt wird und am Ende wieder gelöscht wird. Mit einem [[Oszilloskop]] kann man so sehr einfach die Laufzeit messen.&lt;br /&gt;
&lt;br /&gt;
=== Wieviel ===&lt;br /&gt;
&lt;br /&gt;
Der Aufwand von Optimierungen wächst exponentiell. Die letzten paar Prozent brauchen überproportional viel Aufwand.&lt;br /&gt;
&lt;br /&gt;
=== Wie ===&lt;br /&gt;
&lt;br /&gt;
Meist muss man die Wahl treffen ob man Speicher oder Rechenzeit sparen will, beides gleichzeitg geht meist nicht. Das Konzept heißt &#039;Space for Time&#039; und kann in beide Richtungen verwendet werden. Als Beispiel soll eine komplizierte Berechnung dienen. Diese kann man relativ kompakt in eine Funktion packen, welche dann aber eher langsam ist. Oder man benutzt eine sehr große Tabelle, in welcher die Ergebnisse schon für jeden Eingangswert vorausberechnet wurden. Diese Lösung ist sehr schnell, verbraucht aber sehr viel Speicher.&lt;br /&gt;
&lt;br /&gt;
* Inlining von Funktionen erhöht den Speicherverbrauch, senkt aber die Laufzeit. Beispiel: Funktion A ist 50 Byte groß und wird 10 mal im Programm aufgerufen. Ein Aufruf kostet 10 Byte:&lt;br /&gt;
** Ohne Inline: 10 * 10Byte + 50 Byte = 150 Byte Platzverbrauch&lt;br /&gt;
** Mit Inline: 10 * 50 Byte = 500 Byte&lt;br /&gt;
* Optimierer einschalten&lt;br /&gt;
* möglichst keine Floating Point Operationen, besser ist meist [[Festkommaarithmetik]]&lt;br /&gt;
* Formeln umstellen und zusammenfassen&lt;br /&gt;
* Variablen so klein wie möglich, uint8_t wo&#039;s nur geht.&lt;br /&gt;
* Wirklich zeitkritische Funktionen und Interrupts als Assemblercode in separater Datei&lt;br /&gt;
&lt;br /&gt;
==Optimierung der Größe==&lt;br /&gt;
&lt;br /&gt;
===GCC-interne Optimierung===&lt;br /&gt;
&lt;br /&gt;
Im AVR-Studio kann bei den Projekteinstellungen der gewünschte Optimierungsgrad eingestellt werden. Hier gibt es folgende Möglichkeiten:&lt;br /&gt;
*O0 - keine Optimierung, Code wird direkt in Assembler umgesetzt&lt;br /&gt;
*O1-O3 - Optimierung auf Geschwindigkeit, Grad 1-3; von O3 ist für Mikrocontroller abzuraten, da durch Function-Inlining die Code-Größe sehr stark zunimmt&lt;br /&gt;
*Os - Optimierung vorrangig auf Codegröße. Durch diese Einstellung lässt sich vor allem bei umfangreicheren Projekten sehr viel Platz sparen. Für Mikrocontroller oft sehr vorteilhaft.&lt;br /&gt;
&lt;br /&gt;
===Nullinitialisierung von statischen Variablen===&lt;br /&gt;
&lt;br /&gt;
Bisher hatte ich mich in meinen Init-Funktionen nicht auf den Startup-Code verlassen, sondern die nötigen Variablen genullt. So kann ich auch eine Re-Initialisierung machen, habe aber keinen Gebrauch davon gemacht. Stattdessen starte ich komplett neu. Entfernung der Null-Inits brachte einiges. (OK, kann man doch als Anfängerfehler bezeichnen, ich mußte erst im C-Standard nachlesen&lt;br /&gt;
daß das BSS-Nullen keine Eigenart von gcc ist.)&lt;br /&gt;
&lt;br /&gt;
===Statische (globale) Variablen in ein struct sammeln===&lt;br /&gt;
&lt;br /&gt;
Das erleichtert dem Compiler die Adressierung, da er den Basiszeiger wiederverwenden kann. Die Codegröße kann dann noch von der Reihenfolge der struct-Member abhängen. Die häufigst benutzte Variable sollte am Anfang stehen, dann kann sie ohne Offset direkt mit dem Basiszeiger adressiert werden. Ansonsten in Gruppen, wie die Variablen auch gebraucht werden. Hier kann man viel rumprobieren...&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef struct &lt;br /&gt;
{&lt;br /&gt;
    uint16_t sec;            // Meistbenutze Variable an den Anfang&lt;br /&gt;
    uint16_t minute;&lt;br /&gt;
    uint16_t hour;&lt;br /&gt;
} t;&lt;br /&gt;
&lt;br /&gt;
t global;                    // Globale Struktur definieren&lt;br /&gt;
uint8_t min;                 // Als Vergleich: einzelne globale Variable&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    t *time = &amp;amp;global;       // Zeiger auf die globale Struktur&lt;br /&gt;
    // LDI R30,LOW(global)   ; Init Z pointer&lt;br /&gt;
    // LDI R31,(global &amp;gt;&amp;gt; 8) ; Init Z high byte&lt;br /&gt;
    if (++time-&amp;gt;sec == 60)&lt;br /&gt;
    {&lt;br /&gt;
    // LDD R16,Z+2           ; Load with displacement&lt;br /&gt;
    // INC R16               ; Increment&lt;br /&gt;
    // STD Z+2,R16           ; Store with displacement&lt;br /&gt;
    // CPI R16,LOW(60)       ; Compare&lt;br /&gt;
    // BRNE ?0005            ; Branch if not equal&lt;br /&gt;
    }&lt;br /&gt;
    if ( ++min == 60)&lt;br /&gt;
    {&lt;br /&gt;
    // LDS R16,LWRD(min)     ; Load direct from SRAM&lt;br /&gt;
    // INC R16               ; Increment&lt;br /&gt;
    // STS LWRD(min),R16     ; Store direct to SRAM&lt;br /&gt;
    // CPI R16,LOW(60)       ; Compare&lt;br /&gt;
    // BRNE ?0005            ; Branch if not equal&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch, dass die Strukturvariable über LDD/STD (LDD/STD 2 Bytes; LDS/STS 4 Bytes) angesprochen werden kann, werden an dieser Stelle 4 Bytes eingespart.&lt;br /&gt;
Hinzu kommen jedoch noch einmal die 4 Bytes für die Initialisierung des Z-pointers, sodass die Einsparung erst bei mehreren Globalvariablen zum Tragen kommt.&lt;br /&gt;
&lt;br /&gt;
===Multiplikationen mit Konstanten===&lt;br /&gt;
&lt;br /&gt;
Der Compiler instanziiert sofort eine teure allgemeine Bibliotheksfunktion, auch wenn es anders ginge. Ich hatte eine einzige 32-bit Multiplikation mit 10 drin, die mir ein mulsi3 beschert hat. Mit a = (b&amp;lt;&amp;lt;3) + (b&amp;lt;&amp;lt;1) geht es in dem Fall kürzer. Wie gesagt, map-File beobachten. &lt;br /&gt;
Anmerkung: Variablen als unsigned definieren, dann sollte der Compiler das selbst machen.&lt;br /&gt;
&lt;br /&gt;
===Alle Variablen nur so breit wie nötig===&lt;br /&gt;
&lt;br /&gt;
Hatte ich eigentlich schon, nur an einigen wenigen Stellen war ich da etwas nachlässig. Mitunter reicht ein kleinerer Typ doch, wenn man z.&amp;amp;nbsp;B. vorher geeignet skaliert. Am besten nur die skalaren Typen aus &amp;lt;stdint.h&amp;gt; verwenden, das erleichtert auch das Folgende. Bei RAM Knappheit: kann ich Strings sinnvollerweise aus dem RAM ins Flash verbannen? Kann ich es mir leisten mehere Flag-Variablen in ein Byte zusammenzufassen, auch wenn dann die Zugriffe mglw. etwas langsamer werden.&lt;br /&gt;
&lt;br /&gt;
===Logische Operatoren werden auf int-Größe erweitert===&lt;br /&gt;
&lt;br /&gt;
Obwohl der AVR ein 8-Bit Controller ist, weitet der AVR-GCC an manchen Stellen  Vergleiche von zwei 8-Bit Variablen auf 16-Bit auf.&lt;br /&gt;
Als Beispiel sei dabei folgendes gezeigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
void foo(uint8_t a, uint8_t b)&lt;br /&gt;
{&lt;br /&gt;
    if (a == b)&lt;br /&gt;
    {&lt;br /&gt;
        // tue dies&lt;br /&gt;
    }   &lt;br /&gt;
    if (a == ~b)&lt;br /&gt;
    {&lt;br /&gt;
        // tue das&lt;br /&gt;
    // clr r19           ; clear register&lt;br /&gt;
    // mov r24,r22       ; copy register&lt;br /&gt;
    // clr r25           ; clear register&lt;br /&gt;
    // com r24           ; one&#039;s complement&lt;br /&gt;
    // com r25           ; one&#039;s complement&lt;br /&gt;
    // cp r18,r24        ; compare registers&lt;br /&gt;
    // cpc r19,r25       ; compare registers with carry&lt;br /&gt;
    // brne .L1          ; branch if not equal&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Den zweiten Vergleich mit der Negation weitet der Compiler auf 16 Bit auf.&lt;br /&gt;
Ein Cast verhindert dieses:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
void foo(uint8_t a, uint8_t b)&lt;br /&gt;
{&lt;br /&gt;
    if (a == b)&lt;br /&gt;
    {&lt;br /&gt;
        // tue dies&lt;br /&gt;
    }   &lt;br /&gt;
    if (a == (uint8_t) ~b)&lt;br /&gt;
    {&lt;br /&gt;
        // tue das&lt;br /&gt;
    // com r22           ; one&#039;s complement&lt;br /&gt;
    // cp r25,r22        ; compare registers&lt;br /&gt;
    // brne .L1          ; branch if not equal&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Einsparung an Speicher zwischen den beiden Versionen beträgt 12 Bytes. Außerdem ist die zweite Version um 6 Takte schneller.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Tatsächlich handelt es sich dabei nicht um ein Optimierungsproblem, sondern einen typischen Programmierfehler. Die beiden Varianten sind keineswegs identisch. Bei Variablen vom Typ uint8_t wird der Ausdruck (a == ~b) immer falsch sein (a=0x0000:0x00FF, ~b=0xFF00:0xFFFF). Dem Compiler ist allenfalls anzulasten, dass er nicht darauf hinweist.&lt;br /&gt;
&lt;br /&gt;
===Eine bool-Variable negieren===&lt;br /&gt;
&lt;br /&gt;
Das geht ganz gut so:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
c = not c ;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
oder besser so:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ( c ) c = false ; else c = true ;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Am besten geht das mit WinAVR20090313, wenn geschrieben wird:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
c = c ^ true ;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compileroption -mint8 für 8-Bit Arithmetik als Default===&lt;br /&gt;
&lt;br /&gt;
Mit obigen casts überall sähe der Code ziemlich schlimm aus. Blöd auch, wenn man mal einen Type ändert, dann muß man sorgsam nach den zugehörigen casts&lt;br /&gt;
suchen. Mit dem Compilerschalter -mint8 wird das zum Standard. Bei mir&lt;br /&gt;
hat das etwa 200 Byte gespart! Man sollte dafür aber keine ints mehr im&lt;br /&gt;
Code haben, nur noch Typen definierter Größe aus &amp;lt;stdint.h&amp;gt;.&lt;br /&gt;
Literal-Werte muß man ggf. anpassen (z.&amp;amp;nbsp;B. mit postfix L long machen)&lt;br /&gt;
damit sie nicht überlaufen, Compiler-Warnings beachten.  Ist anscheinend&lt;br /&gt;
noch etwas experimentell(?), mit dem aktuellen gcc 4.1.1 gibt es eine&lt;br /&gt;
Unverträglichkeit in &amp;lt;stdint.h&amp;gt;, der kriegt ein Problem mit den 64-bit Typen. Ist aber wohl in Arbeit, ich habe einen Patch gesehen.&lt;br /&gt;
&lt;br /&gt;
Die meisten Funktionen der avr-libc vertragen sich nicht mit -mint8!&lt;br /&gt;
&lt;br /&gt;
===Stack auf 256 Bytes begrenzen===&lt;br /&gt;
&lt;br /&gt;
Mit dem Compileflag -mtiny-stack wird für den Stack eine einfachere Adressierung möglich, die aber &amp;quot;nur&amp;quot; 256 Byte Stacktiefe erlaubt. Wenn man nicht exzessiv automatische Variablen benutzt (Arrays!) oder eine hohe&lt;br /&gt;
Verschachtelungstiefe hat, sollte das ausreichen. Hat mir nochmal knapp 100 Byte (!) kleineren Code erzeugt.&lt;br /&gt;
&lt;br /&gt;
===Prolog/Epilog von main() verkleinern===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;main()&#039;&#039; ist für Embedded-Anwendungen unnötigerweise eine normale Funktion.&lt;br /&gt;
Das könnten wir nur dann gebrauchen, wenn &#039;&#039;main()&#039;&#039; rekursiv aufgerufen wird,&lt;br /&gt;
und das wäre auf einem Mikrocontroller nicht sonderlich sinnvoll. Schon eine einfache Endlosschleife &#039;&#039;for(;;)&#039;&#039; am Ende läßt den Compiler wohl erkennen, das er sparen kann, wird 4 Byte kürzer.&lt;br /&gt;
&lt;br /&gt;
Für die Verwendung von &#039;&#039;noreturn&#039;&#039; muss in der &#039;&#039;&#039;main.h&#039;&#039;&#039;&lt;br /&gt;
  int main(void) __attribute__((noreturn));&lt;br /&gt;
und in der &#039;&#039;&#039;main.c&#039;&#039;&#039; das normale&lt;br /&gt;
  int main(void)&lt;br /&gt;
  {&lt;br /&gt;
    ..&lt;br /&gt;
  }&lt;br /&gt;
verwendet werden. Eine Warnung wird jedoch darauf hinweisen, das es keinen Retun gibt, trotz &#039;&#039;int&#039;&#039; definition.&lt;br /&gt;
&lt;br /&gt;
Definiert man hier ein&lt;br /&gt;
  void main (void) __attribute__((noreturn));&lt;br /&gt;
so wird sich der Compiller über das fehlende &#039;&#039;int&#039;&#039; beschweren, die Codegröße bleibt bei beiden Varianten die gleiche: es werden 12 Bytes gesparrt (gegenüber &#039;&#039;int main(void)&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Um die Warnungen endgültig zu unterdrücken, einfach -Wno-main als Compiler Schalter verwenden.&lt;br /&gt;
&lt;br /&gt;
===Speichern von globalen Flags===&lt;br /&gt;
&lt;br /&gt;
Oft werden in den Programmen Flags verwendet um beispielsweise eingetroffene Interrupts in der main-Routine auszuwerten. Hierzu wird üblicherweise eine globale Variable verwendet.&lt;br /&gt;
&lt;br /&gt;
Um den Wert dieser Variable abzufragen, muss sie jedoch erst aus dem SRAM in ein Register geladen werden, und kann dann erst auf ihren Status hin überprüft werden. Eine Möglichkeit ist, der globalen Variablen ein einziges Register fest zuzuordnen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
register uint8_t counter8_1 asm(&amp;quot;r2&amp;quot;);&lt;br /&gt;
register uint8_t counter8_2 asm(&amp;quot;r3&amp;quot;);&lt;br /&gt;
register uint16_t counter16_1 asm(&amp;quot;r4&amp;quot;); // r4:r5&lt;br /&gt;
register uint16_t counter16_2 asm(&amp;quot;r6&amp;quot;); // r6:r7&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
siehe auch: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_regbind&lt;br /&gt;
&lt;br /&gt;
Als Alternative kann man ein nicht verwendetes Register des I/O-Bereichs verwenden. Dabei würde sich z.&amp;amp;nbsp;B. das Register eines zweiten UARTs, oder das  EEPROM-Register anbieten, falls diese nicht benötigt werden.&lt;br /&gt;
&lt;br /&gt;
Neuere AVR-Modelle besitzen für diesen Zweck 3 frei verwendbare Bytes im bitadressierbaren I/O-Bereich: GPIOR0-2.&lt;br /&gt;
&lt;br /&gt;
===Speichern von globalen volatilen Variablen===&lt;br /&gt;
&lt;br /&gt;
Ähnlich wie globale Flags werden in Programmen häufig globale Variablen benötigt um eine Kommunikation zwischen einer Interruptroutine und z.&amp;amp;nbsp;B. der main-Routine zu ermöglichen. Diese Variable muss dann als volatile deklariert werden. &lt;br /&gt;
&lt;br /&gt;
Man könnte diese Variable dazu wieder in einem Register abspeichern, mit z.&amp;amp;nbsp;B.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
register volatile uint8_t counter8_1 asm(&amp;quot;r2&amp;quot;);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
die Kombination von register und volatile scheint jedoch mit avr-gcc nicht problemlos zu klappen, siehe http://www.mikrocontroller.net/topic/136799#new.&lt;br /&gt;
&lt;br /&gt;
Allerdings kann man genau wie bei den Flags auch hier wieder ein nicht verwendetes SFR Register verwenden, wie die des UARTs oder des EEPROMs, oder die frei verwendbaren Register GPIOR0, GPIOR1, und GPIOR2 (falls vorhanden). Glücklicherweise sind alle SFRs bereits als volatile deklariert (siehe Header-Datei sfr_defs.h), so dass ein #define ausreicht:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define counter8_1 GPIOR0&lt;br /&gt;
&lt;br /&gt;
ISR(){ &lt;br /&gt;
  counter8_1++; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void){ &lt;br /&gt;
  while(){ &lt;br /&gt;
    if(!counter8_1) put_str(&amp;quot;Cool&amp;quot;); &lt;br /&gt;
  } &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Puffern von volatile-Variablen===&lt;br /&gt;
&lt;br /&gt;
Der Compiler behandelt volatile-Variablen bei mehreren Manipulationen wie heiße Kartoffeln. Für jeden einzelnen Vorgang wiederholt sich das Spiel:&lt;br /&gt;
&lt;br /&gt;
* aus dem Speicher holen&lt;br /&gt;
* bearbeiten&lt;br /&gt;
* zurückspeichern&lt;br /&gt;
&lt;br /&gt;
Unter Umständen ist dieses Verhalten unsinnig. Ein Minimalbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
volatile char var;&lt;br /&gt;
&lt;br /&gt;
ISR(){&lt;br /&gt;
  var++;&lt;br /&gt;
  if (var&amp;gt;100) var=0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main (void){&lt;br /&gt;
   while(1){&lt;br /&gt;
     printf(var);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Hier wird &#039;&#039;&#039;var&#039;&#039;&#039; in der ISR insgesamt zwei mal aus dem RAM geholt und zurückgeschrieben. Das ist unsinnig, da die Interruptrountine nicht unterbrochen werden kann. Aus Sicht der ISR bräuchte man eigentlich kein volatile, kann es aber wegen dem zurgiff von main herraus nicht weglassen. Eine Lösung findet sich im folgenden Schnipsel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
volatile char var;&lt;br /&gt;
&lt;br /&gt;
ISR(){&lt;br /&gt;
  char temp=var;&lt;br /&gt;
  temp++;&lt;br /&gt;
  if (temp&amp;gt;100) temp=0;&lt;br /&gt;
  var=temp;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main (void){&lt;br /&gt;
   while(1){&lt;br /&gt;
     printf(var);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Hier wird die globale Variable &#039;&#039;&#039;var&#039;&#039;&#039; in der lokalen Variable &#039;&#039;&#039;temp&#039;&#039;&#039; gepuffert. Ein Nachteil durch das Anlegen von &#039;&#039;&#039;temp&#039;&#039;&#039; ergibt sich nicht, da das dafür verwendete Register für die Manipulation sowieso benötigt wird. Wie alle Optimierungen kann dieses Vorgehen auch nach hinten losgehen: Wenn Laden und Zurückspeichern von &#039;&#039;&#039;var&#039;&#039;&#039; weit auseinanderliegen (extrem lange ISR), müllt man sich die Register zu. Im schlimmsten Fall wird &#039;&#039;&#039;temp&#039;&#039;&#039; sogar zwischenzeitlich auf dem Stack ausgelagert.&lt;br /&gt;
&lt;br /&gt;
===Schleifen===&lt;br /&gt;
&lt;br /&gt;
Bei Schleifen, die eine bestimmte Anzahl an Durchläufen ausgeführt werden sollen, ist es besser den Schleifenzähler vorher auf einen Wert zu setzen, und am Ende einer Do-While Schleife diesen zu dekrementieren.&lt;br /&gt;
So beschränkt sich die Sprungbedingung auf ein brne (branch if not equal).&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
uint8_t counter;	&lt;br /&gt;
counter = 100;&lt;br /&gt;
do&lt;br /&gt;
{&lt;br /&gt;
    // mach irgendetwas&lt;br /&gt;
} while (--counter);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ein paar Schlagworte===&lt;br /&gt;
&lt;br /&gt;
Es gibt noch -ffreestanding, soll noch ein pragma für main() geben welches&lt;br /&gt;
Prolog/Epilog kappt, vielleicht kann man die Vektortabelle beschneiden.&lt;br /&gt;
&lt;br /&gt;
Mit -mcall-prologues werden die mitunter recht langen push/pop-Sequenzen in komplexen Funktionen durch Hilfsfunktionen ersetzt. Das kann vor allem bei grossen Programmen Platz sparen.&lt;br /&gt;
&lt;br /&gt;
Switch-Statements werden durch -mno-tablejump manchmal deutlich kürzer.&lt;br /&gt;
&lt;br /&gt;
==Optimierung der Ausführungsgeschwindigkeit==&lt;br /&gt;
&lt;br /&gt;
Hierzu gibt es schon eine Application-Note von Atmel:&lt;br /&gt;
&lt;br /&gt;
[http://www.atmel.com/dyn/resources/prod_documents/doc1497.pdf AVR035: Efficient C Coding for AVR ]&lt;br /&gt;
&lt;br /&gt;
Evtl. auf deutsch hier übersetzen?&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR]]&lt;/div&gt;</summary>
		<author><name>78.42.25.70</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=WinAVR&amp;diff=51119</id>
		<title>WinAVR</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=WinAVR&amp;diff=51119"/>
		<updated>2010-10-04T22:32:30Z</updated>

		<summary type="html">&lt;p&gt;78.42.25.70: /* Passende AVR-Studio Version */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:AVR]]&lt;br /&gt;
&lt;br /&gt;
WinAVR ist die Windows-Distribution der [[C]] und C++ aus der GNU compiler-collection [[AVR-GCC]] für [[AVR]]-[[Mikrocontroller]]. Der [[AVR-Ada|Ada]]-Compiler war mal enthalten und kann inzwischen nachinstalliert werden. WinAVR enthält neben dem Compiler und den erforderlichen Zusatzprogrammen (sogen. Binutils) noch einige andere Pakete, z.&amp;amp;nbsp;B. die C-Standardbibliothek avr-libc (inkl. Dokumentation), die Programmiersoftware [[AVRDUDE]] und den Editor Programmer&#039;s Notepad.&lt;br /&gt;
&lt;br /&gt;
[http://winavr.sourceforge.net/ Download über die WinAVR-Startseite]&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
Auf 64bit-Windows darf WinAVR &#039;&#039;&#039;nicht&#039;&#039;&#039; im Standard-Programmverzeichnis &amp;quot;C:\Program Files (x86)&amp;quot; installiert werden, sonst [http://www.mikrocontroller.net/topic/83517#700417 funktioniert der Compiler nicht]. Es ist entweder das vom Installer vorgeschlagene Defaultverzeichnis zu verwenden, oder z.B. &amp;quot;C:\WinAVR&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nach dem Installieren sollten Win9X-Rechner neu gestartet werden, um die Erweiterung des Suchpfades um die WinAVR-Verzeichnisse zu aktivieren (autoexec.bat). Bei Windows NT/2000/XP ist üblicherweise kein Neustart erforderlich, sollte aber dennoch ausgeführt werden, wenn Probleme auftreten (Fehler in der Art: &#039;&#039;Der Befehl ist falsch geschrieben/kann nicht gefunden werden...&#039;&#039;). Danach kann man sofort im Programmer&#039;s Notepad z.&amp;amp;nbsp;B. mit dem Beispielcode anfangen. &lt;br /&gt;
&lt;br /&gt;
Zwei WinAVR Verzeichnisse müssen in der PATH-Umgebungsvariable aufgeführt sein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C:\Dokumente und Einstellungen\willi&amp;gt;path&lt;br /&gt;
PATH=[...]C:\WinAVR\bin;C:\WinAVR\utils\bin;[...]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps + Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== Umstieg von AVR-Studio mit avr-gcc zu WinAVR mit AVRISP ===&lt;br /&gt;
* Programmer&#039;s Notepad 2 hat konfigurierbare Menüpunkte, vorkonfiguriert sind: &lt;br /&gt;
**Make all&lt;br /&gt;
**Make clean&lt;br /&gt;
**Make program&lt;br /&gt;
* Man muss sich selbst um ein passendes Makefile kümmern. Dazu kann WinAVR/mfile/mfile.tcl genutzt werden (Achtung, F_CPU ist im Template bereits mit 8 MHz eingestellt und muss ggf. von Hand geändert werden). mfile benötigt TCL/TK ([http://www.activestate.com/Products/Download/Download.plex?id=ActiveTcl Win32 download], ca 20 MB). &lt;br /&gt;
* Zum Flashen wird AVRDUDE benutzt.&lt;br /&gt;
* Wenn es beim Flashen einen &#039;out of sync&#039; Fehler gibt, ist nicht der richtige AVRISP eingestellt (unterschiedliche Softwareversionen).&lt;br /&gt;
&lt;br /&gt;
=== WinAVR Version ===&lt;br /&gt;
&lt;br /&gt;
Die aktuelle WinAVR Version ist derzeit (01/2010) WinAVR-20100110. &lt;br /&gt;
[http://winavr.sourceforge.net/ SourceForge.net WinAVR Projekt-Seite] und [http://sourceforge.net/projects/winavr/files/ Download]&lt;br /&gt;
&lt;br /&gt;
Bekannte Probleme:&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/163022#1554907]: AVRDUDE Fehler: avrdude was compiled without usb support. Abhilfe: Ältere Version nehmen oder selbst kompilieren [http://www.mikrocontroller.net/topic/163675#1561957].&lt;br /&gt;
&lt;br /&gt;
=== Passende AVR-Studio Version ===&lt;br /&gt;
Wenn eine WinAVR-Version 2007... mit AVR Studio betrieben wird, ist AVR Studio Version &amp;gt;= 4.13 erforderlich. Beim Projekt Erstellen möglichst einen Leerzeichen freien Pfad nehmen, da es andern falls zu Problemen/Fehlern(z.&amp;amp;nbsp;B. error: &#039;UBRR&#039; undeclared (first use in this function)) kommen &#039;&#039;&#039;kann&#039;&#039;&#039; beim compilieren, eine neue Installation behebt den Fehler nicht.&lt;br /&gt;
&lt;br /&gt;
Downloadadressen sind derzeit:&lt;br /&gt;
* [http://www.atmel.no/beta_ware AVR Tools Beta Site]&lt;br /&gt;
* [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725 AVR Studio 4 Site] (Registrierung notwendig!)&lt;br /&gt;
&lt;br /&gt;
=== MAKE funktioniert nicht ===&lt;br /&gt;
&lt;br /&gt;
==== Richtiges Make Programm? ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; make all&lt;br /&gt;
MAKE Version 5.2  Copyright (c) 1987, 2000 Borland&lt;br /&gt;
Error makefile 461: Command syntax error&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn make mit dieser oder ähnlichen Fehlermeldung abbricht, ist der Pfad für ausführbare Programme nicht auf das make Programm aus dem GCC/Binutils Paket gesetzt. Es wird ganz banal das falsche Make-Programm (z.&amp;amp;nbsp;B. von Borland C oder Delphi) für das verwendete makefile aufgerufen. In diesem Fall ist die Umgebungsvariable PATH in Autoexec.Bat (Windows 98SE) bzw. in der Systemsteuerung (Windows XP, 2000) anzupassen.&lt;br /&gt;
&lt;br /&gt;
==== gcc plug-in: Error: Object file not found on expected location ====&lt;br /&gt;
&lt;br /&gt;
Diese Fehlermeldung kann nur auftauchen, wenn der GNU C Compiler aus dem AVR-Studio heraus bedient wird. Dass keine weiteren Fehlerursachen genannt werden, ist eigentlich ein [[AVR-Studio Bugs|AVR-Studio Bug]]. &lt;br /&gt;
&lt;br /&gt;
Eine Analyse des AVR-Studio Bugs hat [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=53658 Johan Ekdahl im avrfreaks.net Forum] beschrieben. AVR-Studio erkennt in gewissen Fällen beim &#039;&#039;&#039;Build&#039;&#039;&#039;-Vorgang auftretende Fehler nicht und erwartet eine nie hergestellte Ausgabedatei. &lt;br /&gt;
&lt;br /&gt;
Auf jeden Fall sollte man in AVR Studio mal zwischen dem Build und Message-Fenster umschalten, ob ein einem von beiden mehr Infos stehen, was wodurch den Fehler produziert.&lt;br /&gt;
&lt;br /&gt;
Wenn nicht mehr Infos aus AVR Studio herauszukitzeln sind, könnte man das Projekt beispielsweise als herkömmliches Make-Projekt aufsetzen, mit WinAVR kompilieren (Kommandozeile oder aus dem Programmers Notepad heraus) und auf Fehlermeldungen achten.&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/80188 gcc plug-in: Error: Object file not found...] im Forum&lt;br /&gt;
&lt;br /&gt;
==== avr-gcc: _spawnvp: No such file or directory ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; &amp;quot;make.exe&amp;quot; all&lt;br /&gt;
&lt;br /&gt;
-------- begin --------&lt;br /&gt;
avr-gcc (GCC) 4.1.1 (WinAVR 20070122)&lt;br /&gt;
Copyright (C) 2006 Free Software Foundation, Inc.&lt;br /&gt;
This is free software; see the source for copying conditions.  There is&lt;br /&gt;
NO&lt;br /&gt;
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR&lt;br /&gt;
PURPOSE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Linking: main.c.elf&lt;br /&gt;
avr-gcc -mmcu=at90s2313 -I. -gdwarf-2 -DF_CPU=7372800UL -Os&lt;br /&gt;
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall&lt;br /&gt;
-Wstrict-prototypes -Wa,-adhlns=  -std=gnu99 -Wundef -MMD -MP -MF&lt;br /&gt;
.dep/main.c.elf.d  --output main.c.elf -Wl,-Map=main.c.map,--cref&lt;br /&gt;
-lm&lt;br /&gt;
avr-gcc: _spawnvp: No such file or directory&lt;br /&gt;
make.exe: *** [main.c.elf] Error 1&lt;br /&gt;
&lt;br /&gt;
&amp;gt; Process Exit Code: 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei WinAVR-20070122 und WinAVR-20070525 kann es unter VISTA und Windows98SE eine ähnliche Fehlermeldung wie oben gezeigt geben. &lt;br /&gt;
&lt;br /&gt;
Verschiedene Binärpatches können diese Probleme beheben:&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/61716#508449 Forenbeitrag von MadWizard] und [http://www.madwizard.org/extern/winavr-vista/ Originalseite] für VISTA (32-Bit). Bei der 64-Bit Version von VISTA wird berichtet, dass der Linker mit Fehlermeldung abbricht.&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/60163#490161 Forenbeitrag von Stefan] für Windows98SE&lt;br /&gt;
&lt;br /&gt;
WinAVR-20071221 funktioniert unter Windows98SE, wie erste Tests zeigen, wie aus der Tüte, d.h. ohne Binärpatch (Jippy!).&lt;br /&gt;
&lt;br /&gt;
==== ...\WinAVR\utils\bin\sh.exe: *** Couldn&#039;t reserve space for cygwin&#039;s heap, Win32 error 487 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; &amp;quot;make.exe&amp;quot; all&lt;br /&gt;
AllocationBase 0x0, BaseAddress 0x71590000, RegionSize 0x470000, State 0x10000&lt;br /&gt;
E:\WinAVR\utils\bin\sh.exe: *** Couldn&#039;t reserve space for cygwin&#039;s heap, Win32 error 487&lt;br /&gt;
&lt;br /&gt;
-------- begin --------&lt;br /&gt;
avr-gcc (GCC) 3.4.3&lt;br /&gt;
Copyright (C) 2004 Free Software Foundation, Inc.&lt;br /&gt;
This is free software; see the source for copying conditions.  There is NO&lt;br /&gt;
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;br /&gt;
&lt;br /&gt;
AllocationBase 0x0, BaseAddress 0x71590000, RegionSize 0x470000, State 0x10000&lt;br /&gt;
E:\WinAVR\utils\bin\sh.exe: *** Couldn&#039;t reserve space for cygwin&#039;s heap, Win32 error 487&lt;br /&gt;
make.exe: *** [sizebefore] Error 1&lt;br /&gt;
&lt;br /&gt;
&amp;gt; Process Exit Code: 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn make mit dieser oder ähnlichen Fehlermeldung abbricht, ist es einen Versuch wert, die Hilfsdatei &#039;&#039;&#039;msys-1.0.dll&#039;&#039;&#039; im Ordner des Tools sh.exe (beim Beispiel E:\WinAVR\utils\bin\) auszutauschen. Eine Anleitung dazu gibt es von Madwizard (http://www.madwizard.org/extern/winavr-vista). Siehe auch im Forum die [http://www.mikrocontroller.net/topic/70505#573305 Frage von Lukas] und die [http://www.mikrocontroller.net/topic/79973#667605 Frage von werdlangsammüde].&lt;br /&gt;
&lt;br /&gt;
==== make: *** [####.eep] Error 1 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Build started 18.8.2007 at 20:14:23&lt;br /&gt;
avr-objcopy -j .eeprom --set-section-flags=.eeprom=&amp;quot;alloc,load&amp;quot;&lt;br /&gt;
--change-section-lma .eeprom=0 -O ihex I2C_Motor.elf I2C_Motor.eep&lt;br /&gt;
c:\Programme\WinAVR\bin\avr-objcopy.exe: there are no sections to be&lt;br /&gt;
copied!&lt;br /&gt;
c:\Programme\WinAVR\bin\avr-objcopy.exe: --change-section-lma&lt;br /&gt;
.eeprom=0x00000000 never used&lt;br /&gt;
make: *** [I2C_Motor.eep] Error 1&lt;br /&gt;
Build succeeded with 0 Warnings...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese oder eine ähnliche Fehlermeldung erscheint, wenn im erzeugten Programm der [[EEPROM]]-Abschnitt unbenutzt ist. Um die Fehlermeldung zu unterdrücken, kann man vor den Aufruf von avr-objcopy im Makefile ein Minuszeichen schreiben ([http://www.mikrocontroller.net/topic/76369#633387 Forenbeitrag von Jörg]).&lt;br /&gt;
&lt;br /&gt;
Beispielzeilen in einem Makefile &#039;&#039;&#039;ohne&#039;&#039;&#039; Fehlerunterdrückung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%.eep: %.elf&lt;br /&gt;
	@echo&lt;br /&gt;
	@echo $(MSG_EEPROM) $@&lt;br /&gt;
	$(OBJCOPY) -j .eeprom \&lt;br /&gt;
        --set-section-flags=.eeprom=&amp;quot;alloc,load&amp;quot; \&lt;br /&gt;
	--change-section-lma .eeprom=0 \&lt;br /&gt;
        --no-change-warnings -O $(FORMAT) \&lt;br /&gt;
        $&amp;lt; $@ || exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielzeilen in einem Makefile &#039;&#039;&#039;mit&#039;&#039;&#039; Fehlerunterdrückung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%.eep: %.elf&lt;br /&gt;
	@echo&lt;br /&gt;
	@echo $(MSG_EEPROM) $@&lt;br /&gt;
	-$(OBJCOPY) -j .eeprom \&lt;br /&gt;
        --set-section-flags=.eeprom=&amp;quot;alloc,load&amp;quot; \&lt;br /&gt;
	--change-section-lma .eeprom=0 \&lt;br /&gt;
        --no-change-warnings -O $(FORMAT) \&lt;br /&gt;
        $&amp;lt; $@ || exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== make.exe: *** No rule to make target `main.elf&#039;, needed by `elf&#039;. ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-------- begin --------&lt;br /&gt;
avr-gcc (GCC) 4.2.2 (WinAVR 20071221rc1)&lt;br /&gt;
Copyright (C) 2007 Free Software Foundation, Inc.&lt;br /&gt;
This is free software; see the source for copying conditions.  There is NO warranty;&lt;br /&gt;
not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;br /&gt;
&lt;br /&gt;
make.exe: *** No rule to make target `main.elf&#039;, needed by `elf&#039;.  Stop.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; Process Exit Code: 2&lt;br /&gt;
&amp;gt; Time Taken: 00:02&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese oder eine ähnliche Fehlermeldung erscheint, wenn der Quelltest NICHT main.c heisst und ein Makefile OHNE weitere Anpassung an den verwendeten Dateinamen der Quelltextdatei verwendet wird. &lt;br /&gt;
&lt;br /&gt;
Abhilfe ist also die Quelltextdatei in main.c umbenennen oder das Makefile anzupassen (siehe [[AVR-GCC-Tutorial]]).&lt;br /&gt;
&lt;br /&gt;
Eine weitere Fehlerursache könnte auch eine Ordnerstruktur mit Leerzeichen und/oder Sonderzeichen im Pfad sein.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Ursache kann das benutzte Makefile sein. Es ist da anscheinend eins im Umlauf mit falscher Einrückung der Anweisungen ([http://www.mikrocontroller.net/topic/123719#1126830] und [http://www.mikrocontroller.net/topic/116346#1043825])&lt;br /&gt;
&lt;br /&gt;
==== fatal error: opening dependency file .dep/main.o.d: No such file or directory ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avr-gcc (GCC) 4.2.2 (WinAVR 20071221)&lt;br /&gt;
Copyright (C) 2007 Free Software Foundation, Inc.&lt;br /&gt;
This is free software; see the source for copying conditions.  There is&lt;br /&gt;
NO&lt;br /&gt;
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR&lt;br /&gt;
PURPOSE.&lt;br /&gt;
&lt;br /&gt;
Compiling: main.c&lt;br /&gt;
avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2   -Os -funsigned-char&lt;br /&gt;
-funsigned-bitfiel&lt;br /&gt;
ds -fpack-struct -fshort-enums -Wall -Wstrict-prototypes&lt;br /&gt;
-Wa,-adhlns=main.lst  -&lt;br /&gt;
std=gnu99 -DF_OSC=3686400 -MD -MP -MF .dep/main.o.d main.c -o main.o&lt;br /&gt;
main.c:21: fatal error: opening dependency file .dep/main.o.d: No such&lt;br /&gt;
file or directory&lt;br /&gt;
compilation terminated.&lt;br /&gt;
make: *** [main.o] Error 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sind Leerzeichen oder Sonderzeichen im Verzeichnispfad ([http://www.mikrocontroller.net/topic/99642#864556])?&lt;br /&gt;
&lt;br /&gt;
Wird VISTA 64 benutzt? Obige Fehlermeldung kann als zweite Fehlermeldung nach der eigentlichen VISTA-spezifischen Fehlermeldung (sync_with_child Problem) kommen. Die Lösung hat dann [http://www.madwizard.org/electronics/articles/winavrvista MADWIZARD].&lt;br /&gt;
&lt;br /&gt;
==== make: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4217b3) ====&lt;br /&gt;
&lt;br /&gt;
WinAVR darf nicht im Standard-Programmverzeichnis &amp;quot;C:\Program Files (x86)&amp;quot; installiert werden, sonst kommt dieser Fehler. Es ist entweder das vom Installer vorgeschlagene Defaultverzeichnis zu verwenden, oder z.B. &amp;quot;C:\WinAVR&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Portable Installation ===&lt;br /&gt;
&lt;br /&gt;
Das Hauptproblem beim Ausführen von WinAVR von einem USB-Stick ist der fehlende Eintrag für den Compilerpfad in der Windowsumgebungsvariable PATH. &lt;br /&gt;
&lt;br /&gt;
Die folgende Batchdatei zum Starten des Programmers Notepad extrahiert mit %~dp0 das Laufwerk und den Pfad vom Aufruf der Batchdatei und setzt damit PATH neu. &lt;br /&gt;
&lt;br /&gt;
Zu beachten ist, das die neu gesetzte PATH Variable nicht systemweit etabliert wird, sondern nur für Prozesse gilt, die aus dieser Batch (mit dieser cmd Session) aufgerufen werden (in diesem Fall pn.exe)&lt;br /&gt;
&lt;br /&gt;
....\WinAVR\pn.bat&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@echo off&lt;br /&gt;
echo PN.BAT Version 1.0&lt;br /&gt;
&lt;br /&gt;
set BatchPath=%~dp0&lt;br /&gt;
set BinDir=pn\&lt;br /&gt;
set BinDir=%BatchPath%%BinDir%&lt;br /&gt;
set PATH=%BatchPath%\bin;%BatchPath%\utils\bin;%PATH%&lt;br /&gt;
&lt;br /&gt;
start %BinDir%pn.exe&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Code-Größe anzeigen ===&lt;br /&gt;
* [[WinAVR: Code-Größe anzeigen]]&lt;br /&gt;
* Das Tool [[AVR-GCC#Tipps_.26_Tricks|avr-nm]]&lt;br /&gt;
&lt;br /&gt;
=== Avrdude findet libusb0.dll nicht (WinAVR-20070525) ===&lt;br /&gt;
[http://www.mikrocontroller.net/topic/83524#701461 Forenbeitrag von Paul]: Habe leider noch etwas zu bemängeln, und zwar meckerte avrdude, dass es die &amp;quot;libusb0.dll&amp;quot; nicht fand. Musste dann erst noch manuell den Pfad c:\winavr\utils\libusb\bin in die autoxecec.bat eintragen. Siehe auch [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;p=373283 Diskussion bei www.avrfreaks.net]&lt;br /&gt;
&lt;br /&gt;
=== C-Quellcode fehlt im *.LSS Listing (WinAVR-20071221) ===&lt;br /&gt;
&lt;br /&gt;
In WinAVR-20071221 werden im ggf. erzeugten Disassemblerlisting (Dateiendung .LSS) keine Quellcodezeilen angezeigt. Es handelt sich um ein Problem des Programms avr-objdump ([http://www.mikrocontroller.net/topic/87778#744096 Forenbeitrag]). Der User DosMan hat einen [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=59538 Workaround #1] bei www.avrfreaks.net angegeben (zum Download ggf. kostenlos registrieren). Ein anderer ebenfalls bei www.avrfreaks.net beschriebener [http://www.mikrocontroller.net/topic/87778#774185 Workaround #2] besteht darin, die Zeilenenden im C-Quelltext in &amp;quot;Unix-Zeilenenden&amp;quot; (nur \n statt \n\r) umzuformen bzw. nur mit Editoren zu arbeiten, die solche Unix-Zeilenenden erzeugen.&lt;br /&gt;
&lt;br /&gt;
=== Hilfe! Habe neues WinAVR und das Datensegement ist jetzt riesig! (WinAVR-20071221) ===&lt;br /&gt;
&lt;br /&gt;
Es gibt in der aktuellen Version bereits gemeldete Bugs im Zusammenhang mit &#039;&#039;&#039;float&#039;&#039;&#039; Variablen bzw. den neu geschriebenen Gleitzahlfunktionen der avr-libc ([http://www.mikrocontroller.net/topic/86837#734278 Forumsbeitrag]). Wir können im Moment nur hoffen (oder besser: mitarbeiten), dass bald ein WinAVR Update herauskommt.&lt;br /&gt;
&lt;br /&gt;
=== WinAVR-2010 soll die letzte Version sein? [http://www.mikrocontroller.net/topic/178763] ===&lt;br /&gt;
&lt;br /&gt;
[http://www.makehackvoid.com/group-projects/mhvavrtools MHV AVR Tools] - A WinAVR Replacement. With WinAVR marked as inactive, and no official release yet from Atmel, we (Make Hack Void, an association of geeks &amp;amp; artists. We are forming a Hackerspace* in Canberra) have built our own set of tools in a WinAVR-like layout suitable for use as a replacement. Please note that no guarantees as to fitness or suitability are being made. In particular,GCC 4.5.1 has not been tested as extensively as GCC 4.4.x, so use our builds at your own risk.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* [[AVR-GCC-Tutorial]]&lt;br /&gt;
* [[AVR-GCC]]&lt;br /&gt;
* [[AVR-Studio]]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/gcc GCC-Forum]&lt;/div&gt;</summary>
		<author><name>78.42.25.70</name></author>
	</entry>
</feed>