Die Grösse der primitiven Datentypen in C ist architekturabhängig

Ähnliche Dokumente
U5 Fortgeschrittene AVR-Programmierung U5 Fortgeschrittene AVR-Programmierung. Synchronisation mit Unterbrechungsbehandlungen

U5 Fortgeschrittene AVR-Programmierung

U2 Fortgeschrittene AVR-Programmierung. U2-1 Externe Interrupts des AVR-μC. 1 Flanken-/Pegel-Steuerung. 1 Flanken-/Pegel-Steuerung (2) 2 Maskieren

Übungen zu Systemnahe Programmierung in C (SPiC)

Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Moritz Strübe, Rainer Müller (Lehrstuhl Informatik 4) Sommersemester 2014

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Implementierung von Interruptbehandlungen. Interrupts

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18

Übungen zu Systemnahe Programmierung in C (SPiC)

U5-1 Symboltabellen. statische Bibliotheken. Besprechung 3. Aufgabe (smash) Erstellen von C-Funktionsbibliotheken RCS

Wiederholung: Zugriff auf AVR-Prozessor-Register. Aufgabe 3: 7seg-Modul der SPiCboard-Bibliothek

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

Zeiger vom Typ (void *) sind am besten für Zeigerarithmetik geeignet, da sie kompatibel zu jedem Zeigertyp sind.

Wiederholung: Zugriff auf AVR-Prozessor-Register. Aufgabe 3: 7seg-Modul der SPiCboard-Bibliothek

Wiederholung: Zugriff auf AVR-Prozessor-Register

U3-1 Register beim AVR-μC. U3 3. Übung. U3-2 I/O-Ports des AVR-μC. 1 Überblick. 2 Makros für Register-Zugriffe. 1 Überblick

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Globale Variablen

Zeiger vom Typ void* benötigen weniger Speicher als andere Zeiger, da bei anderen Zeigertypen zusätzlich die Größe gespeichert werden muss.

Übungen zu Systemnahe Programmierung in C (SPiC)

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Schnittstellenbeschreibung. Inhalt

U4 Grundlagen der C-Programmierung

Microcontroller Praktikum SS2010 Dipl. Ing. R. Reisch

U2-1 Register beim AVR- C. U2-2 I/O-Ports des AVR- C. 1 Überblick. 2 Makros für Register-Zugriffe. 1 Überblick

U5 5. Übung U5 5. Übung

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt

Sebastian Maier (Lehrstuhl Informatik 4) Übung 4. Sommersemester 2017

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

myavr Programmierung in C

f) Was versteht man beim Zugriff auf I/O-Register unter dem Begriff "Memory-mapped"?

Übungen zu Grundlagen der systemnahen Programmierung in C (GSPiC) im Wintersemester 2017/18

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

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2018/19

Systemnahe Programmierung in C Übungen Moritz Strübe, Michael Stilkerich Universität Erlangen-Nürnberg Informatik 4, 2010 U2.fm

d) Was passiert, wenn das folgende Programmstück übersetzt und ausgeführt

C++ - Einführung in die Programmiersprache Header-Dateien und Funktionen. Leibniz Universität IT Services Anja Aue

Datentypen mit fester Größe. Bitoperatoren. Funktionen. Nachtrag Compiler. Aufgabe 2. SPiC - Ü U2.1

b) Was bewirken folgende Programmanweisungen? uint8_t x = 42; x ^= x;

Inhalt. Aufgabe 4: LED-Modul Hinweise Testen des Moduls Sommersemester 2015

a) Welche Aussage zu Zeigern ist richtig? Die Übergabesemantik für Zeiger als Funktionsparameter ist callby-value.

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18

4 Formelsammlung C/C++

Einführung in die Programmiersprache C

U3 UNIX-Signale U3 UNIX-Signale

Einführung in die Programmiersprache C

Zeiger vom Typ (void *) sind am besten für Zeigerarithmetik geeignet, da sie kompatibel zu jedem Zeigertyp sind.

U4 Grundlagen der C-Programmierung

U5-2 Register beim AVR-µC

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

