hallo
weiss leider nicht ob ich hier den richtigen ansprechpartner finde,
aber habe eine frage zur designtechnische vorgehensweise bei µC
programmierung in C/asm.
habe angefangen meine diplomarbeit an meiner fh zu schreiben. es wird
ein von der fh entwickelter µC im FPGA als softcore geladen und mit
anderen signalverarbeitungsmodulen erweitert.
im moment geht es darum eine einheitliche bibliothek und ein minimales
basisprogramm zu programmieren, auf das später dann auch aufgebaut
werden kann, d.h. das programm soll zunächst simpel und straight forward
die anforderung innerhalb meine diplomarbeit erfüllen
(SIgnalverarbeitung, Senden, empfangen, Timer etc.), eventuell noch
einen sheduler implementieren.
später sollte man in der lage sein anhand dieses basiskonzepts eine
shell aufzusetzen in verbindung mit der rs232 schnittstelle, d.h. eine
minimale console, wo man eine hand voll befehle in echtzeit ausführen
kann wie speicher auslesen, programm laden etc.
meine frage ist jetz welches verfahren sich bisher am besten
ausgezeichnet hat? ich selbst hatte zuvor schon entsprechende erfahrung
gemacht mit einem kleinen single tasking OS. dort bin ich so
vorgegangen, dass ich im hauptprogramm eine Message-Loop gemacht hab,
die drauf gewartet hat bis ein Interrupt eine Message in den Buffer
schiebt und sie dann abholt, auseinander nimmt und dann entsprechende
anweisungen ausführt.
Mein Professor will es aber so, dass nach der initialisierung der µC in
einer HALT schleife drin is, d.h. gar nix macht, und alle anweisungen
und verarbeitungen in den interrupt routinen drin stecken. ich
persönlich wurde und bin etwas stutzig bzw skeptisch. alles alleine NUR
in die interrupt routinen reinzustopfen führt früher oder später zu
einem gebastel bei dem dann gar nix mehr funktioniert und der überblick
fehlt. ich fände es besser (wenn man schon auf threads hinaus will),
einen kernelthread gleich am anfang zu starten der die steuerung
übernimmt und die interruptroutinen von den anwendungsspezifischen
steuerungen entlastet, d.h. voneinander kapselt.
ich wollte einfach mal in die runde fragen was ihr so meint und wie so
ein RTOS bzw minimal-Kernel programmiert wird. bin aufgrund der aussagen
meines professors etwas verwirrt geworden und bin deshalb motiviert mal
im internet zu recherchieren.
vielen dank!
mfg
gigolo wrote:
> Mein Professor will es aber so, dass nach der initialisierung der µC in> einer HALT schleife drin is, d.h. gar nix macht, und alle anweisungen> und verarbeitungen in den interrupt routinen drin stecken.
Ja das ist sinnfrei.
Man verschenkt damit eine Ausführungsebene.
Ein Programm mit Interrupts ohne Main arbeitet exakt genau so, wie ein
Programm ohne Interrupts, das in der Mainloop die Ereignisflags pollt.
D.h. einen Unterschied gibt es.
Die Mainloop ist in der Regel schneller, da sie keine Arbeitsregister
sichern muß.
Aber die Interrupts wissen ja nicht, daß es kein Main gibt und müssen
daher alles sichern, was sie verwenden.
Ob Du überhaupt ein OS brauchst, hängt davon ab, wie umfangreich Dein
Programm wird.
Ich würd mal so sagen, über 64kB Programmgröße könnte ein OS Sinn
machen.
Für einen simplen RS-232 Kommandointerpreter dürfte es aber Overkill
sein.
Peter
Hi gigolo,
frag' Deinen Prof. doch mal ganz direkt was er sich von einem solchen
vorgehen verspricht ?
Wie Peter schon sagte ist es ziemlich sinnfrei den µC vor sich hin
warten zu lassen, wenn doch solange keine IRQs zu bearbeiten sind z.B.
selbige weiterverarbeitet werden könnten.
Im übrigen kommt es zudem auf die Arten an IRQs an die der µC hat.
Sind die alle mit der gleichen Priorität versehen ?
Können sie gewichtet werden ?
Ist ein Watchdog aktiv ?
Je nachdem macht dann Dein Ansatz mit einem "Kernelthread" Sinn oder
nicht.
Also lieber mehrfach nerven und gezielt nachfragen, als wenn dann die
ganze Arbeit für die Füße war ;)
Meine Meinung.
Alles in Interrupts zu stopfen ist zweifelhaft. Sollte der Prof
allerdings ein RTOS gemeint haben, kann man das per kreativer
Interpretation wieder grade biegen. Indem man nämlich die Mainloop vom
RTOS betrachtet, und alle Tasks als erweiterte Interrupts ansieht.
Beim einen RTOS ist es wie bei Betriebssystemen wie Windows oder Linux
auch. Das einzig permanent laufende Programm tut überhaupt nichts, und
besteht entweder aus einer Totschleife/Zählschleife (zwecks
Last-Statistik), oder, wenn Strom gespart werden soll, aus einer
Schleife um HALT. Die Idle-Loop.
Das stört auch nicht weiter, weil da kaum Resourcen drauf gehen. Kaum
Stack, und wenn einen der Registerkontext stört, kann man diese Task bei
der Kontextumschaltung speziell handhaben.
Grund für diese Methode: Der Scheduler tut sich meist etwas schwer, wenn
er nichts findet, was lauffähig ist.
Tatsächlich ist es schon der Reaktionszeiten von Interrupts wegen
sinnvoller, in (echten) Interrupts nur das nötigste zu erledigen.
Komplexe Aktivitäten erledigt man dann in irgendwelchen Tasks die im
Interrupt angestossen werden. Vor allem in System mit bescheidener
Unterstützung von Interrupt-Nesting (z.B. AVR) kann das sehr helfen.
Unterschied zwischen klassicher Mainloop-Programmierung und RTOS: Im
RTOS haben die einzelnen Abläufe eine recht übersichtliche Darstellung,
das ganze spielt sich dort einigermassen top-down ab. Bei
Mainloop-Programmierung sammeln sich dagegen einige State-Machines an,
deren sequentieller Ablauf sich aus dem Programmtext nicht immer leicht
erschliessen lässt (Doku!). Dafür muss man in einem preemtiven RTOS
immer die jederzeit mögliche Taskumschaltung im Kopf behalten, weshalb
als Kompromiss ein kooperativ arbeitendes RTOS durchaus nützlich sein
kann.
Ein RTOS kann übrigens klein sein: AvrX liegt mit 1,5KB durchaus im
Rahmen mittlerer AVRs.