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

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

U5 Fortgeschrittene AVR-Programmierung

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

Ü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

Übungen zu Systemnahe Programmierung in C (SPiC)

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

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

U5-2 Register beim AVR-µC

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

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

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

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

... Polling. Interrupt: c dl GSPiC (Teil C, SS 11) 15 Nebenläufigkeit 15.1 Interrupts: Einführung 15 1

Systemnahe Programmierung in C (SPiC)

Systemnahe Programmierung in C (SPiC)

Systemnahe Programmierung in C (SPiC)

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

d) Welche Aussage zum Thema virtueller Adressraum ist richtig?

d) Welche Aussage zu Zeigern ist richtig? Beim Rechnen mit Zeigern wird immer der Typ des Zeigers beachtet.

Unter einem Interrupt kann man sich einen durch Hardware ausgelösten Unterprogrammaufruf vorstellen.

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

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

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

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

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

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

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

Wiederholung: Zugriff auf AVR-Prozessor-Register

d) Welche Aussage zu volatile 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?

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

J Mikrocontroller-Programmierung

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

U4 Grundlagen der C-Programmierung

GdI 2 Systemnahe Programmierung in C

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

U3 UNIX-Signale U3 UNIX-Signale

Richtung durch Taster während des Ablaufs umschaltbar

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

E Mikrocontroller-Programmierung

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

Einleitung Die Pins alphabetisch Kapitel 1 Programmierung des ATmega8 und des ATmega

e) Welchen Wert hat die Variable i nach Ausführung der folgenden Zeilen Code: x25 0x84 b) Welche Aussage zu folgender Funktion ist richtig?

Interruptsystem AVR. Interrupt-Quellen: Extern, Timer, ADC, USART usw. (siehe IVT im Anhang) Rücksprungadresse automatisch am Stack.

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

2.1 Atmega-Peripherie/Interrupts

myavr Programmierung in C

PIC16 Programmierung in HITECH-C

U4 Grundlagen der C-Programmierung

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

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

Übung zu Betriebssysteme

Mikrocomputertechnik

Nebenläufige Programmierung in Java: Threads

Microcontroller Selbststudium Semesterwoche 9

i386 Interrupt-Deskriptortabelle (IDT)

J Mikrocontroller-Programmierung. J.2 Mikrocontroller vs. Betriebssystem-Plattform. 1 Betriebssystemunterstützung. J.1 Überblick

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

Übungen zu Systemnahe Programmierung in C (SPiC)

Aufbau eines Assembler-Programms

Tag 2 Eingabe und Interrupts

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

Betriebssysteme. Vorlesung im Herbstsemester 2010 Universität Mannheim. Kapitel 6: Speicherbasierte Prozessinteraktion

Erste Schritte der Programmierung in C

Memory Models Frederik Zipp

Laborskript Verteilte Systeme

U3 3. Übung U3 3. Übung. Systemnahe Programmierung in C Übungen Moritz Strübe Universität Erlangen-Nürnberg Informatik 4, 2009 U3.fm

Besprechung Aufgabe 1. Pointer. Register und Ports. SPiC - Ü U3.1

Übung zu Betriebssystembau (Ü BS)

U3 Grundlagen der AVR-Programmierung

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

Betriebssystembau. 3. Übung. Michael Engel Arbeitsgruppe Eingebettete Systemsoftware. Lehrstuhl für Informatik 12 TU Dortmund

Interrupts. Funktionsprinzip. Funktionsprinzip. Beispiel in C

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

Übungen zu Systemnahe Programmierung in C (SPiC)

Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Sebastian Maier (Lehrstuhl Informatik 4) Übung 10. Sommersemester 2016

Rainbow-OS Architekturseminar Thema: Interrupt-Controller

Timer. Funktionsprinzip

Fakultät für Informatik der Technischen Universität München. Kapitel 3. Nebenläufigkeit

IR NEC Empfänger mit 4x7 LED Anzeige (ATtiny2313)

2

Einführung DIP & AVR EVK1100

Einführung in AVR Assembler

Übungen zu Systemnahe Programmierung in C (SPiC)

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

B4 Interrupts (Unterbrechungen)

(a) Wie unterscheiden sich synchrone und asynchrone Unterbrechungen? (b) In welchen drei Schritten wird auf Unterbrechungen reagiert?

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

Übungen zu Systemprogrammierung 2 (SP2)

Teil 6: PIC Studiengang Technische Informatik (TI) Prof. Dr.-Ing. Alfred Rożek. nur für Lehrzwecke Vervielfältigung nicht gestattet

Software ubiquitärer Systeme