Arduino Kurs Timer und Interrupts. Stephan Laage-Witt FES Lörrach

Stopp-Uhr. Erstellen Sie ein Programm (in Zweier- bzw. Dreier-Gruppen), welches folgende Bedingungen erfüllt:

Globale Variablen Diverses. Globale Variablen. Globale Variablen

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

d) Welche Aussage zu volatile ist richtig?

d) Welche Aussage zum Thema virtueller Adressraum ist richtig?

A B C D E C 5 7 D 3 E. 2. [6-Bit, positiv] Welche Dezimalzahl wird durch die gegebene Bit-Sequenz kodiert?

GdI2 - Systemnahe Programmierung in C Übungen Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2006 U4.fm

Erste Schritte der Programmierung in C

Hinweise C-Programmierung

C++ Klassen, Vererbung. Philipp Lucas. Sebastian Hack. Wintersemester 2008/09. saarland.

Mikrocontrollerplatine vorbereiten

Praxisorientierte Einführung in C++ Lektion: "Die Compiler-Chain (Vom Quellcode zum ausführbaren Programm)"

Einführung in die Programmiersprache C

Einführung in die Programmiersprache C

Übungen zu Systemnahe Programmierung in C (SPiC)

Einführung in die Programmierung Wintersemester 2016/17

Praxisorientierte Einführung in C++ Lektion: "Die Compiler-Chain (Vom Quellcode zum ausführbaren Programm)"

Einführung in die Programmierung

Systempraktikum im Wintersemester 2009/2010 (LMU): Vorlesung vom Foliensatz 2

J Mikrocontroller-Programmierung

Repetitorium Programmieren I + II

Grundlagen der Informatik 2 Modul Systemnahe Programmierung in C (SPiC) Klausur am 25. Juli 2008

Einführung in die C-Programmierung

V cc. 1 k. 7 mal 150 Ohm

U3 Grundlagen der AVR-Programmierung

Programmieren in C. Macros, Funktionen und modulare Programmstruktur. Prof. Dr. Nikolaus Wulff

Berichte aus der Informatik. Dieter Pawelczak. Start in die C-Programmierung

Überblick: Teil C Systemnahe Softwareentwicklung

Friedrich-Alexander-Universität Erlangen-Nürnberg

Programmierung mit C Modularisierung von Programmen. Präprozessor-Anweisungen nutzen.

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

Grundlagen der Informatik 2 Modul Systemnahe Programmierung in C (SPiC) Klausur am 9. April 2008

Aufbau eines Assembler-Programms

Arduino Kurs Bits und Bytes. Stephan Laage-Witt FES Lörrach

Memory Models Frederik Zipp

Modulare Programmierung und Bibliotheken

Praktikum DST (MRT Teil) 1. Termin

Grundlagen der Systemnahen Programmierung in C (GSPiC)

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 29

µversion 2 Einführung

PIC16 Programmierung in HITECH-C

Atmega Interrupts. Rachid Abdallah Gruppe 3 Betreuer : Benjamin Bös

Microcontroller Selbststudium Semesterwoche 9

Interrupts. Funktionsprinzip. Funktionsprinzip. Beispiel in C

Transkript:

U2 2. Übung U2 2. Übung Datentypen mit fester Größe (Statische) Programmbibliotheken SPiCboard-Bibliothek Wiederholung: volatile Wiederholung: Nebenläufigkeit / Synchronisation Aufgabe 1 U2.1 U2-1 Datentypen fester Größe U2-1 Datentypen fester Größe Die Grösse der primitiven Datentypen in C ist architekturabhängig Beispiel für drei Architekturen (Angaben in Bits) 8-bit AVR Intel x86-32 x86-64 Intel char 8 8 8 short 16 16 16 int 16 32 32 long 32 32 64 Probleme Portabilität des Quellcodes eingeschränkt Insbesondere in der hardwarenahen Programmierung braucht man oft Datentypen einer bekannten, festen Grösse (I/O-Register) U2.2

