U5 Fortgeschrittene AVR-Programmierung U5 Fortgeschrittene AVR-Programmierung. Synchronisation mit Unterbrechungsbehandlungen

Ähnliche Dokumente
Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Interrupts. Inhalt. Interrupts. Synchronisation

Interrupts. Funktionsprinzip. Funktionsprinzip. Beispiel in C

Einführung in die Programmierung von Mikrocontrollern mit C/C++

Tag 2 Eingabe und Interrupts

b) Gegeben sei folgende Enumeration: enum SPRACHE {Deutsch, Englisch, Russisch};

ARM Cortex-M Prozessoren. Referat von Peter Voser Embedded Development GmbH

Wer möchte, kann sein Programm auch auf echter Hardware testen

Microcontroller Kurs Programmieren Microcontroller Kurs/Johannes Fuchs 1

Makros sind Textersetzungen, welche vom Präprozessor aufgelöst werden. Dies Passiert bevor der Compiler die Datein verarbeitet.

Arten der Synchronisation. Koordination nebenläufiger Prozesse. Koordinierung. Reihenschaltung. Einseitige Synchronisation

Mikrocontroller stromsparend. Uwe Berger

Parallel-IO. Ports am ATmega128

Interrupt-Programmierung

AVR UART. ELV Modul: ch=&marke=

AVR-8-Bit-Mikrocontroller Bootloader

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Befehlssatz AVR RISC Controller

Treiber Fortgeschrittene Konzepte

Ergänzungen zum Manual OS V 2.05/2.06

Deklarationen in C. Prof. Dr. Margarita Esponda

Programmieren in C Teil 3: Mikrocontrollerprogrammierung

Einführung in AVR-Assembler

Fachhochschule Kaiserslautern Fachbereich Angewandte Ingenieurwissenschaften WS2010/11. Zeitpunkt der Prüfung: Beginn: 10.

Atmel AVR für Dummies

Propädeutikum. Dipl.-Inf. Frank Güttler

Name: ES2 Klausur Thema: ARM Name: Punkte: Note:

RTOS mit Energiesparfunktionen für Low-Power Applikationen

leave: mov flag, 0 ; 0 in flag speichern: Lock freigeben ret

Hinweise bei Problemen mit Makros

Rechnerarchitektur Atmega Vortrag Atmega 32. Von Urs Müller und Marion Knoth. Urs Müller Seite 1 von 7

Lösungen zum Kurs "Mikrocontroller Hard- und Software

Benutzerhandbuch Tele Columbus-Telefonanschluss inkl. Anrufbeantworter Kundenservice fernsehen. internet. telefon.

U Abend 3: Musterlösungen, Taster entprellen, Unterprozeduren, Interrupts, Timer

Betriebssystembau (BSB)

Programmierung Nibo 2 Teil 3 Display. * by nicaisystems

Gliederung Hardware fuer die Zeitmessung Zeitmanagement auf Uniprozessorsystemen. Timing Measurements. Timo Schneider. 4.

Technische Informatik 2: Addressierung und Befehle

MIKROPROZESSOR PROGRAMMIERUNG 8. VORLESUNG. LV-Nr SS INSTITUT FÜR ELEKTRONIK BIT

White Paper. Embedded Treiberframework. Einführung

Laborprotokoll Informationstechnologien

Einführung in die C-Programmierung

AVR-Mikrocontroller mit dem GCC programmieren

Wintersemester 08/09. Anwendungen der Prozessdatenverarbeitung Inverses Pendel

Universität Karlsruhe (TH)

Interrupts & I/O-Ports

Zahlendarstellung Logikfunktionen Register Eingänge Infrarot senden TSOP-Effekte Weiterführendes U Abend 3:

Moderne Betriebssysteme. Kapitel 8. Kapitel 8. Folie: 1. Multiprozessorsysteme. Autor: Andrew S. Tanenbaum

Betriebssysteme. Wintersemester Kapitel 2 Prozess und Threads. Patrick Kendzo ppkendzo@gmail.com

UART-Kommunikation mit dem Atmel AVR

Simple Scope. ecos-vertiefung. Florian Franzmann Tobias Klaus Peter Wägemann

Maschinenorientierte Programmierung

Betriebssysteme BS-V SS Hans-Georg Eßer. Foliensatz V: Ulix: Interrupts und Faults Ulix: System Calls. Dipl.-Math., Dipl.-Inform.

