www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Optimale Programmstruktur bei blockierenden Funktionen?


Autor: Be Bo (bebo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

bisher sahen meine Mikrocontroller-Programmer immer so aus:

1. In Interrupts wurde alles Hardwarenahe kurz und knapp erledigt. Gab 
es größere Aufgaben, wurden diese über Messages oder Datenstrukturen an 
das Hauptprogramm übergeben.
2. Mainloop: Hier wurde alles verarbeitet, was nicht zeitkritisch war. 
Allerdings habe ich die einzelnen Funktionen im Mainloop auch in 
Ausführungsblöcke aufgeteilt, damit eine Funktion die länger dauerte, 
die anderern Funktionen im Mainloop nicht unnötig lange ausbremste 
(Stichwort: kooperatives Multitasking).

Das hat auch immer alles bestens funktionniert. Da ich auf fremde 
Bibliotheken verzichtet habe, konnte ich darauf achten, daß die 
einzelnen Funktionen sich immer kooperativ verhielten (Multitasking).

Nun aber, da auch Mikrocontrollerbastelleien immer komplexer werden, 
möchte ich auch auf fremde Bibliotheken zugreifen. Insbesondere 
Microchip stellt ja eine ganze Reihe von Bibliotheken zur Verfügung.

Leider ergibt sich daraus nun ein Problem: Einige Funktionen verlangen 
nach einer regelmäßigen Ausführung (sagen wir einmal alle 1ms). Andere 
Funktionen blockieren allerdings den Mainloop mehrere 100ms lang. 
Dummerweise sind die Funktionen aber nicht asynchron ausgelegt (Funktion 
starten, Abarbeitung in Interrupts und Ergebnis später vom Hauptprogramm 
abholbar).

Nun würde ich gerne so etwas konstruieren, wie:
Prio 1: ISRs wie bisher für zeitkritische Aufgaben
Prio 2: Highprio Mainloop (bisheriger Main-Loop, der z.B. 1x pro 
Milisekunde durchlaufen wird)
Prio 3: Standard Mainloop, in dem auch blockierende Funktionen erlaubt 
sind

Dann würden die ISRs zeitunkritische Aufgaben an den Highprio Mainloop 
abgeben. Dieser soll allerdings eine Art kooperatives Multitasking 
bewältigen, d.h. dieser Mainloop darf nicht länger als eine bestimmte 
Zeit (z.B. 1ms oder 10ms) für einen Durchlauf brauchen. Gibt es nun 
Funktionen, die länger brauchen und kein kooperatives Multitasking 
unterstützen, sollten diese vom Highprio Mainloop an den Standard 
Mainloop abgegeben werden können. Dort kann dann die Funktion gern auch 
mal 1 Sekunde rumwerkeln, bis sie das Ergebnis zurückgibt.


Daraus ergibt sich für mich, daß der Inhalt des Highprio Mainloops auch 
in einen Timerinterrupt niedriger Priorität hineinmuß. Frage ist nun, 
wie macht man das am besten. Ich habe bereits eine TIMER-ISR, welche 
alle möglichen Timings erzeugt, von wenigen Mikrosekunden bis hin zu 
Minuten. Fakt ist, daß die Ausführung der gesamten TIMER-ISR nicht 
länger dauern darf, als die Zeit, bis der Timer wieder auslöst, und das 
sind unter umständen nur einige 10µs. Im Grunde könnte diese TIMER-ISR 
für das Timing des Highprio Mainloops sorgen. Nur muß der Timer bereits 
wieder auslösen dürfen, während die Funktionen des Highprio Mainloop 
noch abgearbeitet werden.

Wie löse ich so ein Problem am besten? (Ich verwenden zur Zeit einen 
PIC32 mit dem C32)

Ich bin aber auch gern für andere Vorschläge offen. Mir ist nur wichtig, 
daß solche Funktionen wie Lade_File_von_SD_Karte() den Rest der 
Schaltung nicht für 1s lahmlegen.

Grüße,
Bebo

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wird wohl oder übel auf ein präemtives RTOS rauslaufen.

Autor: Be Bo (bebo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso, gibt es keine Möglichkeit den Interrupt wieder zu enablen? Das 
würde für's erst schon reichen.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Be Bo schrieb:
> Wieso, gibt es keine Möglichkeit den Interrupt wieder zu enablen? Das
> würde für's erst schon reichen.

Du schriebst doch was von "Priorität ändern" (wenn eine Funktion zu 
lange braucht) und eben auch die Zeitüberwachung, bzw. dass ein 'Task' 
nur soundsoviele Millisekunden Laufzeit bekommt, bevor der andere wieder 
dran ist. Das klingt halt schon ziemlich nach einem Betriebssystem.

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Leider ergibt sich daraus nun ein Problem: Einige Funktionen verlangen
> nach einer regelmäßigen Ausführung (sagen wir einmal alle 1ms). Andere
> Funktionen blockieren allerdings den Mainloop mehrere 100ms lang.

Dann merkst du jetzt wo der Nachteil liegt wenn man fremden Code 
verwenden will. :-)

Natuerlich kann man einiges machen. Du kannst z.b Interrupts mit 
verschiedenen Prioritaeten verwenden wenn dein Prozessor das kann. Du 
kannst auch einen Interrupt durch einen anderen unterbrechen lassen. Du 
kannst auch viele verschiedene TimerIRQs verwenden.

Aber das aendert nichts daran das du eine ganze Menge Dinge im Auge 
behalten musst. Langfristig faehrt man dann am besten wenn man sich 
seine Funktionen selber schreibt. Oder wenn man etwas uebernehmen will, 
es so anpassen das es gut an den eigenen Programmstil angepasst ist.

Ich denke Faulheit an dieser Stelle muss man sonst wirklich mit einem 
Betriebssystem und entsprechend dicker Hardware bezahlen.

Olaf

Autor: Be Bo (bebo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Standardsachen würde ich ja auch selber machen, aber warum soll man 
nicht die Bibliotheken des Herstellers verwenden. USB-Firmware, FAT16/32 
Stack, Ethernetstack, im Grunde gibt's das bei Microchip schon fertig. 
Da allerdings Dinge abzuändern würde ich vermeiden wollen. Kommt die 
nächte Version, kann man von vorn beginnen.

Verschiedene Interruptlevel gibt es und mit einem 2. Timer wäre das 
ganze auch nicht schwierig. Ich würde aber gern darauf verzichten einen 
Timer nur für diese Funktion zu opfern. Und da ich mal von Nested 
Interrupts gelesen habe, dachte ich, das wäre das was ich brauche. Ich 
weiß allerdings nicht, wie man das Programmiert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.