U2-1 Datentypen fester Größe U2-1 Datentypen fester Größe C99 definiert neue Datentypen mit definierter Grösse Auszug der wichtigsten Typen: int8_t uint8_t int16_t uint16_t int32_t uint32_t 8-bit signed 8-bit unsigned 16-bit signed 16-bit unsigned 32-bit signed 32-bit unsigned verfügbar durch Einbinden von stdint.h wird auch mit vielen nicht C99-konformen Compilern geliefert kann ansonsten auch relativ einfach selbst erstellt werden die Grösse von Zeigertypen ist immer architekturabhängig (Adressbusbreite) U2.3 U2-2 Statische Bibliotheken U2-2 Statische Bibliotheken Zugriff auf Funktionen und Variablen über symbolische Namen Eine Übersetzungseinheit (C-Datei) definiert und verwendet Symbole Hauptprogramm definiert das Symbol main für die main-funktion Programm ruft (verwendet) eine Funktion der C-Bibliothek (z.b. malloc) C-Datei definiert eine globale (nicht-static) Variable Programm verwendet eine globale Variable, die u.u. in einer anderen Übersetzungseinheit definiert wurden Der Namensraum ist flach jeder Name muss eindeutig sein es darf auch keine Funktion mit dem Namen einer globalen Variable geben Kompilierte Übersetzungseinheit (Objekt-Datei) enthält Symboltabelle Liste mit Symbolen, die von der Einheit verwendet werden Liste von Symbolen, die von der Einheit definiert werden U2.4

U2-2 Auflösung von Symbolreferenzen U2-2 Statische Bibliotheken Statisches Binden: Binden der Übersetzungseinheiten zum Binärabbild Offene Symbolreferenzen werden aufgelöst definiert in anderen Übersetzungseinheiten Suche in Programmbibliotheken GCC sucht beim Binden implizit in der Standard C-Bibliothek (libc.a) weitere Bibliotheken können vom Entwickler angegeben werden U2.5 U2-2 Statische Bibliotheken U2-2 Statische Bibliotheken Archiv (Dateiendung.a) von Objekt-Dateien (.o-dateien) Erstellen einer Bibliothek mit dem Kommando ar avr-ar rcs libexample.a bar.o foo.o Jede Objekt-Datei enthält wiederrum eine Symboltabelle Anzeige mit dem Kommando avr-nm libexample.a bzw. avr-nm bar.o Die Bibliothek kann dem Linker als Symbolquelle angeboten werden Parameter -Lpfad: Suche nach Bibliotheken (.a-dateien) in pfad Parameter -llibname: Binden mit der Bibliothek libname diese wird in einer Datei liblibname.a in den Suchpfaden gesucht Der Linker bindet dann alle Objekt-Dateien, die bis dahin unaufgelöste Symbole definieren, zum Binärabbild dazu Die Reihenfolge von Objekt-Dateien und Bibliotheken ist wichtig U2.6

U2-2 Statische Bibliotheken U2-2 Beispiel: Kompilieren mit Bibliotheken #include <bar.h> void main ( void ) { bar ( 42 ); #ifndef BAR_H #define BAR_H void bar ( int ); #include <bar.h> void bar ( int param ) { /* do some magic */ #endif main.c bar.h (Schnittstelle) bar.c (Implementierung) Module exportieren eine Schnittstelle (Header-Datei) Funktionsdeklarationen und ggf. Deklarationen (extern) globaler Variablen Beim Übersetzen muss der Compiler den Typen eines Symbols kennen Einbinden der Schnittstellenbeschreibung mit #include <bar.h> Die Adresse der Funktion bzw. Variable ist an dieser Stelle nicht notwendig Parameter -Ipfad: Teilt Compiler zusätzlichen Suchpfad für Headerdateien mit avr-gcc -c <...> -I/myincludes main.c U2.7 U2-2 Statische Bibliotheken U2-2 Beispiel: Binden mit statischen Bibliotheken #include <bar.h> void main ( void ) { bar ( 42 ); #ifndef BAR_H #define BAR_H void bar ( int ); #include <bar.h> void bar ( int param ) { /* do some magic */ #endif main.c bar.h (Schnittstelle) bar.c (Implementierung) Modul bar definiert Symbol bar ( Funktion void bar(int); ) Hauptprogramm ruft die Funktion bar auf (verwendet Symbol bar) Annahme: Modul bar.o ist Teil der Bibliothek libexample.a in /libbase Übersetzung mit Kommando: avr-gcc -L/libbase -o main.elf <...> main.o -lexample Falsch (warum?): avr-gcc -L/libbase -o main.elf <...> -lexample main.o U2.8