DST EINFÜHRUNG IN MRT (V2)

2A Basistechniken: Weitere Aufgaben

1. Schritt: Benutzerkontensteuerung aktivieren

CCS Compiler Tutorial mit Beispielen

B1 Stapelspeicher (stack)

Softwarelösungen: Versuch 4

Multitasking / virtuelle Maschinen mittels Atmel AVR- Mikrocontrollern (Simple & Stupid)

Synchronisation in Java. Invisible Web

i2c-bus.de I2C-001 KURZBESCHREIBUNG I 2 C Modul mit PCF Bit I/O Port-Expander Dokument NR.: I2C-001-D-01

Betriebssysteme Kap B: Hardwaremechanismen

,,Echtzeit ist ein Buzzword und sagt gerade bei Nichtrealtime-Betriebssystemen garnichts aus. (Thomas Ogrisegg in at.linux) Linux PREEMPT RT

Grundlagen. Die Komponenten eines C Programms. Das erste Programm

Mikroprozessoren Grundlagen AVR-Controller Input / Output (I/O) Interrupt Mathematische Operationen

SIMATIC S Aktualisierung des S Systemhandbuchs, Ausgabe 04/2012 Produktinformation

Projekt Thermen-Steuerung von Manuel Schreiner Mat.-Nr.: Betreuer: Prof. Rückle

i2c-bus.de I2C-002 KURZBESCHREIBUNG I 2 C Modul mit PCA Bit I/O Port-Expander Dokument NR.: I2C-002-D-01

Tutorial. Microcontroller. Grundlagen µc. Kapitel 1

Software ubiquitärer Systeme

Einführung in die Programmierung

Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Sebastian Maier, Heiko Janker (Lehrstuhl Informatik 4) Übung 1. Wintersemester 2015/2016

Einführung in die Echtzeitbetriebssysteme

Fiery Driver Configurator

Anleitung zur Aktualisierung

M-AX-16/C1 (Typ 37) Inhaltsverzeichnis M-AX-16/C1

Universita t Koblenz/Landau Studienarbeit

Der Goopax Compiler GPU-Programmierung in C++ ZKI AK-Supercomputing, Münster, , Ingo Josopait

SPI Serial Peripheral Interface

Modulare Programmierung und Bibliotheken

Systeme I: Betriebssysteme Kapitel 4 Prozesse. Maren Bennewitz

Was ist Arduino? Historie Der Kern Entwicklungsumgebung Hardware Software Und wozu das Ganze? Workshop Mikrorechner 2012 A.

Sicheres C Programmieren in Embedded Systemen ARM II (ARM7TMDI [1] ) Wintersemester

Grundlagen der Rechnerarchitektur

OpenMP am Beispiel der Matrizenmultiplikation

POSIX Echtzeit: Kernel 2.6 und Preempt-RT

5. Threads, Serverprozesse und Benachrichtigungen

Eigenen WSUS Server mit dem UNI WSUS Server Synchronisieren

Domänenmodell: Fadenkommunikation und -synchronisation

OSEK / OSEKtime Ausgewählte Kapitel eingebetteter Systeme

x86 Open Source Virtualisierungstechniken Thomas Glanzmann

Einführung in das Programmieren in der Sekundarstufe 1. mit einem Arduino und der Physical-Computing-Plattform

Die Entwicklungsumgebung. Labor Technische Informatik. Prof. Dr.-Ing. F. Kesel Dipl.-Ing. (FH) A. Reber

EXPANDIT. ExpandIT Client Control Kurzanleitung. utilities. be prepared speed up go mobile. Stand

Microcontroller Kurs Microcontroller Kurs/Johannes Fuchs 1

Operating System Kernels

Projekt Nr. 15: Einen elektronischen Würfel erstellen

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus

Produktinformationen. Basis Set Atmel Atmega8 & ISP Programmer. Lieferumfang :

Display Controller für ein 320x240 4 Bit Display

Transkript:

