Interrupt in C
Zur Verwendung und Behandlung von Interrupts in C-Quellen ist das Einbinden von vorgefertigtem Assemblercode nötig. Seine Aufgabe besteht in der Maskierung und Verteilung ausgelöster Interrupts.Interrupts im GCC behandeln
Weiter Informationen stehen im Wiki unter Assemblerbefehle zur Interrupt Steuerung.
Sekunden Interrupt in C mit Ausgabe eines Wertes auf SFR_LED
Beim SpartanMC ist auch die Programmierung von ISR Programmen in C möglich. Dazu muss zusammen mit dem startup Kode in der Firmware make Datei "config-build.mk" ein Assembler Programm geladen werden. Der Systembuilder jConfig erstellt für alle im System installierten Geräte zwei Dateien, die immer als Include in einem C-Programm eingebunden werden müssen. Im #include <system/hardware.h> werden für jedes Gerät die im jConfig getroffenen Einstellungen übergeben. Alle Einstellungen können also im C-Programm abgefragt werden. Die zweite Datei #include <system/peripherals.h> legt für alle Geräte den Namen der Geräteregister-Struktur fest. Wurde im jConfig der zu verwendende Timer Modul auf seiner Seite mit "timer_1" bezeichnet, dann bekommt die Registerstruktur des Timers in dem #include <system/peripherals.h> die Bezeichnung "TIMER_1". In dieser Datei werden auch automatisch alle *.h Dateien für alle implementierten Geräte geladen. Der Programmierer muss also nur noch die Register der verwendete Geräte initialisieren um sie zu verwenden. Soll also das Register für den maximalen Zählerwert vom Timer geladen werden, dann erfolgt das in der Form:
TIMER_1->limit = 195313;
Die Namen aller Geräteregister des Timers und aller vorbereiteten Konstanten findet man in der "timer.h" Datei auf der Wiki-Seite zum Timer.
Zur Erzeugung eines Sekundeninterrupt wird eine Konfiguration mit einem TIMER Modul, dessen Eingang mit dem System Takt von 25 MHz verbunden ist eingesetzt. Das höchste Bit des TIMER Zählerregisters ist dann mit dem Eingang eines RTI Moduls verbunden, der dann den Interrupt auslösen soll. Mit den Vorteilern vom RTI von 2⁰ bis 2¹⁵, dem Vorteiler vom TIMER von 2¹ bis 2⁸ und dem einstellbaren maximalen Wert vom Zähler des Timer von 2¹⁷ < wert < 2¹⁸ -1 muss der Sekunden Interrupt eingestellt werden. Beim Test hat sich eine Einstellung auf (2¹⁷ + 64241) * 2⁷ = 195313 * 128 = 25000064 als günstigste Variante herausgestellt, bei der die Sekunde sehr genau eingehalten wird. Die 2⁷ wurde mit 2⁴ im Vorteiler des TIMER und 2³ im RTI eingestellt.
#include <system/peripherals.h> #include <interrupt.h> #include <led7.h> /* Zuordnung der Interrupts */ #define isr_rti0 isr00 // Sekunden Interupt von RTI0 /* * Werte fuer RTI0 Interrupt in jeder Sekunde */ /* * Impuls mit einer Periodendauer von 0,125s aus 25MHz erzeugen. Fuer den Sekundenimpuls * an RTI0 bringen die Vorteiler vom TIMER = 2^4 und RTI0 = 2^3 den Wert 16 * 8 = 128. * Der Rest muss vom Haupteiler des Timers kommen und muss die Bedingung * 2^17 < Wert < (2^18 -1) erfuellen. * 2^17 = 131072 * int(25000000 / 128)+1 = 195313 erfuellt die Bedingung * 2^18 – 1 = 262143 * Die Periodendauer des Impuls am TIMER Ausgang ergibt sich damit zu: * (1 / 25000000 Hz)*(int(25000000 / 128)+1) * 16 = 0,00000004s * 195313 * 16 = 0,12500032s */ #define LI_TIMER1 ((25000000 / 128)+1) // limit fuer Timer 1 #define VT_TIMER1 4 // TIMER_PRE_VAL = 2^4 #define VT_RTI0 3 // RTI_PRE_VAL = 2^3 // Variablen der ISR-Fuktionen unsigned int i; // Wert zur Ausgabe auf die LEDs /* * Timer und LED Testprogramm */ void main(void) { // Initialisierung der Geraete interrupt_disable(); TIMER_1->control = TIMER_EN|TIMER_PRE_EN|(TIMER_PRE_VAL*(VT_TIMER1-1)); TIMER_1->limit = LI_TIMER1; // getesteter Wert fuer eine Sekunde RTI_0->ctrl = RTI_EN|RTI_EN_INT|(RTI_PRE_VAL*VT_RTI0); // Initialisierung beendet interrupt_enable(); while (1) { } } /* Funktionen zur Interrupt Behandlung */ // Sekunden Interupt von RTI0 void isr_rti0() { volatile int rtictrl; rtictrl = RTI_0->ctrl; // Interrupt ruecksetzen i++; if (i>=128) i=0; led7_set(i); // Wert auf LEDs ausgeben }
Vollständige C-Quellen für die Konfiguration der Förderband4 Version:
- Wertausgabe auf die LED in jeder Sekunde timer_led.c
- Uhrzeit auf der Konsole anzeigen und LED timer_led_pr.c