U2-3 SPiCboard-Bibliothek U2-3 SPiCboard-Bibliothek modular einfacher Zugriff auf die Hardware ohne diese selbst zu programmieren die einzelnen Module eignen sich selbst gut als Übungsaufgabe - Schnittstellenbeschreibung im Doku-Bereich auf der Webseite (timer und button sind jedoch relativ schwierig) Header und Bibliothek libspicboard.a in /proj/i4spic/pub/i4 installiert Anwendung 7seg timer button adc led U2.9 U2-3 Timer-Modul U2-3 SPiCboard-Bibliothek Erlaubt Registrierung sog. Alarms und ms-genaues Warten Ein Alarm ist beschrieben durch drei Parameter Aktion (Callback-Funktion), die ausgeführt wird wenn der Alarm auslöst Alarmzeit: Zeitspanne relativ zum aktuellen Zeipunkt in ms, nach deren Verstreichen der Alarm auslösen soll Zyklus: Zeitspanne in ms, in der der Alarm nach der Erstauslösung periodisch immer wieder auslöst. Ist die Zeitspanne 0, so löst der Alarm nur ein einziges Mal aus (nicht-zyklisch). 1 Delay-Funktion zur Realisierung von Wartezeiten int8_t sb_timer_delay(uint16_t waittime); Wartet waittime Millisekunden Rückgabe: Im Erfolgsfall 0, sonst -1 (Wartezeit u.u. nicht verstrichen!) U2.10

2 Aktivieren eines Alarms U2-3 SPiCboard-Bibliothek Angabe einer Rückruf (Callback)-Funktion diese wird, ähnlich einem Interrupthandler (ISR), bei Ablauf des Alarms asynchron ausgeführt es gelten die selben Randbedingungen wie bei ISRs Eine Alarmcallback-Funktion hat den Typ void callbackfunktion(void); Registrierung eines neuen Alarms mit ALARM *sb_timer_setalarm(alarmcallback_t cb, uint16_t alarmtime, uint16_t cycletime); die Funktion liefert einen Zeiger auf einen abstrakten ALARM-Datentyp im Fehlerfall wird NULL zurückgeliefert, der ALARM wurde nicht aktiviert diese Referenz kann nachher zum Abbruch des Alarms verwendet werden U2.11 3 Abbruch einer aktiven Verzögerung U2-3 SPiCboard-Bibliothek Funktion void sb_timer_delay_abort(); Kann nur auf ISR-Level ausgeführt werden (Programm gerade im Delay) Bricht eine aktive Verzögerung ab 4 Abbruch eines laufenden Alarms Funktion uint8_t sb_timer_cancelalarm(alarm *alrm); Parameter ist die Referenz auf einen aktiven Alarm diese Referenz hat man von sb_timer_setalarm erhalten Nach dem Abbruch verliert die Referenz ihre Gültigkeit Die Funktion liefert 0 im Erfolgsfall, -1 im Fehlerfall (ungültige Referenz) U2.12