U5 Fortgeschrittene AVR-Programmierung U5 Fortgeschrittene AVR-Programmierung Interrupts volatile-variablen Synchronisation mit Unterbrechungsbehandlungen Stromsparmodi des AVR U5.1 U5-1 Externe Interrupts des AVR- C U5-1 Externe Interrupts des AVR-mC 1 Flanken-/Pegel-Steuerung Externe Interrupts durch Pegel(änderung) an bestimmten I/O-Pins ATmega32: 3 Quellen an den Pins PD2, PD3 und PB2 Pegel- oder flanken-gesteuert Abhängig von der jeweiligen Interruptquelle Beispiel: Externer Interrupt 2 (INT2) ISC2 IRQ bei: 0 Fallender Flanke 1 Steigender Flanke Dokumentation im ATmega32-Datenblatt Interruptbehandlung allgemein: S. 44-48 Externe Interrupts: S. 66-68 U5.2

1 Flanken-/Pegel-Steuerung (2) U5-1 Externe Interrupts des AVR-mC Beim ATmega32 befinden sich die ISC-Bits im MCU Control Register (MCUCR) und MCU Control and Status Register (MCUCSR) Position der ISC-Bits in den Registern durch Makros definiert ISCn0 und ISCn1 (INT0 und INT1) oder ISCn (INT2) Beispiel: INT2 bei ATmega32 für fallende Flanke konfigurieren /* die ISCs für INT2 befinden sich im MCUCSR */ MCUCSR &= ~(1<<ISC2); /* ISC2 löschen */ U5.3 2 Maskieren U5-1 Externe Interrupts des AVR-mC Alle Interruptquellen können separat ausgeschaltet (=maskiert) werden Für externe Interrupts ist folgendes Register zuständig: ATmega32: General Interrupt Control Register (GICR) Die Bitpositionen in diesem Register sind durch Makros INTn definiert Ein gesetztes Bit aktiviert den jeweiligen Interrupt Beispiel: Interrupt 2 aktivieren GICR = (1<<INT2); /* demaskiere Interrupt 2 */ U5.4