Übungen zu Systemprogrammierung 2 (SP2)

Übungen zu Systemnahe Programmierung in C (SPiC) Sommersemester 2018

Anschluss von Peripherien Jiri Spale, Programmierung eingebetteter Systeme 1

Transkript:

U Fortgeschrittene AVR-Programmierung U Fortgeschrittene AVR-Programmierung U-1 Externe Interrupts des AVR-μC Aufgabe Interrupts volatile-variablen Synchronisation mit Unterbrechungsbehandlungen Stromsparmodi des AVR 1 Flanken-/Pegel-Steuerung Externe Interrupts durch Pegel(änderung) an bestimmten I/O-Pins ATmega: Quellen an den Pins PD, PD und PB Pegel- oder flanken-gesteuert Abhängig von der jeweiligen Interruptquelle Beispiel: Externer Interrupt (INT) ISC IRQ bei: 0 Fallender Flanke 1 Steigender Flanke U.1 Dokumentation im ATmega-Datenblatt Interruptbehandlung allgemein: S. 44-48 Externe Interrupts: S. -8 U. 1 Flanken-/Pegel-Steuerung () Maskieren Beim ATmega 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 (INT) Beispiel: INT bei ATmega für fallende Flanke konfigurieren /* die ISCs für INT befinden sich im MCUCSR */ MCUCSR &= ~(1<<ISC); /* ISC löschen */ Alle Interruptquellen können separat ausgeschaltet (=maskiert) werden Für externe Interrupts ist folgendes Register zuständig: ATmega: General Interrupt Control Register (GICR) Die Bitpositionen in diesem Register sind durch Makros INTn definiert Ein gesetztes Bit aktiviert den jeweiligen Interrupt Beispiel: Interrupt aktivieren GICR = (1<<INT); /* demaskiere Interrupt */ U. U.4

Maskieren () Interrupt-Handler 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 (im nächsten Takt) zu cli() - blockiert alle Interrupts (sofort) Beispiel #include <avr/interrupt.h> sei(); /* IRQs zulassen */ 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. INT_vect für den externen Interrupt verfügbare Vektoren: siehe avr-libc-doku zu avr/interrupt.h verlinkt im Doku-Bereich auf der SPiC-Webseite Beispiel: Handler für Interrupt implementieren #include <avr/interrupt.h> static int zaehler; 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 U.5 ISR (INT_vect) { zaehler++; U. 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 (GIFR) 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 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 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 U.7 U.8

1 Beispiel Beispiel () Hauptprogramm wartet auf ein Ereignis, das durch einen Interrupt gemeldet wird (dieser setzt event auf 1) Lösung: Unterdrücken der Optimierung mit dem volatile- Schlüsselwort Aktive Warteschleife wartet, bis event!=0 static volatile uint8_t event=0; ISR (INT0_vect) { event=1; 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; while(event == 0) { /* warte auf Event */ U.9 while(event == 0) { /* warte auf Event */ Teilt dem Compiler mit, dass der Wert extern verändert wird Wert wird bei jedem Lesezugriff erneut aus dem Speicher geladen U.10 volatile in einem anderen Zusammenhang... 4 Verwendung von volatile 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 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. Ab sofort: Alle Programme müssen auch mit -O funktionieren U.11 U.1

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 U.1 1 5 4 5 U.14 4 5 U.15 4 5 U.1

4 5 4 5 5 U.17 4 5 4 5 5 5 4 U.18 4 5 4 5 5 5 4 4 U.19 4 5 4 5 5 5 4 4 4 4 - U.0

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

Sperren der Unterbrechungsbehandlung beim AVR Viele weitere Nebenläufigkeitsprobleme möglich Problemanalyse durch den Anwendungsprogrammierer Vorsicht bei gemeinsamen Daten nebenläufiger Kontrollflüsse AVR-basierte Geräte oft batteriebetrieben (z.b. Sensorknoten) Energiesparen kann die Lebensdauer drastisch erhöhen Auswahl geeigneter Synchronisationsprimitive AVR-Prozessoren unterstützen unterschiedliche Powersave-Modi 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 Interrupts sollten so kurz wie möglich gesperrt werden U.5 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 ATmega-Datenblatt, S. -5 U. 1 Nutzung der Sleep-Modi Passives Warten auf Unterbrechungen 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 */ U.7 Polling bei passivem Warten nicht möglich (warum?) Beispiel: volatile static char event=0; ISR (INT_vect) { event=1; while(event==0) { /* Warte auf Event */ sleep_enable(); sleep_cpu(); sleep_disable(); Synchronisation erforderlich? U.8

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