U2-3 7seg-Modul (7-Segment-Anzeigen) U2-3 SPiCboard-Bibliothek Ansteuerung der beiden 7-Segment-Anzeigen Verwendet Timer-Modul zur schnellen Umschaltung quasi-parallele Nutzung der beiden Anzeigen möglich Anzeige von Dezimalzahlen im Bereich [-9; 99] int8_t sb_7seg_shownumber(int8_t number); Deaktivierung der 7-Segment-Anzeigen void sb_7seg_disable(void); weitere Anzeigemöglichkeiten API-Dokumentation U2.13 U2-4 Button-Modul (Taster) U2-4 Button-Modul (Taster) Das Board verfügt über zwei Taster (Ort siehe Board-Übersicht) C-Datentyp: BUTTONEVENT BUTTON0: hardwareseitig entprellt BUTTON1: softwareseitig durch SPiCboard-Bibliothek entprellt für die Anwendung sind beide Taster gleichermaßen verwendbar Anwendung kann sich für Tasterereignisse an einem Taster registrieren C-Datentyp: BUTTONEVENT BTNPRESSED: Taster wurde gedrückt BTNRELEASED: Taster wurde losgelassen bitweise Veroderung ermöglicht Registrierung für beide Ereignisse U2.14

1 Rückruffunktion für Tasterereignisse U2-4 Button-Modul (Taster) void buttoncallback(button btn, BUTTONEVENT eve); Parameter btn: ID des Buttons, der gedrückt wurde Parameter eve: Typ des eingetretenen Ereignisses Die gleiche Funktion kann bei verschiedenen Tastern für verschiedene Ereignisse registriert werden, pro Taster/Ereignis jedoch nur einmal Auch diese Rückruffunktion wird auf ISR-Ebene ausgeführt U2.15 U2-4 Button-Modul (Taster) 2 Anmeldung für Benachrichtigung bei Tasterevents uint8_t sb_button_registerlistener( BUTTON btn, BUTTONEVENT eve, buttoncallback_t callback); btn: für welchen Button sollen Events gemeldet werden eve: für welches Tasterereignis soll eine Benachrichtigung erfolgen (Drücken, Loslassen, oder beides) callback: die Funktion, die zur Benachrichtigung aufgerufen wird 3 Abmeldung, Polling siehe Online-Dokumentation U2.16

U2-5 Beispiel: Countdown von 99-0 mit Resettaste U2-5 Beispiel: Countdown von 99-0 mit Resettaste #include <timer.h> #include <7seg.h> #include <button.h> #include <avr/interrupt.h> static int8_t cnt; static void reset ( BUTTON btn, BUTTONEVENT eve ) { cnt = 99; void main( void ) { sb_button_registerlistener(button0, BTNPRESSED, reset); sei(); /* Interrupts initial erlauben */ while ( 1 ) { for(cnt=99; cnt >= 0; ) { sb_7seg_shownumber(cnt); /* akt. Zahl anzeigen */ sb_timer_delay(100); /* 100 ms warten */ cnt--; /* countdown */ sb_timer_delay(5000); /* 5s warten, dann von vorn beginnen */ U2.17 U2-6 Wiederholung: der volatile-qualifier U2-6 Wiederholung: der volatile-qualifier 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 U2.18

1 Beispiel U2-6 Wiederholung: der volatile-qualifier Hauptprogramm wartet auf ein Ereignis, das durch einen Interrupt gemeldet wird (dieser setzt event auf 1) Aktive Warteschleife wartet, bis event!= 0 Der Compiler sieht, 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 */ U2.19 2 Beispiel (2) U2-6 Wiederholung: der volatile-qualifier Lösung: Unterdrücken der Optimierung mit dem volatile-schlüsselwort static volatile char 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 Sofort-Aufgabe: Schreiben Sie gemeinsam ein Programm, das ähnlich obigem Beispiel die Bibliothek verwendet. Das Programm soll auf ein Event warten (wie oben), das von einem Taster-Eventhandler gesetzt wird. Danach aktiviert das Programm eine LED zur Bestätigung. Kompilieren und Testen Sie das Programm mit -O0 sowie -O3. U2.20

U2-6 Wiederholung: der volatile-qualifier 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 U2.21 4 Verwendung von volatile U2-6 Wiederholung: der volatile-qualifier 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 U2.22