2 Maskieren (2) U5-1 Externe Interrupts des AVR-mC Alle Interrupts können nochmals bei der CPU direkt abgeschaltet werden durch speziellen Maschinenbefehl cli Die Bibliothek avr-libc bietet hierfür Makros an: (#include <avr/interrupt.h>) sei() - lässt Interrupts zu cli() - blockiert alle Interrupts Beispiel #include <avr/interrupt.h> sei(); /* IRQs zulassen */ Innerhalb eines Interrupt-Handlers sind automatisch alle Interrupts blockiert, beim Verlassen werden sie wieder deblockiert Beim Start des C sind die Interrupts bei der CPU abgeschaltet U5.5 3 Interrupt-Handler U5-1 Externe Interrupts des AVR-mC Installieren eines Interrupt-Handlers wird durch C-Bibliothek unterstützt Makro ISR (Interruptvektor) zur Definition einer Handler-Funktion (#include <avr/interrupt.h>) Als Parameter gibt man dem Makro den gewünschten Vektor an, z. B. INT2_vect für den externen Interrupt 2 verfügbare Vektoren: siehe avr-libc-doku zu avr/interrupt.h verlinkt im Doku-Bereich auf der SPiC-Webseite Beispiel: Handler für Interrupt 2 implementieren #include <avr/interrupt.h> static int zaehler; ISR (INT2_vect) { zaehler++; } U5.6

U5-1 Externe Interrupts des AVR-mC 4 Implementierung von Interruptbehandlungen Während einer Interruptbehandlung sind andere Interrupts gesperrt Auftreten eines Interrupts wird durch Flag in Statusregister vermerkt Dieses Flag (Bit) ist entweder 0 oder 1 es kann also maximal ein Interrupt zwischengespeichert werden weitere Interrupts während einer Interruptsperre gehen verloren Gleiches gilt für mit Interruptsperren synchronisierte kritische Abschnitte Das Problem ist generell nicht zu verhindern Risikominimierung: Interruptbehandlungen sollten möglichst kurz sein sei sollte niemals in einer Interruptbehandlung ausgeführt werden potentiell endlos geschachtelte Interruptbehandlung Stackoverflow möglich U5.7 U5-2 Das volatile-schlüsselwort U5-2 Das volatile-schlüsselwort Manche Variablen werden "von außen" verändert Hardware-Register Variablen, auf die mehrere Programmabläufe nebenläufig zugreifen Threads Unterbrechungsbehandlungen Kann Probleme bei Compileroptimierungen verursachen U5.8

1 Beispiel U5-2 Das volatile-schlüsselwort Hauptprogramm wartet auf ein Ereignis, das durch einen Interrupt gemeldet wird (dieser setzt event auf 1) Aktive Warteschleife wartet, bis event!=0 Der Compiler erkennt, dass event innerhalb der Warteschleife nicht verändert wird der Wert von event wird nur einmal vor der Warteschleife aus dem Speicher in ein Prozessorregister geladen dann wird nur noch der Wert im Register betrachtet Endlosschleife static char event=0; ISR (INT0_vect) { event=1; } void main(void) { while(1) { while(event == 0) { /* warte auf Event */ } /* bearbeite Event */ U5.9 2 Beispiel (2) U5-2 Das volatile-schlüsselwort Lösung: Unterdrücken der Optimierung mit dem volatile- Schlüsselwort static volatile uint8_t event=0; ISR (INT0_vect) { event=1; } void main(void) { while(1) { while(event == 0) { /* warte auf Event */ } /* bearbeite Event */ } } Teilt dem Compiler mit, dass der Wert extern verändert wird Wert wird bei jedem Lesezugriff erneut aus dem Speicher geladen U5.10

U5-2 Das volatile-schlüsselwort 3 volatile in einem anderen Zusammenhang... Beispiel: Funktion zum aktiven Warten void wait(unsigned int len) { while(len > 0) { len--; } } Die Schleife wird terminieren Der Wert von len wird bei Verlassen der Funktion verworfen Optimierender Compiler entfernt die komplette Schleife Wartezeit wird stark verkürzt Mit volatile kann diese Optimierung verhindert werden Sonderfall: len wird nicht extern modifiziert U5.11 4 Verwendung von volatile U5-2 Das volatile-schlüsselwort Fehlendes volatile kann zu unerwartetem Programmablauf führen Unnötige Verwendung von volatile unterbindet Optimierungen des Compilers und führt zu schlechterem Maschinencode Korrekte Verwendung von volatile ist Aufgabe des Programmierers! Verwendung von volatile so selten wie möglich, aber so oft wie nötig. U5.12

Unterbrechungsbehandlungen führen zu Nebenläufigkeit Nicht-atomare Modifikation von gemeinsamen Daten Kann zu Inkonsistenzen führen Einseitige Unterbrechung: Interrupt-Handler überlappt Hauptprogramm Lösung: Synchronisationsprimitiven hier: zeitweilige Deaktivierung der Interruptbehandlung U5.13 1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 2 4 5 6 3 U5.14

1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 4 5 6 3 U5.15 1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 6 3 U5.16

1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 4 5 5 6 3 U5.17 1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 4 5 5 5 4 6 6 3 U5.18

1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 4 5 5 5 4 6 6 6 4 6 3 U5.19 1 Beispiel 1: Lost Update Tastendruckzähler: Zählt noch zu bearbeitende Tastendrücke Inkrementierung in der Unterbrechungsbehandlung Dekrementierung im Hauptprogramm zum Start der Verarbeitung volatile unsigned char zaehler; /* C-Anweisung: zaehler--; */ 1 lds r24, zaehler 2 dec r24 3 sts zaehler, r24 4 lds r25, zaehler 5 inc r25 6 sts zaehler, r25 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 4 5 5 5 4 6 6 6 4 6 3 4 4 - U5.20

2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 1 lds r22, zaehler 2 lds r23, zaehler+1 /* z verwenden... */ 3 lds r24, zaehler 4 lds r25, zaehler+1 5 adiw r24,1 6 sts zaehler+1, r25 7 sts zaehler, r24 Instruktion zaehler z HP 1 0x00ff 3-7 2 U5.21 2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 1 lds r22, zaehler 2 lds r23, zaehler+1 /* z verwenden... */ 3 lds r24, zaehler 4 lds r25, zaehler+1 5 adiw r24,1 6 sts zaehler+1, r25 7 sts zaehler, r24 Instruktion zaehler z HP 1 0x00ff 0x??ff 3-7 2 U5.22

2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 1 lds r22, zaehler 2 lds r23, zaehler+1 /* z verwenden... */ 3 lds r24, zaehler 4 lds r25, zaehler+1 5 adiw r24,1 6 sts zaehler+1, r25 7 sts zaehler, r24 Instruktion zaehler z HP 1 0x00ff 0x??ff 3-7 0x0100 0x??ff 2 U5.23 2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 1 lds r22, zaehler 2 lds r23, zaehler+1 /* z verwenden... */ 3 lds r24, zaehler 4 lds r25, zaehler+1 5 adiw r24,1 6 sts zaehler+1, r25 7 sts zaehler, r24 Instruktion zaehler z HP 1 0x00ff 0x??ff 3-7 0x0100 0x??ff 2 0x0100 0x01ff Weitere Problemszenarien? Nebenläufige Zugriffe auf Werte >8-bit müssen i.d.r. geschützt werden! U5.24

3 Sperren der Unterbrechungsbehandlung beim AVR Viele weitere Nebenläufigkeitsprobleme möglich Problemanalyse durch den Anwendungsprogrammierer Vorsicht bei gemeinsamen Daten nebenläufiger Kontrollflüsse Auswahl geeigneter Synchronisationsprimitive Lösung hier: Einseitiger Ausschluss durch Sperren der Interrupts Sperrung aller Interrupts (sei(), cli()) Maskieren einzelner Interrupts (GICR-Register) Problem: Interrupts während der Sperrung gehen evtl. verloren U5.25 U5-4 Stromsparmodi von AVR-Prozessoren U5-4 Stromsparmodi von AVR-Prozessoren AVR-basierte Geräte oft batteriebetrieben (z.b. Sensorknoten) Energiesparen kann die Lebensdauer drastisch erhöhen AVR-Prozessoren unterstützen unterschiedliche Powersave-Modi Deaktivierung funktionaler Einheiten Unterschiede in der "Tiefe" des Schlafes Nur aktive funktionale Einheiten können die CPU aufwecken Standard-Modus: Idle In tieferen Sleep-Modi wird der I/O-Takt deaktiviert nur asynchron arbeitende Einheiten können die CPU aufwecken low-level-gesteuerte externe Interrupts werden asynchron ermittelt flankengesteuerte Interrupts benötigen evtl. den Taktgeber Dokumentation im ATmega32-Datenblatt, S. 32-35 U5.26

1 Nutzung der Sleep-Modi U5-4 Stromsparmodi von AVR-Prozessoren Unterstützung aus der avr-libc: (#include <avr/sleep.h>) sleep_enable() - aktiviert den Sleep-Modus sleep_cpu() - setzt das Gerät in den Sleep-Modus sleep_disable() - deaktiviert den Sleep-Modus set_sleep_mode(uint8_t mode) - stellt den zu verwendenden Modus ein Dokumentation von avr/sleep.h in avr-libc-dokumentation verlinkt im Doku-Bereich auf der SPiC-Webseite Beispiel #include <avr/sleep.h> set_sleep_mode(sleep_mode_idle); /* Idle-Modus verwenden */ sleep_enable(); /* Sleep-Modus aktivieren */ sleep_cpu(); /* Sleep-Modus betreten */ sleep_disable(); /* Empfohlen: Sleep-Modus danach deaktivieren */ U5.27 U5-4 Stromsparmodi von AVR-Prozessoren 2 Passives Warten auf Unterbrechungen Polling bei passivem Warten nicht möglich (warum?) Beispiel: volatile static char event=0; ISR (INT2_vect) { event=1; } void main(void) { while(1) { while(event==0) { /* Warte auf Event */ sleep_enable(); sleep_cpu(); sleep_disable(); } /* bearbeite Event */ Synchronisation erforderlich? U5.28

U5-4 Stromsparmodi von AVR-Prozessoren 2 Passives Warten auf Unterbrechungen Was passiert, wenn der Interrupt wie unten gezeigt eintrifft? Beispiel: volatile static char event=0; ISR (INT2_vect) { event=1; } void main(void) { while(1) { while(event==0) { /* Warte auf Event */ sleep_enable(); Interrupt! sleep_cpu(); sleep_disable(); } /* bearbeite Event */ U5.29 2 Dornröschenschlaf vermeiden U5-4 Stromsparmodi von AVR-Prozessoren Atomarität von Wartebedingungsprüfung und Sleep-Modus-Aktivierung Beispiel: volatile static char event=0; ISR (INT2_vect) { event=1; } void main(void) { while(1) { cli(); while(event==0) { /* Warte auf Event */ sleep_enable(); sei(); sleep_cpu(); sleep_disable(); cli(); } sei(); /* bearbeite Event */ kritischer Abschnitt sei und die Folgeanweisung werden atomar ausgeführt (notwendig?) U5.30