Hallo Zusammen,
ich habe mal eine allgemeine Frage. Ich habe mir mittlerweile viele
Headerdatein geschrieben und möchte diese nun in verschiedenen
Programmen verwenden. Aber diese sollen dann strukturiert aufgerufen
werden. Ich denke die beste Methode ist es dafür ein OS zu schreiben,
oder!? Wenn ja, wie würdet ihr so ein OS aufbauen? Im Pollingbetrieb?
Oder strukturierte Abarbeitung der verschiedenen Funktionen?
Ich weiß das ist wieder Anwendungsbedingt, vorallem bei
Echtzeitanwendungen, aber ich wüßte zur zeit nicht einmal wie ich den
Pollingbetrieb aufbauen soll!! Hat jemand vielleicht mal Beispiele wie
man sowas entwickeln kann? Oder macht ihr das dann über Timer mit denen
Ihr eine ISR auslöst und die Funktionen bedingt an einem Zählerstand
aufruft?
Ich fänd es gut wenn, mir vielleicht jemand irgendeine Hilfestellung
geben kann!
Beispiel ist bei mir eine Schrittmotorsteuerung für eine
Isolationsfräse, bei der ich ein Echtzeitsystem haben muss, wegen der
Sicherheitsfunktionen. Schließlich muss der Motor stehen, wenn der
Notausgedrückt wird und nicht erst wenn die Funktion abgearbeitet ist.
Danke und Gruß
Benjamin
Ich hoffe für den Benutzer der Maschine, dass die Not-Aus Funktion nicht
nur in Software hinterlegt ist.
Je nach Gefährdungspotential ist dies auch gar nicht zulässig.
keine Angst die Notaus-Funktion wird über Interrupt und direkte Trennung
der Versorgungsspannung für die Antriebe realisiert!!!
ich werde keinen Gefährden... Aber ich wollte nur mal ein Beispiel
nehmen was verdeutlichen kann was Realtime bedeutet!!
Realtime bedeutet doch nur, dass das OS innerhalb einer garantierten
Zeit reagiert. Wie groß diese Zeit ist, um noch als RealTime
durchzugehen, hängt immer von den Anforderungen des Projektes ab.
Ob die Abschaltung eines Motors nun 30us oder 100us dauert ist doch
ziemlich egal, wenn man die Nachlaufzeit des Motors da ins Verhältnis
setzt.
@Andre:
das war mir schon klar wie RealTime definiert ist, aber ich suche halt
ein Beispiel wie Ihr sowas aufbauen würdet...
Wenn ich die Definition Notaus habe, dann sollten die Antriebe nicht
nachlaufen sondern sofort stehen. Dafür gibt es verschiedene
Möglichkeiten bei Antrieben... Kurzschlißen der Wicklungen,
Gleichstrombremsen oder mechanische Bremsen... usw.. Auf dem Gebiet kann
man so viel machen.
@All:
Ich würde lieber wissen wie Ihr Euren Quellcode aufbauen würdet um dies
zu realisieren. Also ich meine, würdet Ihr ähnlich einer Schrittkette
die Funktionen nacheinander aufrufen und bearbeiten lassen und die
Interrupts nur nutzen um z.B. die Endlagen, Notaus usw. zu erkennen.
Oder würdet Ihr zb. einen Timer in genau definierten Abständen einen
Interrupt auslösen lassen (zb. 100us) und mit dem Interrupt einen Zähler
hochzählen lassen. Der ausserhalb der Interruptroutine mit Konstanten
verglichen wird, die ein Auslösen einer gewissen Funktion
zusammenhängen...
Beispiel "main":
if (ucCounter < 256) { //Taster, Endlagenabfrage
... //Frage die Taster alle 100us ab
}
if (ucCounter == 10) { //Wenn kein Taster gedrückt
... //Gebe jede 1ms einen Tackt aus
}
usw.
oder wie würdet ihr das machen?
Gruß
Benjamin
Die Frage ist doch, ob du tatsächlich ein "vollwertiges" OS brauchst.
Wenn ich dich richtig verstehe, hast du eine kritische Anforderung: den
Notaus. Dieser soll innerhalb kürzester Zeit bearbeitet werden. Ich
würde den dann also in eine Interrupt-Routine packen.
Die restlichen Funktionen deiner Anwendung sollen in einer bestimmten
Reihenfolge durchlaufen werden.
Selbst die Endschalter musst du nicht unbedingt mit einem Interrupt
abarbeiten, wenn du die Funktion, die den Endschalter überwacht, nur
häufig genug aufrufst. Vielleicht würde das sogar für den Notaus
funktionieren.
Es kommt ganz darauf an, welche Laufzeit deine einzelnen Funktionen
haben, welche Vorschubgeschwindigkeit du hast und ob dir die
resultierende Abfragehäufigkeit ausreicht.
Beispiel:
1
while(1)
2
{
3
endschalter();
4
funktion1();
5
endschalter();
6
funktion2();
7
endschalter();
8
funktion3();
9
}
Wenn du mit einem Timer arbeiten möchtest, dann musst du spätestens in
der Auswertefunktion deine (ganzen) Register sichern und wieder
herstellen. Denn du weißt nicht, in welcher Funktion du gerade den
Prozessor unterbrichst und welche Register belegt sind.
Ich weiß von einem sicherheitsrelevanten Steuergerät (Bremsassistent),
da ist das "OS" ähnlich implementiert, da werden keinerlei Interrupts
verwendet, alles über Polling, sogar der Datentransfer auf dem
Systembus.
@Stefan
Danke für den Kommentar:
"Ich würde es so machen, wie es in bewährten OSen gemacht wird."
Ich würde nicht danach fragen, wenn ich wüßte wie die "bekannten" OS
aufgebaut sind!!!
@Andre
Danke für die Info!! Aber meinst du die Bearbeitung ist wirklich schnell
genug?? Dann werde ich das wohl so aufbauen. Aber ich denke um den
Regelprozess für die Motoren nicht zu stören, sollte ich das Display an
der Controllereinheit vielleicht über einen seperaten Controller
ansteuern... Sonst bremst das LCD alles aus, oder was denkst Du?
Danke noch mal!!!
Gruß
Mit dem Display wird die Sache schon etwas komplizierter, was das Timing
angeht. Die Frage dabei ist, wie oft und wann die Anzeige aufgefrischt
wird, wieviele Daten dann an das Display gesendet werden, wie schnell
die Schnittstelle zum Display ist, welche Wartezeiten durch das Display
entstehen.
- Wird das Display nur beim Einschalten initialisiert und dann nur
gelegentlich 2..3 Zahlen aufgefrischt? Dann könnte es mit dem obigen
Ansatz klappen pro Schleifendurchlauf einmal das Display
aufzufrischen.
- Gibt das Display nur Statusmeldungen aus? zB "Betriebsbereit",
"In Arbeit", "Fertig". Dann muss das Display nicht in der Schleife
aufgefrischt werden, hat also da keinen Einfluss auf die Steuerung.
Gerade wenn ein Display ins Spiel kommt, kann es tatsächlich nützlich
sein auf ein RTOS zu setzen. Dann wird die Ansteuerung für das Display
als Task mit niedriger Priorität implementiert. Alle anderen Tasks
erhalten eine höhere Priorität. Dann wird unter Umständen das Display
verzögert aufgefrischt, aber die anderen Tasks werden mit garantierten
Zeiten bearbeitet. (Das stimmt aber auch nur bedingt. Es kann dann zB zu
Problemen mit Prioritäts-Inversion[1] kommen.) Grundsätzlich behält aber
immer der Task mit der höchsten Priorität die Kontrolle über die CPU.
Du musst dabei aber immer im Kopf behalten, dass ein RTOS dir
zusätzlichen Overhead verursacht(Zeit- und Speicherverbrauch), und du
musst dich in das RTOS einarbeiten.
[1] http://netrino.com/Publications/Glossary/PriorityInversion.html
"Ich würde nicht danach fragen, wenn ich wüßte wie die "bekannten" OS
aufgebaut sind!!!"
Das weiss ich. Ich würde deshalb auch dort nachsehen. Ich verstehe aus
meinen Lernstrategien heraus nicht, warum du das nicht machst. Es ist
doch eigentlich normal, dass man sich in ein unbekanntes Thema auch
einliest. Aber wir haben hier ein Metakommunikationsproblem und ich
klinke mich daher jetzt aus.
@benjamin
ich bin zur zeit dabei mir mein eigenes kleines "os" (wenn es denn
diesen namen verdient) zu schreiben.
grundelemente in JEDEM os sind folgende :
- scheduler (egal ob unterbrechend oder kooperativ)
- signale
- zeitgeber
- fifos
so habe ich mein system aufgebaut :
mein scheduler ist kooperativ. d.h. das laufende programm wird nicht
unterbrochen, sondern gibt die kontrolle freiwillig ab. das erfodert
etwas nachdenken, vor allem bei operationen die "länger" dauern und
andere programmteile nicht blockieren dürfen.
der scheduler schaut nur nach ob signale gesetzt sind, und ruft die
hinter den signalen stehenden prozeduren auf.
die signale selbst sind jeweils nur jeweils ein bit (pro prozess bzw.
prozedur).
die timer (z.b. 1ms, 10ms, 1sek) erzeugen für sich genommen nur signale
(die dann vom scheduler aus die prozeduren aufrufen).
mit fifos verhält es sich ähnlich. man kann bei einem neuen
geschriebenen byte ins fifo ein signal auslösen, oder bei einem
gelesenen.
die fifos benötige ich für kommunikation per uart, für tasten-buffer,
für event buffer und div. andere steuer-sachen.
fifos und signale eignen sich wunderbar zum "entkoppeln" von interrupts
und ausführung der interrupt-funktionen (sofern die bedeutung des
interrupts nicht zeitkritisch ist, also eine ausführung im bereich von
<1ms bis 10ms kein thema ist).
weiterhin habe ich noch elemente wie statemachines (wunderbar geeinget
um bediener-oberflächen und applikationen zu schreiben), devices (das
sind dann die einzelnen hardware-stückchen, welche alle über eine
zentrale funktion aufberufen werden. hat den vorteil das die
schnittstelle einheitlich ist, und leicht neue devices; sprich hardware;
hinzugefügt werden kann) und einen parser/dispatcher.
das ganze system (ohne statemachines und devices) braucht auf einem
msp430 knapp 1 kB.
hoffe ich konnte dir anregungen geben
@stefan:
ich finde es nett das du mich auf ein fertiges RTOS hinweist..., aber
ich wollte mich nicht erst in die strukturen eines ARM und dem
hinterlegten RTOS einarbeiten...
Wenn dies jetzt für einen AVR vorhanden gewesen wäre, hätte ich damit
keine probleme gehabt... aber ich bin ein newbie im gegensatz zu manch
anderem hier!! ich bin froh das ich meinen displaytreiber und
verschiedene andere sachen zusammen bekomme. darum verweigere ich mich
in eine RTOS für ein anderes system einzuarbeiten!! ich möchte erst
einmal eines verstehen!!!!
@TheMason:
vielen dank für die detailierten informationen. das hat mir schon ein
wenig weitergeholfen... ich glaube ich sollte noch ein
informatik-studium hinterherschieben... dann komme ich vielleicht besser
in die struktruen hinein!!
Gruß
Benjamin
@benjamin
so schwer ist das nicht. um strukturierte abläufe zu gewährleisten
benötigst du wie gesagt eigentlich nur :
- scheduler
- signal-variablen (bei mir ist das pro task eine char-variable
(signal gesetzt oder nicht), und einen funktionszeiger (welche
funktion aufgerufen wird)
- prozeduren die ein signal setzen/löschen bzw. alle signale
initialisiert
- den scheduler selbst (eine kleine schleife die prüft ob ein signal
gesetzt ist, und die entsprechende funktion aufruft und anschließend das
signal weder zurücknimmt)
- zeitgeber
- timer-variablen (datenstruktur die die verstrichene zeit und die
"overflow" zeit hält, eine signalnummer, und einen status (läuft
periodisch, läuft nur einmal, läuft gar nicht bzw. stop)
- 1 prozedur um alle timer-variablen definiert zu resetten.
- 1 prozedur um eine timervariable um x ms zu erhöhen und ggf signal
setzen und timer-werte neu zu setzen
- 1 interrupt-prozedur die alle timer bearbeitet (sprich oben genannte
prozedur für alle vorhanden timer-variablen aufruft)
- fifos
- 2 fifo-datenstrukturen (eine steuer-struktur mit den
schreib/lesezeigern, eine daten-struktur die den fifo-buffer (oder einen
zeiger daruf) sowie die größe und das auszulösende signal enthält)
- prozeduren die die fifo-buffer initialisieren, ein byte in den fifo
schreiben (und ein signal setzen), ein byte aus dem buffer lesen
es dreht sich alles letztenendes um die signale und den scheduler. alles
was signale "auslöst" ist nur nettes (aber wichtiges) beiwerk.
mit so einem "konglomerat" an funktionen (wobei es wirklich recht wenig
funktionen sind die zu implementieren sind, ich habe insgesamt knapp
20-25 kleine funktionen, von denen nur 10-15 nach "draußen" exportiert
bzw. bekanntgegeben werden).
das mal als etwas detaillierteren umriss meines systems.
je nach anforderung kann man mit so einem system schon einiges
realisieren. vor allem ablaufsteuerungen können recht schnell realisiert
werden (durch die fifos, in denen drehgeber-events, tasten-events,
uart-events, timer-events eingetragen werden können, und diese fifos
dann quasi als ereignis-queue arbeiten)
ein kleines mini-os ist wirklich kein hexenwerk (vor allem wenn man sich
für kooperatives multitasking entscheidet wird der gesamte code sehr
einfach). ob es deinen anforderungen genügen wird weiß ich nicht.
gruß
rene
@ Benjamin
Das Target hattest du nicht angegeben. Ich wollte auf diesem Mangel
nicht herumhacken und hatte stattdessen auf FreeRTOS hingewiesen. Bei
FreeRTOS gibt es Portierungen für relativ viele Targets und ich dachte,
dass deine Plattform vielleicht dabei ist. Wenn du wie jetzt geschrieben
auf AVR aus bist... war meine Überlegung korrekt, denn es gibt auch zwei
FreeRTOS Ports für AVR und "tausend" andere Targets.