5 volatile im Beispielprogramm? #include <timer.h> #include <7seg.h> #include <button.h> #include <avr/interrupt.h> static int8_t cnt; static void reset ( BUTTON btn, BUTTONEVENT eve ) { cnt = 99; U2-6 Wiederholung: der volatile-qualifier void main( void ) { sb_button_registerlistener(button0, BTNPRESSED, reset); sei(); /* Interrupts initial erlauben */ while ( 1 ) { for(cnt=99; cnt >= 0; ) { sb_7seg_shownumber(cnt); /* akt. Zahl anzeigen */ sb_timer_delay(100); /* 100 ms warten */ cnt--; /* countdown */ sb_timer_delay(5000); /* 5s warten, dann von vorn beginnen */ U2.23 5 volatile im Beispielprogramm? #include <timer.h> #include <7seg.h> #include <button.h> #include <avr/interrupt.h> static volatile int8_t cnt; static void reset ( BUTTON btn, BUTTONEVENT eve ) { cnt = 99; U2-6 Wiederholung: der volatile-qualifier void main( void ) { sb_button_registerlistener(button0, BTNPRESSED, reset); sei(); /* Interrupts initial erlauben */ while ( 1 ) { for(cnt=99; cnt >= 0; ) { sb_7seg_shownumber(cnt); /* akt. Zahl anzeigen */ sb_timer_delay(100); /* 100 ms warten */ cnt--; /* countdown */ sb_timer_delay(5000); /* 5s warten, dann von vorn beginnen */ U2.24

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 U2.25 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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 Instruktion zaehler zaehler HP zaehler INT 1 5 2 4 5 6 3 U2.26

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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 4 5 6 3 U2.27 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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 6 3 U2.28

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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 4 5 5 6 3 U2.29 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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 Instruktion zaehler zaehler HP zaehler INT 1 5 5-2 5 4-4 5 4 5 5 5 4 6 6 3 U2.30

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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 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 U2.31 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--; */ 2 dec r24 3 sts zaehler, r24 4 lds r24, zaehler 5 inc r24 6 sts zaehler, r24 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 - U2.32

2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 2 lds r25, 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 U2.33 2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 2 lds r25, 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 U2.34

2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 2 lds r25, 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 U2.35 2 Beispiel 2: 16-bit-Zugriffe Nebenläufige Nutzung von 16-bit-Werten volatile unsigned int zaehler; /* C-Anweisung: z=zaehler; */ 2 lds r25, 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! U2.36

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 U2.37 4 Synchronisation im Beispiel? #include <timer.h> #include <7seg.h> #include <button.h> #include <avr/interrupt.h> static int8_t cnt; static void reset ( BUTTON btn, BUTTONEVENT eve ) { cnt = 99; void main( void ) { sb_button_registerlistener(button0, BTNPRESSED, reset); sei(); /* Interrupts initial erlauben */ while ( 1 ) { for(cnt=99; cnt >= 0; ) { sb_7seg_shownumber(cnt); /* akt. Zahl anzeigen */ sb_timer_delay(100); /* 100 ms warten */ cnt--; /* countdown */ sb_timer_delay(5000); /* 5s warten, dann von vorn beginnen */ U2.38

4 Synchronisation im Beispiel? Lost Update Problem #include <timer.h> #include <7seg.h> #include <button.h> #include <avr/interrupt.h> static volatile int8_t cnt; static void reset ( BUTTON btn, BUTTONEVENT eve ) { cnt = 99; void main( void ) { sb_button_registerlistener(button0, BTNPRESSED, reset); sei(); /* Interrupts initial erlauben */ while ( 1 ) { for(cnt=99; cnt >= 0; ) { sb_7seg_shownumber(cnt); /* akt. Zahl anzeigen */ sb_timer_delay(100); /* 100 ms warten */ cli(); cnt--; sei(); /* countdown, sync wozu? */ sb_timer_delay(5000); /* 5s warten, dann von vorn beginnen */ U2.39 U2-8 Aufgabe 1 U2-8 Aufgabe 1 Messung der Dauer eines Tastendrucks in 100 ms Intervallen Anzeige der laufenden Messung auf den 7-Segment-Anzeigen Anzeige des Ergebnisses auf den 7-Segment-Anzeigen Verwendung der SPiCboard-Bibliothek zur Implementierung U2.40