Forum: Mikrocontroller und Digitale Elektronik Modellierung und Implementierung reaktiver Systeme, Statecharts, UML, C, Diagramme, OO/nicht-OO


von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Hallo!!

Ich befürchte das wird mal wieder so ein Posting, welches
keiner liest, weil es viel zu umfangreich und lang ist :-).
Aber es gab ja trotzdem auch oft schon sehr interessantes
Feedback!

Seit einigen Jahren bereits bastel ich nun im Hobbybereich mit
Microcontrollern auch in Zusammenhang mit C als Programmiersprache.

Mangels theoretischer Basis war mein Vorgehen dabei meist
recht blauäugig. Sicher macht man sich anfänglich ein paar
Gedanken, wie man ein Stück Software strukturieren könnte.
Aber im wesentlichen hacke ich dann doch eher drauf los.
Dabei vergisst man die Hälfte, pfriemelt es dann zwar noch irgendwie
mit rein, aber schön wird das meistens nicht. Die Struktur ist
dahin, die Übersicht auch und selbst nur mittelmässig komplexe
Projekte will man nach einem Jahr eigentlich nicht mehr
anfassen, weil es keinen Spass macht in dem Codewust noch
zu arbeiten.

Sicher, man kommentiert ja brav, aber das Big-Picture fehlt
trotzdem oft und bis man sich das aus den Kommentaren wieder
erarbeitet hat....

Stichwort: Softwaredesign

Das eine oder andere UML Diagramm hat man ja schon gesehen.
Nun kommt UML meinem Verständnis nach vor allem aus der OO
Welt. Mangels Verwendung objektorientierter Sprachen habe ich
dem bislang nicht viel Beachtung geschenkt.

Trotzdem muss es doch auch in funktionalen Sprachen (nennt man
das dann so? Was genau ist eigentlich eine funktionale Sprache?)
formale Methoden geben, um Modelle für das Verhalten von
Software zu entwickeln und zu visualisieren.

Aus der Assemblerzeit kennt man die Flowcharts. Das ist ja nun
etwas, was sehr nahe am Code ist. Also auch sehr nahe an der
Implementierung. Ich denke, dass man das da auch bewusst will.
Bei der Objektorientierung könnte ich mir das in gewisser Weise
ähnlich vorstellen, wenn man eine objektorientierte Sprache
verwendet, die Ausdrucksmittel anbietet, um z.B. Elemente der
UML sehr leicht umzusetzen.

Bei der reinen C Programmierung sind mir entsprechende Verfahren
zur Modellierung irgendwie nicht wirklich geläufig.

Ok, da gibts da noch die Nassi-Shneiderman Diagramme. In der Literatur
findet man gelegentlich den Hinweis dieser Diagrammtyp hätte im Rahmen
der Verwendung von strukurierten Programmiersprachen (C) die
Flowcharts aus der Assemblerzeit abgelöst.
Mir scheint aber eher so, als hätte dieser Diagrammtyp eher
theoretische Bedeutung. Meine Versuche damit etwas sinnvolles
anzufangen waren bisher auch mehr erfolglos.

Vielleicht liegt das aber auch am besonderen Charakter den
(zumindest meine) Microcontrollerprojekte meistens haben.

Hier z.B. eine "black-box", die eigentlich nichts anderes macht
als auf 4 Eingänge zu reagieren und ein paar Ausgänge zu steuern.
Ok, ist noch bischen PWM dabei, Interrupts usw. usw...
Aber vor allem handelt es sich nicht einfach um eine kombinatorische
Logik, die Eingänge mit Ausgängen verbindet, sondern die "box" hat
auch ein "Gedächtnis" und das Verhalten hängt von der Vorgeschichte
ab. Ausserdem muss die Box auf verschiedene Dinge unabhängig und
quasi gleichzeitig reagieren.

Man hat ja schon mal was von Zustandsautomaten gehört und ich hatte
schon vor einer Weile die Ahnung, dass sich das eignen könnte, um
das Verhalten zu modellieren. Dabei habe ich dann auch ein paar
Tools entdeckt, mit denen man das am Computer entwerfen kann.
Moore und Mealy lassen grüßen. Die Tools schienen mir dabei recht
... naja, "hardwarenah". Wie ich inzwischen vermute, lag das daran,
dass die Zielgruppe auch eher Richtung FPGA und co. ausgerichtet
ist als die gewöhnliche Softwareentwicklung.

Bei meinem eher ziellosen Studium der Literatur und diverser
Webseiten musste ich feststellen, dass man das was ich in meiner
"black-box" haben will, wohl als reaktives (echtzeit) System
bezeichnet und dass das eigentlich eine eigene Disziplin ist.

In diesem Dunstkreis sind mir dann die Artikel von David Harel
mit seiner Statechart Notation begegnet. Mir wurde klar, dass sich
so ein Großteil meiner Probleme modellieren und darstellen lassen
können müsste. Also wieder auf die Suche nach einem Tool mit dem
sich Statecharts bearbeiten lassen. Es gibt neben Statemate noch
einige andere kommerzielle Tools, die aber entweder viel zu teuer
oder in ihrer kostenlosen Version unbrauchbar sind.

Schließlich musste ich feststellen, dass in der UML ebenfalls ein
Statemachine-Diagramm enthalten ist. Ich habe also schließlich
mit allerlei UML tools experimentiert.
Woran liegt es eigentlich, dass dergleichen zu 99% in JAVA
geschrieben ist? Ok, es gibt noch umbrello, aber der Schwerpunkt
scheint dort nicht gerade auf den Statecharts zu liegen und
schien mir für meine Zwecke unbrauchbar.

Ich habe dann recht viel Zeit damit verbracht UML tools auszuprobieren:
papyrus, argouml, visualparadigm, poseidon usw usw....
Momentan bin ich bei jude hängen geblieben. Vermutlich deshalb,
weil es allerlei constraints, die offensichtlich im Rahmen der UML
spezifiziert sind, eher schwach durchsetzt. Aufgrund der Tatsache,
dass ich die Diagramme nicht wirklich nutzen will, um objektorientierte
Programme zu schreiben, schien mir das zweckmäßig. Außerdem gibt
es eine brauchbare kostenlose Version.

Nach anfänglicher Begeisterung muss ich aber feststellen, dass sich
nicht jedes Problem als Statemachine darstellen lässt. Zumindest nicht
gut und auch nicht schön.

Wo ich nun schon mal dabei war, hab ich mir einige andere Diagrammtypen
aus der UML angesehen, z.B. das Activity Diagramm. Das scheint mir
schon auch geeignet, um Teilbereiche des Verhaltens zu modellieren und
zu visualisieren. Bei genauerer Betrachung ist das aber ja eigentlich
nichts anderes als ein Flowchart. Und das wiederum scheint bei
der stukturierten Programmierung eher verpönt. Ich sehe aber
den Grund ehrlich gesagt nicht wirklich.

Schon vor einer Weile bin ich dazu übergegangen, mir die Kommunikation
unterschiedlicher Programmteile als Nachrichten vorzustellen, die
ausgetauscht werden. Wie ich nun sehe, bietet auch hier die UML
mit den Sequenz- und Kommunikationsdiagrammen Möglichkeiten, um
das Verhalten darzustellen.

Es bleibt aber das Problem, dass ich es bei C nicht mit einer
objektorientierten Programmiersprache zu tun habe. In der UML ist
es ja eher so, dass Objekte Nachrichten miteinander austauschen.

Bislang hatte ich nur nach Diagrammen gesucht, mit deren Hilfe ich
meine Software eher dokumentieren als modellieren kann.
Aber mir dämmert, dass vielleicht der umgekehrte Weg der
richtige sein könnte. Schliesslich bieten ja die meisten UML Tools
auch die Möglichkeit automatischer Codegenerierung. Natürlich wieder
nur für OO-Sprachen.

Mal vorausgesetzt, dass ich das zu Fuß mache, spricht denn etwas
gegen die Verwendung von UML Diagrammen? Gibt es etwas besseres
für nicht objektorientierte Sprachen?

Wenn ich schöne UML Bildchen male, ohne mir über die Implementierung
Gedanken zu machen, mag das in C++ ganz gut funktionieren, in C
aber nur bedingt. Sicher kann man auch in C objektähnliches
Verhalten nachbilden, aber sehr oft fallen mir dann bei der
tatsächlichen Implementierung wesentlich effizientere Möglichkeiten
ein, die dann aber nicht immer noch viel mit dem ursprünglichen
Modell zu tun haben. Und von denen ich auch gar nicht wüsste, wie ich
sie mit den mir bekannten Methoden modellieren sollte.
Wenn der Resourcenverbrauch keine Rolle spielt, sollte man darauf
vielleicht keine Rücksicht nehmen, aber in einem Microcontroller
ist eben Ram und Flash nicht unbegrenzt.

Gibt es hier andere, bessere formale Methoden, oder ist das einfach
eine Frage der Programmier (und modellier-) Erfahrung?

Also lange Rede, kurzer Sinn:

Wie macht man sowas und bin ich völlig auf dem Holzweg?



so, jetzt langt's erst mal :-).

viele Grüße,
Klaus

von P. S. (Gast)


Lesenswert?

Ich habe es leider schon viel zu oft erlebt, dass Entwickler versuchen 
die Nachteile von schlampiger Programmierarbeit mit allerleit Tools und 
Konzepten auszugeleichen. Das endet dann oft in Projekten die mit 
allerlei TamTam und den interessantesten Werkzeugen und Strategien 
aufgezogen und irgendwann erst recht schlampig runtergehackt werden, um 
auch mal fertig zu werden.

Ordentlichen und wartbaren Code zu schreiben erfordert in erster Linie 
Disziplin und Fleiss. Da gehoert eben Dokumentation dazu, die erklaert 
und nicht nur irgendwelchen formalen Kriterien entspricht. Und vor allem 
gehoert dazu, dass die Dokumentation mitgewartet wird und dem aktuellen 
Stand entspricht. Beim schreiben von Dokumentation geht es nicht darum, 
in moeglichst kurzen Worten alle relevanten Parameter erwaehnt zu haben, 
sondern darum dem Naechsten zu erklaeren, worum es geht. Das kann 
Fliesstext oft sogar besser als abstrakte Diagramme.

Schau dich doch mal hier um, in wie vielen Codebeispielen Variablen x, 
y, z oder i heissen - und wehe, jemand meckert. Und wie stolz viele 
sind, wenn sie die coolste/kuerzeste/kryptischste Loesung fuer ein 
Problem gefunden haben. Dass die komplexesten Vorrangregeln von C stets 
parat sind und konsequent klammerfrei gearbeitet wird. Als Tutor fuer 
Erstsemester hatte ich die tollsten Debatten ueber Codeformatierung - 
dabei haben wir niemandem einen Stil vorgeschrieben, wir haben lediglich 
verlankt, dass ein Stil konsequent umgesetzt wird. Die Standardantwort 
ist "Wieso, es compiliert doch".

von Mark B. (markbrandis)


Lesenswert?

Ich habe einen C-Code gesehen, der ganz doll nach Entwurfsmuster 
entwickelt war. Ergebnis unter anderem: Eine Callback-Funktion, die 
nichts anderes macht als eine Callback-Funktion in einem anderen Modul 
aufzurufen...

Merke: Tolle Diagramme nützen nix, wenn die technische Ausführung nicht 
mit gesundem Menschenverstand durchgeführt wird :-)

Im Grunde genommen gilt doch für Embedded Software: Achte auf die 
Laufzeit und auf den Speicherverbrauch, baue die Software modular auf 
(Stichwort wiederverwendbare Funktionen), und dann passt das auch in der 
Regel.

Manche Diagramme aus der UML kann man tatsächlich auch für prozedurale 
Programmierung verwenden, zum Beispiel das Sequenzdiagramm, um einen 
zeitlichen Ablauf sinnvoll zu dokumentieren. Aber ALLES in UML-Diagramme 
packen zu wollen? Hör auf mich und lass den Quatsch. ;-)

von sebastian (Gast)


Lesenswert?

Hallo Klaus,

ich muss dir voll recht geben.
Für Mikrocontrolleranwendungen ist es sehr schwer den Formalismus der 
UML korrekt einzusetzen.

Zu aller erst empfehle ich dir folgendes Buch:
Agile Softwareentwicklung für Embedded Real-Time Systems mit der UML

Hervorragendes Buch, dass die wichtigsten UML Diagramme in Bezug zu 
Embedded Systems erläutert.

Für mich persönlich sind die folgenden UML Diagramme die wichtigsten für 
die Spezifikation/Design von Embedded Systems:

- Zustandsdiagramm (State Chart)
- Sequenzdiagramm
- Komponentendiagramm
- Timing Diagramme (auch UML gehört aber nicht zum Standard Paket)
- Aktivitätsdiagramme

In diesem Buch wird auch Bezug genommen zu Pattern.
Das sind Entwurfsmuster von Softwaresystemen für spezielle 
Problemstellungen.

Ich habe immer viel mit Zustandsautomaten gearbeitet. Aber der Ablauf 
darin ist mir mit der Zeit zu "linear" bzw. "unflexibel" geworden. Dann 
habe ich angefangen Prozesse in Unterprozesse aufzuteilen und diese über 
definierte Schnittstellen kommunzieren zu lassen, natürlich asychron, da 
sonst eine Aufsplittung wenig Sinn macht. Hier kommen die 
Sequenzdiagramme zum Einsatz.

Um nun einen Überblick über alle Module zu behalten und um zu wissen, 
welches Modul von welchem Modul abhängig ist, bietet sich das 
Kommunikationsdiagramm an.

für den eigentlichen Funktionsablauf bietet sich das Aktivitätsdiagramm 
an, hier muss man sich davon lösen in Funktionen zu denken. Die 
"Funktion" des Moduls soll hier im Vordergrund stehen. So können hier 
auch so Dinge wie ein Warten auf einen Interrupt, oder ein 
Synchronisationspunkt eingezeichnet werden.

Ich wünsche dir noch viel Erfolg und Spaß mit der UML :-)

MFG

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:
> Ich habe es leider schon viel zu oft erlebt, dass Entwickler versuchen
> die Nachteile von schlampiger Programmierarbeit mit allerleit Tools und
> Konzepten auszugeleichen. Das endet dann oft in Projekten die mit
> allerlei TamTam und den interessantesten Werkzeugen und Strategien
> aufgezogen und irgendwann erst recht schlampig runtergehackt werden, um
> auch mal fertig zu werden.

Ganz auf der gleichen Schiene hab ich auch schon erlebt, das das Tool 
regelrecht zum Hauptzweck wurde. Völlig egal, ob hinten ein lauffähiges 
Projekt rauskommt, hauptsache wir haben ein neues Tool :-)


Zurück zum Kern.
Für mich kann ich sagen, dass ich sehr von der objektorientierten 
Programmierung und ihren Denkweisen profitiert habe. Ich würde sagen, 
ich war vor meiner OO Zeit schon ganz gut unterwegs, aber mit OO hab ich 
nochmal einen enormen Sprung nach vorne gemacht. Nicht falsch verstehen: 
Ich spreche hier nicht von tatsächlicher Codeumsetzung, sondern von der 
Gedankenwelt, wie man mit OO ein Projekt aufzieht, wie man abstrakte 
Modelle baut, in die das Problem eingebettet werden kann, etc.

Durch das modellieren von Klassen und ihren Beziehungen, durch die 
Denkweise des "ein Funktionsaufruf ist ein Befehl an ein Objekt, etwas 
zu tun", gewöhnt man sich einen Arbeitsweise und auch eine 
Softwarearchitektur an, die einem auch in C sehr zu gute kommt. Es 
schärft sich einfach der Blick für Modulbauweise, welche Funktion gehört 
logisch wo dazu, welche Aufgabe wird von wem wie delegiert, etc.

von sebastian (Gast)


Lesenswert?

@Karl heinz Buchegger

dito! Aus der OO Welt kann man sehr viele IDEEN in die "Mikrocontroller 
Welt" übertragen.

Ein Professor von mir halt mal gesagt:
"UML bietet die Möglichkeit von verschiedenen Blinkwinkeln auf ein und 
dasselbe Objekt zu schauen."

Es ist wie bei einem Architekt der ein Haus baut, da gibt es Diagramme 
die zeigen aus der Vogelperspektive die Wandstärke, in welche Richtung 
die Türen aufgehen, die Anzahl der Zimmer..

und Diagramme die zeigen wo Strom  Wasser  Abwasser Leitungen führen.

Es gibt die Aussansicht, Innenansicht etc.

So ist das auch mit UML Diagrammen, mit einem
Aktivitätsdiagramm kann man das gleiche Modul wie mit einem 
Sequenzdiagramm beschreiben.. es bietet aber einen anderen Fokus. Z.b. 
betrachtet man sich beim einen den funktionalen Ablauf und beim anderen 
die zeitliche Abfolge wann ein Modul an ein anderes Modul eine Nachricht 
schickt.

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

So schnell so viele Antworten, das ist ja toll! :-)

Also ich denke, dass das alles meine (vor)Ahnung ganz gut bestätigt.

Ich sehe ein Designtool als Werkzeug, das natürlich nicht zum 
Selbstzweck werden soll. Ich hab auch kein Problem damit, mal zu Papier 
und Bleistift zu greifen. Recht oft finde ich das sowieso kreativer :-). 
Aber es hat natürlich auch was, wenn man nicht immer den Radiergummi 
braucht.

Designpattern... das ist auch so ein Stichwort. Mir ist eigentlich gar 
nicht ganz klar, was man darunter versteht. Gelegentlich hat man im 
Forum schon Beispielimplementierungen von Statemachines gesehen, die 
naja, sagen wir mal allgemein verwendbar sein sollten. Könnte man das 
dann als Entwurfsmuster auffassen? Es scheint ja eine ganze Reihe 
solcher "well-known design patterns" zu geben. Sollte man sich das mal 
angucken? Sebastian hat da ja schon Literatur vorgeschlagen. Mir ist 
schon klar, dass man solche Patterns nicht auf biegen und brechen 
umsetzen kann und muss (Marks Beispiel mit den Callback Funktionen).

@Karl Heinz: Vermutlich funktioniert der objektorientierte Denkansatz 
deshalb so gut, weil Modell und Realität recht gut korrespondieren.

Die Frage ist, wie gut man das dann bei der Implementierung umsetzen 
kann. Hier hängt es wohl wirklich viel von der Erfahrung des 
Programmierers ab und man kann sich nicht blind auf irgendwelche Design 
Patterns stützen.
Aber ein Blick darauf kann ja vielleicht mal nicht schaden....

@Peter: Tja, naja, das hat natürlich auch was mit sportlichem Ehrgeiz zu 
tun. Wenn's jemand Spaß macht....
Tatsächlich könnte es ja berechtigt sein, eine kompakte Lösung 
vorzuziehen, wenn der Compiler daraus auch ein kleineres Binary macht.
Aber deswegen muss man den Code sicher nicht unleserlich formulieren.

Mich würde schon auch mal interessieren, wie verständlich mein Code 
eigentlich für Aussenstehende ist. Aber wenn man immer nur im stillen 
Kämmerlein etwas vor sich hin bastelt und nicht irgendwie in einem Team 
arbeitet, ist das mit dem Feedback oft etwas schwierig.


Na, mal sehen.
Vielen Dank erstmal für eure Anmerkungen!

Viele Grüße,
Klaus

von sebastian (Gast)


Lesenswert?

@Klaus

Das Buch konzentriert sich mehr auf den Umgang mit UML für Embedded 
Systems. Entwurfsmuster werden hier nur am Rande erwähnt.

>Designpattern... das ist auch so ein Stichwort. Mir ist eigentlich gar
>nicht ganz klar, was man darunter versteht. Gelegentlich hat man im
>Forum schon Beispielimplementierungen von Statemachines gesehen, die
>naja, sagen wir mal allgemein verwendbar sein sollten. Könnte man das
>dann als Entwurfsmuster auffassen? Es scheint ja eine ganze Reihe
>solcher "well-known design patterns" zu geben.

Naja, eine State-Machine als solches ist genau genommen kein 
Entwurfsmuster. Mir fällt hier als Beispiel das bekannte "Observer" 
Pattern oder auch Beobachter Pattern ein.

Dies beschreibt ein Entwurfsmuster wie man "Änderungen an einem Objekt 
bei anderen Objekt bekannt macht"

Schau mal nach "Model View Controller" das ist DAS klassische 
Architektur Muster für komplexe Softwaresysteme.

Die meisten Entwurfsmuster die ich kenne haben aber etwas mit 
Objektorientierung und Polymorphie zu tun. Die Grundidee dieser Pattern 
lässt sich aber auch auf Sprachen wie C portieren.

Mit generischen Funktionspointern etc. aber gerade auf ressourcen 
begrenzten Systemen ist sowas mit Vorsicht zu genießen.

Gut Nacht ;)

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

sebastian schrieb:
> @Klaus
>
> Das Buch konzentriert sich mehr auf den Umgang mit UML für Embedded
> Systems. Entwurfsmuster werden hier nur am Rande erwähnt.

Das Buch ist inzwischen nicht mehr im Handel, man kann es aber auf der 
Homepage der Sophist Group (www.sophist.de) downloaden, wenn man sich 
registriert. Zum Lesen bin ich noch nicht gekommen, bin aber schon ganz 
gespannt :-).

> Schau mal nach "Model View Controller" das ist DAS klassische
> Architektur Muster für komplexe Softwaresysteme.

Hm, hab' grade mal den Wiki Artikel gelesen.
Sicher kann man das nicht jedem Projekt "überstülpen", oder?
Ich habe schon öfters mal was mit Postgress gebastelt und dabei wohl das 
Model-View-Controller Entwurfsmuster verwendet, ohne es zu kennen :-).
Aber wenn ich grade über meine bisherigen embedded Projekte nachdenke, 
kann ich mir nicht recht vorstellen viel damit anfangen zu können.
Aber vielleicht liegt das ja an mir und nicht an dem Muster :-).

Wenn ich da noch etwas weiter klicke zu den Behavioral Patterns sieht 
das schon anders aus! Sicher ist es auch nicht zweckmässig solche Muster 
mit Gewalt umzusetzen, aber ich könnte mir schon vorstellen, dass es 
recht hilfreich sein könnte, diese Ideen im Hinterkopf zu behalten. Man 
ist sich vielleicht oft viel bewusster was man eigentlich programmiert.


viele Grüße!
Klaus

von Karl H. (kbuchegg)


Lesenswert?

Klaus W. schrieb:

>> Schau mal nach "Model View Controller" das ist DAS klassische
>> Architektur Muster für komplexe Softwaresysteme.
>
> Sicher kann man das nicht jedem Projekt "überstülpen", oder?

'Jedes' im mathematischen Sinne für 'Für Alle' ist eine schwerwiegende 
Behauptung. Aber abgesehen davon: Bisher ging das eigentlich immer. Die 
MFC ist im wesentlichen darauf aufgebaut, auch wenn der Teil Controller 
da stiefmütterlich behandelt wird, da die Bandbreite in diesem Teil 
einfach zu gross ist und Controller oftmals eng mit dem View 
zusammenarbeiten müssen.

Das 'Kochrezept' des MVC ist doch:
trenne Daten, Datenhaltung und Datenmanipulation streng von der Anzeige 
der Daten und das wiederrum von den Werkzeugen, die du deinem Benutzer 
zur Manipulation der Daten in die Hand gibst. Und du kriegst ein 
flexibles System, das gut in alle Richtungen erweiterbar ist. Sowohl was 
Erweiterung des Datenmodells als auch verschiedene Anzeigevariationen 
angeht. Wenn man will, kann man Modell-View alleine auch als eine 
Variation des Observer-Patterns auffassen.

Für mich 'leider', hat sich aber der Trend in der Windows Programmierung 
gewandelt, hin zu Forms-basierter Programmierung ohne die Vorgabe eines 
Model-View Frameworks. Dementsprechend verwoben und wartungsunfreundlich 
sind dann auch zeitgenössische Programme von Leuten, die sich die 
strenge Modell-View Architektur nicht zu eigen gemacht haben. Ich sitz 
auch schon seit einiger Zeit an so einem geerbtem Qt-Programm. Da werden 
Dialog-Elemente an den unmöglichsten Stellen gefüllt oder abgefragt. 
Dialoglogik ist über 15 Klassen verstreut. Selbst ein simples 'Cancel' 
in einem Dialog stellt sich als schwierig heraus, weil der Dialog auf 
den Original-Daten arbeitet, anstatt auf einer Arbeitskopie der Daten 
für den Dialog. Arbeitskopie geht wieder nicht, weil Datenhaltung  und 
Anzeige so ineinander verwoben sind, dass eine Kopie mangels fehlender 
Widget Pointer sofort abschmiert, etc. Eine 2-te, andere, Ansicht (also 
einen View) auf die Daten einzubauen ist momentan ein Ding der 
Unmöglichkeit, weil die Ansichten nicht synchron updaten würden, etc.

> Ich habe schon öfters mal was mit Postgress gebastelt und dabei wohl das
> Model-View-Controller Entwurfsmuster verwendet, ohne es zu kennen :-).

Kann gut sein.

> Aber wenn ich grade über meine bisherigen embedded Projekte nachdenke,
> kann ich mir nicht recht vorstellen viel damit anfangen zu können.

Na denk zb mal an die üblichen Ratschläge, wie ISR zu behandeln sind. In 
einer ISR werden maximal ein paar Datenfelder manipuliert. Die 
eigentliche Anzeige oder Ausgabe kommt in die Hauptschleife.
Mit ein wenig guten Willen kann man die Hauptschleife (oder zumindest 
einen Teil davon) als den View ansehen, während die ISR Teil des Model 
ist.

von sebastian (Gast)


Lesenswert?

>Das 'Kochrezept' des MVC ist doch:
>trenne Daten, Datenhaltung und Datenmanipulation streng von der Anzeige
>der Daten und das wiederrum von den Werkzeugen, die du deinem Benutzer
>zur Manipulation der Daten in die Hand gibst. Und du kriegst ein
>flexibles System, das gut in alle Richtungen erweiterbar ist. Sowohl was
>Erweiterung des Datenmodells als auch verschiedene Anzeigevariationen
>angeht. Wenn man will, kann man Modell-View alleine auch als eine
>Variation des Observer-Patterns auffassen.

Ja, Model und View werden tatsächlich oft mit dem Observer Pattern 
realisiert. Richtig, aber im Grund ist der Gedanke dahinter, die 
konsequente Trennung zwischen Darstellung und Daten und Steuerung.

Und der Gewinn dadurch ist eine flexible, wartbare und erweiterbasre 
Software. Also das Gegenteil von dem, was im Programmspeicher der 
meisten Mikrocontroller Anwednungen rum liegt. ;-)

Ein gutes Beispiel wäre das Menü in einem LCD Display. Viele bauen so 
viel Komplexität in die Menü-STEUERUNG, dass in fast das ganze System um 
die Ohren fliegt, wenn sie die Eingabemethode ändern odern einen weitern 
Menü Punkt hinzufügen wollen. Ja, auch ich schließe mich da nicht aus. 
:-) Aber der Mensch lernt ja bekanntermassen nur durch Schmerz. :)

>Für mich 'leider', hat sich aber der Trend in der Windows Programmierung
>gewandelt, hin zu Forms-basierter Programmierung ohne die Vorgabe eines
>Model-View Frameworks. Dementsprechend verwoben und wartungsunfreundlich
>sind dann auch zeitgenössische Programme von Leuten, die sich die
>strenge Modell-View Architektur nicht zu eigen gemacht haben.

Amen, Bruder! ;-) Ja, die meisten Klick-Drop Entwicklungsumgebungen wie 
Delphi etc. sind mittlerweile so einfach zu bedienen, dass zu weilen 
grausamer Code hinter den Benutzeroberflächen ruht. Oben hui- hinten 
pfui!

>Ich sitz
>auch schon seit einiger Zeit an so einem geerbtem Qt-Programm. Da werden
>Dialog-Elemente an den unmöglichsten Stellen gefüllt oder abgefragt.
>Dialoglogik ist über 15 Klassen verstreut. Selbst ein simples 'Cancel'
>in einem Dialog stellt sich als schwierig heraus, weil der Dialog auf
>den Original-Daten arbeitet, anstatt auf einer Arbeitskopie der Daten
>für den Dialog. Arbeitskopie geht wieder nicht, weil Datenhaltung  und
>Anzeige so ineinander verwoben sind, dass eine Kopie mangels fehlender
>Widget Pointer sofort abschmiert, etc. Eine 2-te, andere, Ansicht (also
>einen View) auf die Daten einzubauen ist momentan ein Ding der
>Unmöglichkeit, weil die Ansichten nicht synchron updaten würden, etc.

Ohja, mit Qt habe ich auch schon Erfahrungen gemacht. zu Beginn war ich 
sehr angetan von dem Signal-Slot konzept, welches man auch als Pattern 
bezeichnen kann. Also für alle die es nicht kennen: Über ein Objekt 
werden Signal (Sender) und Slot (Empfänger) miteinander verküpft. So 
wird z.b. eine bestimmte funktion augerufen, wenn ein bestimmtes Event 
(z.B.) Button.clicked() auftritt.

So kann man auch sehr schön mehrere Funktionen durch ein Event auslösen. 
So wird die Kopplung gering gehalten und man hält die Architektur 
flexibel.

MFG

von sebastian (Gast)


Lesenswert?

>Das Buch ist inzwischen nicht mehr im Handel, man kann es aber auf der
>Homepage der Sophist Group (www.sophist.de) downloaden, wenn man sich
>registriert. Zum Lesen bin ich noch nicht gekommen, bin aber schon ganz
>gespannt :-).

In welchem Format kann man sich das Buch downloaden?
Kannst du mir evtl. das PDF davon schicken?

von Sonnentau (Gast)


Lesenswert?

> Was genau ist eigentlich eine funktionale Sprache?

Och, das ist ganz einfach:

In einer (strengen) funktionalen Sprache gibt es keine Variablen und 
keine iterativen Schleifen und Funktionen haben exakt einen Parameter 
und geben exakt ein Wert zurück. Ausserdem sind Funktionen 
First-Class-Objekte und als "Nebeneffekt" gibt es Funktionen höhere 
Ordnung, d.h. Funktionen die als Ergebnis wiederrum eine Funktion haben.

Und ja, damit kann man Programme schreiben, und das auch noch sehr 
elegant. Aber das alles hier zu erklären führt zu weit.

Zurück zu Deinem Problem:


> Die Struktur ist dahin, die Übersicht auch und selbst nur
> mittelmässig komplexe Projekte will man nach einem Jahr eigentlich
> nicht mehr anfassen, weil es keinen Spass macht in dem Codewust
> noch zu arbeiten.

Ich vermute, Dein Problem ist ein "Disziplin-Problem" oder eine falsche 
Sichtweise auf das Programieren.

Anstatt hier alles wiederzukauen, was schlaue Menschen schon 
niedergeschrieben haben, möchte ich Dir folgendes Buch empfehlen:

  http://www.amazon.de/Pragmatische-Programmierer-Andrew-Hunt/dp/3446223096

von Arne (Gast)


Lesenswert?

UML und strukturierte Sprachen widerspricht sich wohl in einigen 
Aspekten. Man kann somit nicht alles aus der UML benutzen. Ich versuche 
hier auch die Quadratur des Kreises in der Firma und werde wohl nur 
Sequenzdiagramme und Statecharts nehmen. Geholfen hat mir dieses Buch 
"Practical UML Statecharts in C/C++: Event-Driven Programming for 
Embedded Systems"
ISBN 0750687061
Hauptaugenmerk wird in der 2.Auflage auf C gelegt, die erste soll mehr 
C++ lastig sein.

Ansonsten lege ich bei meinen Projekten (privat und beruflich) Wert auf:
- einen durchgängig identischen Programmierstil
- bei uC Anwendungen auf ein BSP, das von der Hauptanwendung 
(ab)gekapselt ist

Je weiter man "nach oben" kommt - also die Hauptanwendung - desto 
verwurschtelter wird es meist... ist meine Ansicht.

Das BSP in der Firma habe ich noch ohne UML entwickelt, für Bootloader 
und Hauptapplikation möchte ich aber unbedingt die Kenntnisse o.g. 
Buches anwenden. Schulungen im Bereich UML & C & Microcontroller sind 
nach meinen Recherchen sehr dünn bis überhaupt nciht vorhanden. Da wird 
einem viel blabla um die Ohren gehauen von den Marketingspezis der 
Schulungsanbieter.

Das o.g. kostet so ~35,-EUR - also nicht die Welt. Ist halt auf englisch 
und man muss sich durch das Papier halt an einigen Wochenenden 
durchbeissen. Dafür ist es das erste, das ich gefunden habe, das auf 
meine Belange eingeht.

von sebastian (Gast)


Lesenswert?

Hab gerade durch den letzten Post noch dieses Buch entdeckt:
Modellierung von eingebetteten Systemen mit UML und SysML (Taschenbuch)

Klingt auch recht viel versprechend.

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

sebastian schrieb:
> Hab gerade durch den letzten Post noch dieses Buch entdeckt:
> Modellierung von eingebetteten Systemen mit UML und SysML (Taschenbuch)
>
> Klingt auch recht viel versprechend.

Ja, das liegt hier bei mir auch schon auf dem Schreibtisch. Jetzt 
bräuchte ich nur noch Zeit zum Lesen. Das andere Buch scheint mir auf 
den ersten Blick fast interessanter. Mal gucken!

Das pdf kann ich Dir schon schicken, aber eine kurze Email an 
buch@sophist.de genügt auch! Die sind recht umgänglich.

@ Karl Heinz:

> Na denk zb mal an die üblichen Ratschläge, wie ISR zu behandeln sind. In
> einer ISR werden maximal ein paar Datenfelder manipuliert. Die
> eigentliche Anzeige oder Ausgabe kommt in die Hauptschleife.
> Mit ein wenig guten Willen kann man die Hauptschleife (oder zumindest
> einen Teil davon) als den View ansehen, während die ISR Teil des Model
> ist.

Hm, also das muss ich mir jetzt erst noch etwas durch den Kopf gehen 
lassen. Ich hätte die ISR wohl eher dem Controller zugeordnet.
Aber ich werde jetzt erst mal etwas Literatur studieren, bevor ich mit 
meinem Viertelwissen versuche etwas zu verstehen :-).

@Sonnentau:
>In einer (strengen) funktionalen Sprache gibt es keine Variablen und
>keine iterativen Schleifen und Funktionen haben exakt einen Parameter
>und geben exakt ein Wert zurück. Ausserdem sind Funktionen

Hm, das heißt also, dass C keine funktionale Sprache ist.



Viele Grüße,
Klaus

von Mark B. (markbrandis)


Lesenswert?

Klaus W. schrieb:
> Hm, das heißt also, dass C keine funktionale Sprache ist.

Rüchtüg.

Zu funktionalen Sprachen fällt mir im Moment nur LISP, Haskell und Gofer 
ein (wobei Gofer ein Haskell-Derivat ist).

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Mark Brandis schrieb:
> Klaus W. schrieb:
>> Hm, das heißt also, dass C keine funktionale Sprache ist.
>
> Rüchtüg.
>
> Zu funktionalen Sprachen fällt mir im Moment nur LISP, Haskell und Gofer
> ein (wobei Gofer ein Haskell-Derivat ist).

Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter 
Programmierung alles als funktionale Programmiersprache bezeichnet wird, 
was nicht objektorientiert ist.

Naja...

von P. S. (Gast)


Lesenswert?

Klaus W. schrieb:

> Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter
> Programmierung alles als funktionale Programmiersprache bezeichnet wird,
> was nicht objektorientiert ist.

Was dann gemeint ist, ist "prozedural". Da die Prozeduren in C 
Funktionen heissen, liegt das Missverstaendnis nahe.

von Baumwurzel (Gast)


Lesenswert?

> Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter
> Programmierung alles als funktionale Programmiersprache bezeichnet wird,
> was nicht objektorientiert ist.

Liegt IMHO daran, dass (viele) OO-Jungs nicht über ihren Tellerrand 
blicken (können) und der irrigen Meinung sind, sie hätten die Spitze der 
Programmier-Paradigmen erklommen.

Das lustige ist aber, dass die Probleme die OO versucht zu lösen, in der 
funktionalen Welt überhaupt nicht existieren. Und das ist (nicht nur) 
für die OO-Jungs hart.

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Puuh, also das ist alles ganz schön kompliziert.

"Agile Softwareentwicklung für Embedded Real-Time Systems mit der UML"
habe ich jetzt zum Großteil gelesen. Natürlich müsste man das richtig
durcharbeiten, aber ich weiss zumindest schon mal was drinsteht.

Wenn ich die Zusammenhänge richtig verstehe, beschäftigt sich das
Buch in erster Linie mit der Verwendung der UML und setzt dabei
schon entsprechendes Vorwissen über die UML selbst voraus.
Dabei geht es also mehr um den Entwicklungsprozess als um die UML
selbst.

Ich muss allerdings gestehen, dass ich durchaus noch meine
Schwierigkeiten habe diese Bereiche gegeneinander abzugrenzen.

Zum Teil finden sich recht interessante Themen, allerdings kann ich
nur ansatzweise sehen, wie ich die Erkenntnisse nutzbringend für
mich einsetzen könnte.

Aber es bleiben für mich auch noch viele Fragen offen.
Ist. z.B. die Gegenüberstellung von essenziellen Klassen und
technologiegetriebenen Klassen gleichzusetzen mit fachlichen
und technologischen Klassen?

Designpatterns werden wie bereits erwähnt auch gestreift.
Es findet sich übrigens ein interessanter Link:

 http://www.hillside.net/patterns

Die Abbildung der diversen Techniken in konkreten C-Code ist mir
immer noch zum großen Teil recht rätselhaft. Auch wenn
Herr Buchegger schon ein paar Hinweise gegeben hat.
Vielleicht ist das aber auch alles einfach ein Nummer zu groß
für meine Miniprojekte?



Also ich würde das ganze ja gerne nochmal von einer anderen
Seite betrachten. Vielleicht kann dazu einer der Experten auch noch
ein paar Anmerkungen machen:

Eine meiner Anwendungen, die ich im Anfangsposting schon erwähnt hatte, 
die fertiggestellt ist und sich bewährt hat, macht folgendes:

Im Auto eines Bekannten (Kfz-Bastelfreak) soll ein Sack voll LEDs
durch verschiedene Ereignisse ( Zentralverriegelung, Zündungsstellung,
Helligkeit, Türkontakte usw..) in geeigneter Weise gesteuert werden.
Es gibt noch ein paar Testmodi, da z.B. die Polarität und Timing
mancher Signale im Voraus nicht bekannt war und zugeöhrige
Konfigurationsmöglichkeiten über ein paar Taster, Config im EEPROM,
Power Management usw.
Das ganze läuft aus historischen Gründen auf einem attiny26, da die
Hardware schon einige Jahre existiert und auch nicht modifiziert werden
sollte.

Das klingt erstmal ziemlich primitiv. Der Code wirkt aber auf den ersten
Blick recht umfangreich und ich frage mich, ob das an irgendwelchen
grundsätzlichen Designfehlern oder auch der konkreten Implementierung
liegt.

Die Auswertung der Eingangssignale wird mit Statemachines
durchgeführt, die auch die Entprellung beinhalten. Die Statemachines
rekonstruieren auch Zustände, die sich nur durch die zeitliche
Historie ergeben. Dieser Teil generiert Nachrichten, die an die
eigentliche "Geschäftslogik" gesendet werden, die wiederum aus
verschiedenen Statemachines besteht. Diese generieren ebenfalls
Nachrichten, welche dann vom Ausgabeteil verarbeitet werden.

Soweit war das auch mein ursprünglicher Gedanke vor der eigentlichen
Implementierung.

Nun ist es aber so, dass die ganzen Statemachines quasi parallel
und voneinander unabhängig, also sozusagen nebenläufig sein müssen.

Der Ausgabeteil läuft mehr oder weniger vollständig im Interrupt, weil
die meisten Kanäle per (software) PWM dimmbar sein sollen und das ganze
relativ zeitkritisch ist, damit es nicht flimmert.

Sonstige zeitabhhängige Ereignisse und (software) timer z.B. innerhalb
der Statemachines laufen in main() und erhalten dazu alle 10ms
ein Signal von einem weiteren Timer Interrupt, das entsprechend
ausgewertet wird. Dadurch werden auch viele volatile Variablen
vermieden auf die der Zugriff recht uneffizient wäre.

Die (logische) Nebenläufigkeit dieser "Tasks" (Prozesse? Objekte?)
(ja, ich bin da in der Terminologie leider recht unsicher) habe ich
so realisiert, dass es einfach eine große main-while(1) loop gibt,
in der diese Tasks zyklisch ausgeführt werden. Dabei habe ich darauf
geachtet, dass es keine Warteschleifen o.ä. in diesen Tasks gibt.

Manche der Tasks werden aber nur in festen Zeitrastern aufgerufen, wie
z.B. die Tastaturentprellung, Abfrage der A/D Wandler usw. Die
Statemachines sind also quasi z.B. mit 10ms oder 1s getaktet. So spare
ich mir zusätzliche Timer innerhalb dieser Statemachines.

Die Statemachines der "Geschäftslogik" werden einfach mit der
verbleibenden Rechenzeit jedesmal ausgeführt, sowie die äussere
while(1) loop ausgeführt wird, obwohl dies eigentlich gar nicht
nötig wäre.

Grundsätzlich scheint mir das ganze irgendwie recht umständlich.
Ich frage mich immer ob es wirklich so kompliziert sein muss ein
paar LEDs in Abhängigkeit von ein paar Eingangssignalen zu steuern.

Die ganzen "Tasks", also im wesentlichen Statemachines sind alle
als Dauerwurst in der while(1) Schleife enthalten und arbeiten mit
lokalen Variablen aus main(). Es wäre viel schöner, jede
Statemachine als Funktion zu programmieren, ihre Zustände in
statischen Variablen zu kapseln und die Nachrichten als Über-
und Rückgabewerte zu übergeben.
Ich habe diese Strategie trotzdem aufgegeben, weil ich mit dem
Flash im tiny26 recht schnell an die Grenze gekommen bin und
Funktionsaufrufe und static Variablen teurer sind als
den Code einfach der Reihe nach hinzuschreiben.
Das ist ein wenig unbefriedigend. Ich verstehe aber auch immer wieder
nicht wirklich was der Compiler daraus macht. Ich hatte gehofft,
dass static inline funktionen zu ähnlich kurzem Code führen
müssten, wenn sie nur einmal verwendet werden und nur
der Übersicht halber vorhanden sind.
Es scheint z.T. auch daran zu liegen, dass die static Variablen
grundsätzlich irgendwo im Speicher und nicht auf dem Stack liegen?
Vielleicht wird das dann mit der Registerverwendung über
Funktionsgrenzen hinweg nicht mehr so gut optimiert?
Oder sag' ich's nur dem Compiler nicht richtig?

Das ganze bleibt trotzdem vergleichsweise übersichtlich, weil
die "Tasks" einfach sequenziell der reihe nach abgearbeitet werden.
Vielleicht ist das in dem Fall dann auch einfach ok so?

Ich frage mich aber auch, wie es zu bewerkstelligen wäre,
wenn ich dem Controller nun noch eine andere Aufgabe geben möchte.
Von mir aus Primzahlen berechnen, die er immer dann ausführen soll,
wenn sonst nichts zu tun ist. Also statt die übrige Rechenzeit
in den Statemachines für die aktuelle Geschäftslogik zu verbraten.

Ich müsste dann den neuen "Task" auch so gestalten, dass der
Algorithmus in Häppchen zerteilt wird, die klein genug sind,
dass die geforderten Antwortzeiten der anderen Tasks auf
ihre Nachrichten gewährleistet bleiben.

Also HALLO? Es kann ja wohl nicht sein, dass ich ein Betriebssystem
mit Scheduler brauche um ein paar LEDs zu steuern!?!?!?

Alternativ hatte ich schon die Idee meine ganze bisherige Applikation
selbst in einen Interrupt zu verlegen, der dann die an sich
nebensächliche Primzahlenberechnung (als Beispiel) in main()
unterbricht. Dieser Interrupt müsste dann aber selbst wieder durch den
sehr hoch priorisierten Interrupt für die PWM Ausgabe zu unterbrechen
sein.
Vermutlich schlagen jetzt wieder einige Leute die Hände über dem Kopf
zusammen falls überhaupt so weit gelesen.....

Dieser beispielhafte Primzahltask hat irgendwie einen anderen
Charakter als alle anderen. Die anderen Tasks reagieren immer nur auf
Nachrichten. Von der Bearbeitung weiss ich, dass sie wesentlich
kürzer dauert als die kürzeste geforderte Antwortzeit von anderen Tasks.
Der Primzahltask dauert aber quasi ewig.

Es scheint ja schon irgendwie wichtig zu sein, sich über all diese
Dinge und Eigenschaften beim Design eines Systems im klaren zu sein.
Glücklicherweise hat das in meinem Fall recht gut funktioniert, aber
es hätte ja auch anders sein können.

Daher meine Suche nach irgendwelchen Modellierungsmöglichkeiten, die
solche Schwierigkeiten im Vorfeld zum Ausdruck bringen können. Vor
allem, wenn es mal etwas komplexer wird, als ein paar LEDs zu steuern 
und man nicht einfach ein persönliches Modell im Kopf haben kann.

Nunja, es bleibt schwierig :-).


gute Nacht und viele Grüße,
Klaus

von sebastian (Gast)


Lesenswert?

Hey Klaus,

ok, so langsam verstehe ich deine Problematik. Wenn es um solche 
"Architektur Techniken" geht, dann ist wohl das Buch über agile 
Softwareentwicklung mit der UML eher ein schlechter Tipp gewesen, da es 
in diesem Buch, wie du schon geschrieben hast, eher um Prozesse und die 
Anwendung der UML in verschiedenen Entwicklungsphasen geht.

Zu deinem konkreten Problem:

Ja, das was du hier brauchst ist ein Task-Management.
Das klingt im ersten Moment vielleicht aufgebläht und übertrieben, aber 
im Grund musst dieses Task-Management nicht viel machen:

Beispiel:
1
#define TASK_PERIODE_1 10  // alle 10  ms
2
#define TASK_PERIODE_2 50  // alle 50  ms
3
#define TASK_PERIODE_3 100 // alle 100 ms

In einem 1 ms Interrupt wird dann das "Task-Management" vorgenommen:

Fuer jeden Task gibt es hier einen Counter, wird ein Periodenwert 
erreicht, dann wird ein Task-Flask gesetzt. Hier sollte natürlich darauf 
geachtet werden, dass keine Tasks aufeinander fallen. Sowas lässt sich 
mit einem Zeit-Diagramm und Deadlines für jeden Task gut darstellen.

Nun werden in der main() nur die Flags fuer die Tasks ausgewertet:
1
int main (void)
2
{
3
 if (TASK_MANAGEMENGT_Task_1.enabled == true)
4
 {
5
   Task_1();
6
   TASK_MANAGEMENGT_Task_1.enabled = false;
7
 }
8
9
 // ...
10
11
 if (TASK_MANAGEMENT_No_Task_enabled == true)
12
 {
13
   Primzahlenberechnung(); //Aus deinem Beispiel, dieser "Task" sollte sehr kurz sein um die anderen Tasks nicht zu beeinflussen...
14
 }
15
 return 0;
16
}

Das ganze ist jetzt nicht sehr ausgearbeitet, aber es soll nur das 
Prinzip veranschaulichen. du kannst auch so dinge wie deadlines, 
Task-Aufsplittung einbauen...

Zu deinen anderen Fragen:
Ja, jede Statemachine sollte Kern eines Moduls und des Tasks sein. 
Statemachines bieten sich hier gut an, da sie nicht komplette in einem 
Task Durchlauf durchlaufen werden müssen, sondern so von "Zustand zu 
Zustand" gedachte werden kann.

Ja, static variablen werden wie globale Variablen behandelt und für sie 
wird Speicher im RAM belegt (kannst du dir im map file anschauen) lokale 
Variablen (also ohne static) werden auf den Stack gepushed.

Ich weiß nicht, aber vielleicht gibt es ja schon einen Beitrag in der 
Artikelsammlung oder Codesammlung zu einem einfachen 8 Bit Controller 
Task Management, welches man auch auf einem ATtiny einsetzen könnte.

Schönen Sonntag :)
Sebastian

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Hallo Sebastian!

Vielen Dank für Deine Antwort!

sebastian schrieb:

> Softwareentwicklung mit der UML eher ein schlechter Tipp gewesen, da es
> in diesem Buch, wie du schon geschrieben hast, eher um Prozesse und die
> Anwendung der UML in verschiedenen Entwicklungsphasen geht.

Schlechter Tipp nicht direkt. Ich finde es schon sehr interessant. Nur 
jetzt aktuell bringt es mich tatsächlich nicht sehr viel weiter.

> In einem 1 ms Interrupt wird dann das "Task-Management" vorgenommen:
> Fuer jeden Task gibt es hier einen Counter, wird ein Periodenwert
> erreicht, dann wird ein Task-Flask gesetzt. Hier sollte natürlich darauf
> geachtet werden, dass keine Tasks aufeinander fallen. Sowas lässt sich
> mit einem Zeit-Diagramm und Deadlines für jeden Task gut darstellen.

So ungefähr habe ich das tatsächlich auch gemacht. Nur dass bei mir die 
maximale Auflösung 10ms beträgt. Das reicht in meinem Fall. Außerdem 
gibt es nur diesen einen 10ms Interrupt und eine Art Scheduling Task, 
der in Deinem Beispiel die "TASK_MANAGEMENGT_Task_x.enabled" Flags 
generieren würde.

Die Zähler decrementiere ich stattdessen. Ich könnte mir denken, dass 
der assembler code um auf 0 zu prüfen kürzer ist als auf einen konkreten 
Wert? Hab' das aber noch nicht nachgesehen.

Was meinst Du damit, dass keine Tasks aufeinander fallen sollten? Es 
würde doch nichts passieren, wenn das Taskmanagement mehrere Tasks 
gleichzeitig aktiviert. Sie werden dann halt einfach in der Reihenfolge 
der Implementierung abgearbeitet, oder?

>    Primzahlenberechnung(); //Aus deinem Beispiel, dieser "Task" sollte
> sehr kurz sein um die anderen Tasks nicht zu beeinflussen...

Tja und das ist eben unschön. Es wäre viel praktischer, wenn dieser Task 
automatisch unterbrochen werden würde. Ich könnte natürlich prüfen, ob 
ein anderer Task aktiviert wurde (per Interrupt) und dann die 
Primzahlenberechnung unterbrechen. Aber auch das müsste man in den 
Primzahlalgorithmus einbauen.

> Das ganze ist jetzt nicht sehr ausgearbeitet, aber es soll nur das
> Prinzip veranschaulichen. du kannst auch so dinge wie deadlines,
> Task-Aufsplittung einbauen...

Bei mir gibts eher so Taskzusammenfassungen :-). Aber auch nur um das 
Binary kürzer zu bekommen.
Was meinst du mit Deadlines?

> Ich weiß nicht, aber vielleicht gibt es ja schon einen Beitrag in der
> Artikelsammlung oder Codesammlung zu einem einfachen 8 Bit Controller
> Task Management, welches man auch auf einem ATtiny einsetzen könnte.

Gibt's! Allerdings konnte ich nichts finden, was effizient genug gewesen 
wäre, um es so 1:1 formal anwenden zu können.

Aber wenn nun niemand eine ganz andere Idee vorschlägt wie man sowas 
macht, bin ich ja schon ganz zufrieden :-).


Schönen Feiertag!
Klaus

von sebastian (Gast)


Lesenswert?

>Vielen Dank für Deine Antwort!
Kein Problem :-)

>So ungefähr habe ich das tatsächlich auch gemacht. Nur dass bei mir die
>maximale Auflösung 10ms beträgt. Das reicht in meinem Fall. Außerdem
>gibt es nur diesen einen 10ms Interrupt und eine Art Scheduling Task,
>der in Deinem Beispiel die "TASK_MANAGEMENGT_Task_x.enabled" Flags
>generieren würde.

>Die Zähler decrementiere ich stattdessen. Ich könnte mir denken, dass
>der assembler code um auf 0 zu prüfen kürzer ist als auf einen konkreten
>Wert? Hab' das aber noch nicht nachgesehen.
Da hast du natürlich Recht! "JUMP IF ZERO" ist natürlich gänger als 
"JUMP IF XY".

>Was meinst Du damit, dass keine Tasks aufeinander fallen sollten? Es
>würde doch nichts passieren, wenn das Taskmanagement mehrere Tasks
>gleichzeitig aktiviert. Sie werden dann halt einfach in der Reihenfolge
>der Implementierung abgearbeitet, oder?

Einfaches Beispiel:
Du hast einen Task 1, der alle 10 ms ausgeführt wird.
Und einen Task 2, der alle 100 ms ausgeführt werden soll.

Die Ausführungszeit von Task 1 ist 50 us und die von Task 2 100 us.

So nun lassen wir beide loslaufen, bei T=0 (sagen wir du hast einen 10 
ms "Basis Takt")

Bei T=10, wird Task 2 zum ersten mal ausgeführt und Task 1 zum 10, mal.

Nun wird aber in deinem Task Management Task 2 z.b. vor Task 1 
ausgeführt (rein theoretisch) dann wir dann Task 1 bei T=10 erst 100 us 
später ausgeführt als die anderen 9 mal zuvor. So ergibt sich ein Jitter 
bei Task 1 den du dir zum Beispiel auf dem Oszi ansehen kannst. Das muss 
nicht kritisch, kann aber unter Umständen zu unschönen Nebeneffekten 
führen.


>>    Primzahlenberechnung(); //Aus deinem Beispiel, dieser "Task" sollte
>> sehr kurz sein um die anderen Tasks nicht zu beeinflussen...

>Tja und das ist eben unschön. Es wäre viel praktischer, wenn dieser Task
>automatisch unterbrochen werden würde. Ich könnte natürlich prüfen, ob
>ein anderer Task aktiviert wurde (per Interrupt) und dann die
>Primzahlenberechnung unterbrechen. Aber auch das müsste man in den
>Primzahlalgorithmus einbauen.

Mhm, nur eine Idee:

Der Task Primzahelnberechnung wird in einem anderen Timer Task 
ausgeführt. Nun normalerweise ist es ja so, dass ein Interrupt keinen 
anderen unterbrechen kann. Wenn du zu Beginn des "Primzahlen Timers" nun 
das Interrupt System wieder aktivierst, dann kann dein "Task Management" 
jederzeit deine Primzahlenberechnung unterbrechen.

Hier musst du aber sehr sorgfältig vorgehen, damit hier keine 
Inkosistenzen oder Deadlocks entsehen. Evtl. brauchst du Semaphoren, 
wenn beide Interrupt Routinen auf gemeinsamen Speicher zugreifen.

>> Das ganze ist jetzt nicht sehr ausgearbeitet, aber es soll nur das
>> Prinzip veranschaulichen. du kannst auch so dinge wie deadlines,
>> Task-Aufsplittung einbauen...

>Bei mir gibts eher so Taskzusammenfassungen :-). Aber auch nur um das
>Binary kürzer zu bekommen.
>Was meinst du mit Deadlines?

Deadline ist die Zeit bis ein bestimmter Task spätestens ausgeführt 
werden soll! Z.b. hast du Task 1 der kommt alle 10 ms, dauert 50 us und 
soll spätestens nach der Aufforderung (alle 10ms) nach 100 us ausgeführt 
werden. Damit erlaubst du Task 1 einen Jitter von 50 us.

>Schönen Feiertag!
>Klaus

Wünsch ich dir auch,
Sebastian

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

sebastian schrieb:

> später ausgeführt als die anderen 9 mal zuvor. So ergibt sich ein Jitter
> bei Task 1 den du dir zum Beispiel auf dem Oszi ansehen kannst. Das muss
> nicht kritisch, kann aber unter Umständen zu unschönen Nebeneffekten
> führen.
Ja, das ist klar, bei mir aber völlig irrelevant. Aber ist schon klar, 
dass es Fälle geben kann, wo das eine Rolle spielt.

> Mhm, nur eine Idee:
>
> Der Task Primzahelnberechnung wird in einem anderen Timer Task
> ausgeführt. Nun normalerweise ist es ja so, dass ein Interrupt keinen
> anderen unterbrechen kann. Wenn du zu Beginn des "Primzahlen Timers" nun
> das Interrupt System wieder aktivierst, dann kann dein "Task Management"
> jederzeit deine Primzahlenberechnung unterbrechen.
Hm, also ich hatte eher gedacht praktisch die ganze (zeitkritische) 
Applikation in einem Interrupt laufen zu lassen (und das wäre dann halt 
99% des Codes) und die Primzahlberechnung in main(). Aber diese ISR 
müsste dann auch wieder Interrupts zulassen, weil die PWM Erzeugung ja 
NOCH zeitkritischer ist. Also ziemlich haarig und von solchen Dingen 
wird ja generell immer abgeraten. - Außer man weiss genau was man tut. 
Weiß ich das?
Naja, ist ja eh nur hypothetisch. Ich werde mir nächstes mal Gedanken 
machen wenn so ein Problem real ansteht :-).

> Hier musst du aber sehr sorgfältig vorgehen, damit hier keine
> Inkosistenzen oder Deadlocks entsehen. Evtl. brauchst du Semaphoren,
> wenn beide Interrupt Routinen auf gemeinsamen Speicher zugreifen.
Hmmm... weil der Compiler Code erzeugt, der nichts davon weiss dass ein 
Interrupt eine ISR unterbrechen kann?

> Deadline ist die Zeit bis ein bestimmter Task spätestens ausgeführt
> werden soll! Z.b. hast du Task 1 der kommt alle 10 ms, dauert 50 us und
> soll spätestens nach der Aufforderung (alle 10ms) nach 100 us ausgeführt
> werden. Damit erlaubst du Task 1 einen Jitter von 50 us.
Ah, verstehe....

Nochmal grundsätzlich zur Nebenläufigkeit:
Wenn man so UML Klassendiagramme sieht, erweckt das bei mir häufig den 
Eindruck dass Objekte in der OO Welt grundsätzlich nebenläufig wären. 
Die generieren da munter irgendwelche Nachrichten.... Ich habe vor 
langer Zeit nur mal so interessehalber ein paar Klassen in C++ gebastelt 
und instanziiert oder wie man da sagt und habe also praktisch wirklich 
keine Ahnung. Aber so ein Objekt macht doch von sich aus erstmal genauso 
nichts wie eine Funktion, wenn es nicht gefragt wird, oder sehe ich das 
falsch?

viele Grüße!
Klaus

von Baumschüler (Gast)


Lesenswert?

> Aber so ein Objekt macht doch von sich aus erstmal genauso
> nichts wie eine Funktion, wenn es nicht gefragt wird, oder
> sehe ich das falsch?

Das siehst Du vollkommen richtig.

Wenn ich mir so Deine Probleme durchlese, bekomme ich den Eindruck, Du 
gehst irgendwie zu kompliziert an die Aufgabe ran.

Auch wenn es "Mode" ist, wenn man 17 Abstraktiosschichten übereinander 
legt, lösen sich die Probleme nicht magisch von selbst. Irgendwo muss im 
Programm gearbeitet werden, irgendwo werden die Hände schmutzig. Sprich: 
Ein Programm wird nicht elegant, wenn man die Verantwortung von einer 
Abstraktion zur nächsten schiebt.

Konkretes Beispiel:

> Manche der Tasks werden aber nur in festen Zeitrastern aufgerufen,
> wie z.B. die Tastaturentprellung, Abfrage der A/D Wandler usw.

Dafür brauchst Du keine Tasks, sondern Du verwendest Hardware.

Z.b. der AD-Wandler kann autonom mit einer festen Samplingrate laufen. 
Immer wenn der einen neuen Wert hat, setzt er ein Bit. Dieses Bit kannst 
Du zu beliebigen Zeitpunkten abfragen, z.B. so:
1
void check_ad()
2
{
3
  if (!bit_in_ad_wandler_gesetzt())
4
    return;
5
6
  ...
7
}

Oder die Entprellerei. Du entscheidest Dich einfach für eine 
Sampling-Rate für die Tasten, und machst das in einem Timer-Interrupt. 
Wenn Du nur auf Taster-Downs reagieren musst, hast Du zwei Variablen. 
Die eine zeigt immer den entprellten Zustand der Taster an. In der 
anderen werden die entsprechenden Bits nur dann gesetzt (vom Interrupt), 
wenn sich der Zustand einer Taste von 0 auf 1 gewechselt hat.

Dann kannst Du jederzeit abfragen, ob ein Taster gedrückt wurde 
(Key-Down-Event) und das Bit dann löschen, wenn Du den Event bearbeitet 
hast. Also etwa so:
1
void check_foobar_key()
2
{
3
  if (!( key_event & 0x01 ))
4
    return;
5
6
  key_event &= ~ 0x01;
7
8
  ...
9
}

Das kannst Du dann auch mit verschiedene Zuständen kombinieren, so dass 
in bestimmten Situationen die Tasten unterschiedliche Funktionen haben 
etc.

Wie gesagt: Nicht die Aufgaben zwischen dutzenden Abstraktionsschichten 
hin und her schieben, sondern Aufgaben da lösen, wo sie auftreten.

Der Witz an der Sache: Wozu Software und Abstraktionen schreiben, wenn 
die Hardware Dir Deine Probleme löst.

Später, wenn Du viel Erfahrungen gesammelt hast, wirst Du ein besseres 
Gespür bekommen, wann und was wie abstrahiert werden kann, soll oder 
muss.

Aber am Anfang gilt:

  Frühe Optimierung ist tödlich!

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Hallo!

Baumschüler schrieb:

> Wenn ich mir so Deine Probleme durchlese, bekomme ich den Eindruck, Du
> gehst irgendwie zu kompliziert an die Aufgabe ran.

Naja, wie erwähnt, sind die Probleme eigentlich schon gelöst und das 
Ding funktioniert. Aber es kann ja nicht schaden mal etwas über den 
Tellerrand zu blicken :-).

> Auch wenn es "Mode" ist, wenn man 17 Abstraktiosschichten übereinander
> legt, lösen sich die Probleme nicht magisch von selbst. Irgendwo muss im
> Programm gearbeitet werden, irgendwo werden die Hände schmutzig. Sprich:
> Ein Programm wird nicht elegant, wenn man die Verantwortung von einer
> Abstraktion zur nächsten schiebt.

Da hast Du recht. Aber auf der anderen Seite sollte es doch auch nicht 
schaden, sich über die Struktur der Applikation im klaren zu sein.
Alleine das Abstraktionsmittel der Statemachine fand ich dabei sehr 
hilfreich. Die Tastaturentprellung war etwas komplizierter, weil ich 
auch so Dinge auswerte wie "zwei kurze Tastenanschläge hintereinander", 
"zwei Tasten gemeinsam lange gedrückt" usw.
Die Frage war für mich einfach ob es neben den Statecharts noch andere 
hilfreiche Abstraktionen gibt, die man sich zu nutze machen könnte.

Klar, muss natürlich alles mit Mass und Ziel passieren und ein Diagramm 
macht noch kein Programm....
Genau genommen ist das Diagramm ja auch nur die visuelle Darstellung des 
Modells welches ich sowieso irgendwie im Kopf haben muss, um sowas zu 
programmieren.
Ich stelle mir schon vor dass es einen weiter bringen könnte, sich diese 
Zusammenhänge bewusst zu machen.


> Konkretes Beispiel:

> Dafür brauchst Du keine Tasks, sondern Du verwendest Hardware.
>
> Z.b. der AD-Wandler kann autonom mit einer festen Samplingrate laufen.
> Immer wenn der einen neuen Wert hat, setzt er ein Bit. Dieses Bit kannst
> Du zu beliebigen Zeitpunkten abfragen, z.B. so:

Ja, das tut er natürlich auch. Auf die Wandlung zu warten kann ich mir 
nicht leisten :-). Mich interessiert der Wert sowieso nur alle 1s. Bis 
dahin ist die Wandlung längst fertig und ich frage das Bit nur 
sicherheitshalber ab.

> Oder die Entprellerei. Du entscheidest Dich einfach für eine
> Sampling-Rate für die Tasten, und machst das in einem Timer-Interrupt.

Naja, das ist nicht ganz so einfach. Wie sicher schon irgendwo erwähnt 
habe ich neben der Tastenentprellung noch allerlei andere Statemachines 
die quasi parallel laufen. Da bräuchte ich ja 20 Timer und Interrupts. 
Also ich muss das schon noch etwas "verteilen" :-).

>
1
> void check_foobar_key()
2
> {
3
>   if (!( key_event & 0x01 ))
4
>     return;
5
> 
6
>   key_event &= ~ 0x01;
7
> 
8
>   ...
9
> }
10
>

Ja, so ungefähr mache ich das auch. Nur dass ich im allgemeinen keine 
einzelnen Bits verwende. Ich stelle mir vor dass die Bitmaskiererei in 
Assembler auch wieder ein paar Instruktionen länger dauert. An RAM bin 
ich nicht knapp und "key_event = 0" geht vermutlich schneller?
(Hab konkret nicht nachgeguckt)

> Das kannst Du dann auch mit verschiedene Zuständen kombinieren, so dass
> in bestimmten Situationen die Tasten unterschiedliche Funktionen haben
> etc.
Ja, es gibt eine Statemachine die den Hauptbetriebsmodus (Test, Config, 
Demo, Operation usw..) festlegt. Je nach dem bewirken die Tasten 
natürlich auch unterschiedliche Dinge.

> Wie gesagt: Nicht die Aufgaben zwischen dutzenden Abstraktionsschichten
> hin und her schieben, sondern Aufgaben da lösen, wo sie auftreten.

Naja, ich würde sagen auf der untersten Abstraktionsebene.

> Später, wenn Du viel Erfahrungen gesammelt hast, wirst Du ein besseres
> Gespür bekommen, wann und was wie abstrahiert werden kann, soll oder
> muss.

Ja, daran arbeite ich gerade :-).

> Aber am Anfang gilt:
>
>   Frühe Optimierung ist tödlich!

Hm, Optimierung in welcher hinsicht?


Viele Grüße,
Klaus

von sebastian (Gast)


Lesenswert?

HEy Klaus,

mein letzter Post war Schwachsinn:
"Primzahlen in einem eigenen Timer Interrupt und Task Management wieder 
in einem eigenen"

--> Hier würde zwar das task MANAGEMENT zum Zuge kommen, aber die 
eigentliche Task Ausführung würde permanent vom Primzahelninterrupt 
unterbrochen. Also Schwachsinn, bitte vergessen :)

Aber die Tasks in der Timer ISR auszuführen ist auch nicht gut.

Du musst darauf achten wie du deine "Primzahlenroutine" gestaltest, d.h. 
wenn die Routine so gestaltest ist, dass sie nur eine Iteration 
durchläuft und ggf. noch einen Status zurück liefert ...

bool dummy_task (void);
// --> Rueckgabewert 0: Task beendet
// -->               1: Wait: Wenn moeglich moechte Task nocheinmal 
ausgefuehrt werden..
1
void main (void)
2
{
3
   // ...
4
5
   while (   (TASK_MG.No_Task_Enabled == true)
6
           &&(Primzahlen_Task() == 1)
7
         )
8
   {
9
     _NOP();
10
   }
11
}

Mfg

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

sebastian schrieb:

> --> Hier würde zwar das task MANAGEMENT zum Zuge kommen, aber die
> eigentliche Task Ausführung würde permanent vom Primzahelninterrupt
> unterbrochen.

Ja, eben :-). Müsste ja eher umgekehrt sein.

> Aber die Tasks in der Timer ISR auszuführen ist auch nicht gut.

Warum eigentlich?
Ok, es ist zwar relativ viel code, aber es wird ja in jedem Interrupt 
immer nur ein winziger Bruchteil davon ausgeführt. Und die Zeit zwischen 
den Interrupts ist eine Ewigkeit im Vergleich zur Ausführungsdauer der 
ISR.
Einzig unschön wäre, dass der Interrupt für die software PWM diese ISR 
wieder unterbrechen müsste.

> Du musst darauf achten wie du deine "Primzahlenroutine" gestaltest, d.h.
> wenn die Routine so gestaltest ist, dass sie nur eine Iteration
> durchläuft und ggf. noch einen Status zurück liefert ...

Ja, das ist klar.


Viele Grüße,
Klaus

PS: Ich lese grade "Modellierung von eingebetteten Systemen mit UML und 
SysML" von Andreas Korff. Damit kann ich grade wesentlich mehr anfangen 
als mit dem anderen von Dir vorgeschlagenen Buch. - Was natürlich nicht 
heisst dass das schlecht wäre. - Naja, hatten wir ja schon :-).

von sebastian (Gast)


Lesenswert?

>Ok, es ist zwar relativ viel code, aber es wird ja in jedem Interrupt
>immer nur ein winziger Bruchteil davon ausgeführt. Und die Zeit zwischen
>den Interrupts ist eine Ewigkeit im Vergleich zur Ausführungsdauer der
>ISR.
>Einzig unschön wäre, dass der Interrupt für die software PWM diese ISR
>wieder unterbrechen müsste.

Läuft die Soft PWM in einem Task in deinem Task Management?
Wieviele Timer Interrupts verwendest du denn für dein Task Management?

Mach es doch so:

Die 'High Priority Tasks" realisierst du direkt in der Timer ISR, also 
die Tasks die relativ kurze Ausführungszeiten haben, aber immer 
deterministisch ausgeführt werden sollen.

Die 'Low Priority Tasks" führst du in main() aus, bei diesen spielt dann 
ein Jitter von ein paar us/ ms keine Rolle.

Du musst natürlich wieder auf Überlappungen, Ausführungszeiten 
aufpassen.

Der Soft PWM Task wäre ein High Priority Task.
Die Primzahlenberechnung ein Low Priority Task, da diese  von den High 
P. Tasks unterbrochen werden darf.

Mfg

PS: Das Buch klingt interessant, das schaue ich mir auch mal an :)
Kannst ja gerne mal deine Erfahrungen mit dem Buch posten.

von Thomas S. (klegom)


Lesenswert?

Klaus W. schrieb:
> Wie macht man sowas und bin ich völlig auf dem Holzweg?

Eigentlich ist der Thread ja schon ein bisschen alt, aber weil er genau 
mein Thema trifft, wollte ich noch einen Beitrag anhängen.
Ich habe mich das gleiche nämlich auch gefragt und Astade ist meine 
Antwort auf die Frage.

Ich mache schon seit über 20 Jahren Software für Embedded Systeme 
(professionell, das heißt ich verdiene mein Geld damit). Für mich ist 
das Zustandsdiagramm der einzige Weg, wirklich gute Software zu machen. 
Das heißt Software, die wirklich auf alle Eventualitäten reagiert.

Leider braucht es dazu die Diagramme (Bilder) sonst verliert man den 
Überblick. Die letzten Jahre mache ich das mit Astade, wo ich auch zu 
den Autoren gehöre.

Astade hat inzwischen einen Zustand erreicht, wo ich es guten Gewissens 
für Mikrocontroller empfehlen kann.

Es generiert effektiven C Code aus grafischen Zustandsdiagrammen und hat 
ein eingebautes Trace Framework, das alle Aktivitäten des Programms 
grafisch in Sequenzdiagrammen darstellen kann.

von texmex (Gast)


Lesenswert?

Hallo Thomas!

Ich hab' mir das Astade mal angeguckt. Die Idee mit den "dynamischen" 
Diagrammen finde ich ganz witzig. Aber ob sich das in der Praxis 
bewährt?

Also seit meinem ursprünglichen Post habe ich (hoffe ich) schon allerlei 
neue Erfahrungen sammeln können.

Sicher sind Statemachines oft ein gutes Mittel, um Abläufe zu 
modellieren. Aber eben auch nicht immer.

Insbesondere muss man unterscheiden, ob die States natürlicherweise in 
einer Funktion enthalten sind (z.B. in einem Übertragungsprotokoll) oder 
ob sie künstlich eingeführt wurden, um das kooperative Multitasking zu 
ermöglichen. States aus dem ersten Fall lassen sich durchaus auch für 
den zweiten Fall verwenden.

Ich habe aber die Erfahrung gemacht, dass man sich mit der Modellierung 
recht schwer tut, wenn man sich diesen Unterschied nicht bewusst macht.

So wie ich sehe, versteht sich Astade nicht unbedingt als vollwertiges 
UML Werkzeug, sondern legt den Schwerpunkt auf automatische 
Codeerzeugung bzw. Simulation der Zustandsautomaten?

Sofern das zur Modellbildung eines Algorithmus dienen soll, kann ich mir 
das schon als große Hilfe vorstellen. Weil das Modell dann mit der 
Softwareimplementierung konsistent bleibt.

Wenn es hingegen um künstliche States wegen dem Multitasking geht, 
scheint mir sowas in der Art wie Adam Dunkels Protothreads die bessere 
Wahl zu sein. Aber da muss ich auch erst noch etwas mehr Praxiserfahrung 
sammeln.

Grundsätzlich tue ich mich nach wie vor noch recht schwer ein 
Softwaresystem komplett als UML Modell darzustellen. Sicher ist es in 
Teilbereichen sehr hilfreich. Andererseits stehe ich immer wieder vor 
dem Problem den einen oder anderen Trick anwenden zu müssen, um 
Anforderungen hinsichtlich Echtzeit, Latenz, Jitter usw. gerecht werden 
zu können, wodurch die Programmstruktur nicht immer schöner und 
übersichtlicher wird. Das dann wiederum in einer Modellsprache 
abzubilden, die womöglich wieder automatisch Code erzeugen soll, 
erscheint mir vorsichtig formuliert unmöglich.

Vielleicht habe ich nur immer noch die falsche Herangehensweise.

Aber möglicherweise kommt ja noch die große Erleuchtung :-).


viele Grüße!
Klaus

von Sebastian B. (mircobolle)


Lesenswert?

texmex schrieb:
> Ich hab' mir das Astade mal angeguckt. Die Idee mit den "dynamischen"
> Diagrammen finde ich ganz witzig. Aber ob sich das in der Praxis
> bewährt?
Ich arbeite auch in der Embedded Softwareentwicklung und wir verwenden 
im Moment das freite Tool UMLet um UML Diagramme zu zeichnen.

> Also seit meinem ursprünglichen Post habe ich (hoffe ich) schon allerlei
> neue Erfahrungen sammeln können.
Ich bin auch der Sebastian aus dem ursprünglichen Post ;-)

> Sicher sind Statemachines oft ein gutes Mittel, um Abläufe zu
> modellieren. Aber eben auch nicht immer.
SW-Systeme allein mit Statecharts zu beschreiben ist unmöglich.
In unserem aktuellen SRS (Software Requirements Specification) sind auf 
oberster Ebene die Komponentendiagramme. Anforderungen, Teilnehmer und 
Akteure werden danach gut mit Use-Case Diagrammen beschrieben. Wie die 
Module miteinander interagieren, wird mit Sequenzdiagrammen beschrieben. 
Zustände innerhalb der Module werden mit Aktivitätsdiagrammen 
(Verhalten, Abläufe) und mit State Charts beschrieben (Zustände)

Wohl gemerkt, alles "embedded" auf einem 8-bit Controller. Für alle die 
so etwas nur mit 32 Bit Controllern und C++, C# in Verbindung bringen 
können ...

> Insbesondere muss man unterscheiden, ob die States natürlicherweise in
> einer Funktion enthalten sind (z.B. in einem Übertragungsprotokoll) oder
> ob sie künstlich eingeführt wurden, um das kooperative Multitasking zu
> ermöglichen. States aus dem ersten Fall lassen sich durchaus auch für
> den zweiten Fall verwenden.

Was meinst du mit "natürlichen" Task und "künstlichen" ? Kann mir 
darunter gerade wenig vorstellen.

> Ich habe aber die Erfahrung gemacht, dass man sich mit der Modellierung
> recht schwer tut, wenn man sich diesen Unterschied nicht bewusst macht.
>
> So wie ich sehe, versteht sich Astade nicht unbedingt als vollwertiges
> UML Werkzeug, sondern legt den Schwerpunkt auf automatische
> Codeerzeugung bzw. Simulation der Zustandsautomaten?
>
> Sofern das zur Modellbildung eines Algorithmus dienen soll, kann ich mir
> das schon als große Hilfe vorstellen. Weil das Modell dann mit der
> Softwareimplementierung konsistent bleibt.
>
> Wenn es hingegen um künstliche States wegen dem Multitasking geht,
> scheint mir sowas in der Art wie Adam Dunkels Protothreads die bessere
> Wahl zu sein. Aber da muss ich auch erst noch etwas mehr Praxiserfahrung
> sammeln.
>
> Grundsätzlich tue ich mich nach wie vor noch recht schwer ein
> Softwaresystem komplett als UML Modell darzustellen. Sicher ist es in
> Teilbereichen sehr hilfreich. Andererseits stehe ich immer wieder vor
> dem Problem den einen oder anderen Trick anwenden zu müssen, um
> Anforderungen hinsichtlich Echtzeit, Latenz, Jitter usw. gerecht werden
> zu können, wodurch die Programmstruktur nicht immer schöner und
> übersichtlicher wird. Das dann wiederum in einer Modellsprache
> abzubilden, die womöglich wieder automatisch Code erzeugen soll,
> erscheint mir vorsichtig formuliert unmöglich.
Die Qualität und die Tiefe der Beschreibung hängt natürlich auch davon 
ab für wenn die Beschreibung gedacht ist. Gerade wenn man in einem Team 
arbeitet ist eine gute Beschreibung unerlässlich - hier zeigen sich 
schnell die Schwächen eines schlecht dokumentierten Systems. ...
>
> Vielleicht habe ich nur immer noch die falsche Herangehensweise.
>
> Aber möglicherweise kommt ja noch die große Erleuchtung :-).
>
>
> viele Grüße!
> Klaus
viele grüße,
sebastian

von Thomas (Gast)


Lesenswert?

texmex schrieb:
> Ich hab' mir das Astade mal angeguckt. Die Idee mit den "dynamischen"
> Diagrammen finde ich ganz witzig. Aber ob sich das in der Praxis
> bewährt?

Ja, tut es. Ich entwickle seit 5 Jahren quasi "alles" mit Astade. Auch 
Astade selbst ist vollständig mit Astade entwickelt.
Leider sind die Tutorials und die Website noch nicht vollständig genug, 
um das alleine vom ansehen her zu beurteilen. Aber Du hast meine Aussage 
und wenn Du dich etwas näher damit befassen willst, helfe ich Dir gerne 
jederzeit über die Anfangsschwierigkeiten.

> Sicher sind Statemachines oft ein gutes Mittel, um Abläufe zu
> modellieren. Aber eben auch nicht immer.

Ein sehr wertvolles Hilfsmittel (eigentlich noch wertvoller als die 
generierten Statecharts) sind die automatisch generierten 
Sequenzdiagramme in Astade. Astade instrumentiert den erzeugten Code mit 
Macros und man kann dann, ein entsprechendes Makefile vorausgesetzt, ein 
Sequenzdiagramm vom laufenden Code bekommen.

> So wie ich sehe, versteht sich Astade nicht unbedingt als vollwertiges
> UML Werkzeug, sondern legt den Schwerpunkt auf automatische
> Codeerzeugung bzw. Simulation der Zustandsautomaten?

Astade versteht sich als IDE zur Softwareentwicklung, die UML soweit 
unterstützt, wie es für den Entwickler hilfreich ist.
Von der Astade Oberfläche aus wird Code generiert, der Editor 
aufgerufen, compiliert, ins Taget geladen und der Debugger gestartet.

> Sofern das zur Modellbildung eines Algorithmus dienen soll, kann ich mir
> das schon als große Hilfe vorstellen. Weil das Modell dann mit der
> Softwareimplementierung konsistent bleibt.

So ist es.

> Grundsätzlich tue ich mich nach wie vor noch recht schwer ein
> Softwaresystem komplett als UML Modell darzustellen. Sicher ist es in
> Teilbereichen sehr hilfreich. Andererseits stehe ich immer wieder vor
> dem Problem den einen oder anderen Trick anwenden zu müssen, um
> Anforderungen hinsichtlich Echtzeit, Latenz, Jitter usw. gerecht werden
> zu können, wodurch die Programmstruktur nicht immer schöner und
> übersichtlicher wird. Das dann wiederum in einer Modellsprache
> abzubilden, die womöglich wieder automatisch Code erzeugen soll,
> erscheint mir vorsichtig formuliert unmöglich.

Ist es nicht. Astade sieht viele Möglichkeiten vor, "Handcodierten" code 
neben dem Model zu haben. Das ist schon deshalb wichtig, weil Du auch 
"alten" Code verwenden willst, oder ein Beispiel aus dem Web, oder eine 
Library, oder Code Stücke, die der Hersteller mitliefert, oder oder oder 
...
Dort ist dann auch Platz für alle Arten von "Tricks". Natürlich macht 
das nur Sinn, wenn Deine Software nicht ausschließlich aus Tricks 
besteht ;-)

> Aber möglicherweise kommt ja noch die große Erleuchtung :-).

Wenn Du mal Zeit und Lust hast, Astade auszuprobieren, biete ich Dir 
meine Unterstützung an. Hier im Forum bin ich nicht immer gut zu 
erreichen, aber über die Astade Website erreichst Du mich auch.

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

> Leider sind die Tutorials und die Website noch nicht vollständig genug,
> um das alleine vom ansehen her zu beurteilen. Aber Du hast meine Aussage
> und wenn Du dich etwas näher damit befassen willst, helfe ich Dir gerne
> jederzeit über die Anfangsschwierigkeiten.

Tja, also so ein mini-howto, mit ein paar codebeispielen wäre sicher 
ganz interessant.
Das Script zum compilieren ist auch etwas undurchsichtig. Ich habe schon 
bemerkt dass "install" als Option an die Makefiles weitergereicht wird. 
Aber ich find's etwas blöd dass die Executables alle in ~/bin und die 
Librarys aber systemweit installiert werden (wollen).

> Ein sehr wertvolles Hilfsmittel (eigentlich noch wertvoller als die
> generierten Statecharts) sind die automatisch generierten
> Sequenzdiagramme in Astade. Astade instrumentiert den erzeugten Code mit
> Macros und man kann dann, ein entsprechendes Makefile vorausgesetzt, ein
> Sequenzdiagramm vom laufenden Code bekommen.

Hm, das klingt eigentlich schon ganz interessant.

> Dort ist dann auch Platz für alle Arten von "Tricks". Natürlich macht
> das nur Sinn, wenn Deine Software nicht ausschließlich aus Tricks
> besteht ;-)

Ja, versteht sich :-).

> Wenn Du mal Zeit und Lust hast, Astade auszuprobieren, biete ich Dir
> meine Unterstützung an. Hier im Forum bin ich nicht immer gut zu
> erreichen, aber über die Astade Website erreichst Du mich auch.

Das Angebot nehme ich zwar gerne an, aber vielleicht wäre es trotzdem 
effizienter, wenn Du die Mühe erstmal in noch etwas docu investierst? 
Dann hätten andere auch noch mehr davon?

Ich werde mir das ganze selbst nochmal angucken bei Gelegenheit.

Viele Grüße,
Klaus

von Thomas (Gast)


Lesenswert?

Klaus W. schrieb:
> Das Angebot nehme ich zwar gerne an, aber vielleicht wäre es trotzdem
> effizienter, wenn Du die Mühe erstmal in noch etwas docu investierst?
> Dann hätten andere auch noch mehr davon?

Im Grunde habe ich mich da schon bemüht. Hier gibt es tutorials: 
http://astade.de/doku2d49.html?id=tutorial:index

Das ganze ist als wiki gestaltet. Es ist aber wirklich sehr schwer, den 
richtigen Level für ein Tutorial zu finden (zumindest kommt mir das so 
vor).
Auch kann ich mir schwer vorstellen, was die Leute wissen wollen.

Ich habe jetzt einen Workshop ausgearbeitet, um speziell die 
Mikrocontroller Programmierung mit Astade zu erklären. 
http://consulting.astade.de/workshop.htm

Der Workshop findet am 15.04.2010 das erste mal statt. Danach habe ich 
möglicherweise genug Erfahrung (im Erklären) um eine Tutorial für 
Mikrocontroller Programmierung mit Astade zu machen.

Wenn Du was Ausprobieren willst und ich Dich hier im Forum unterstützen 
kann, dann würde mir das auch helfen. Es würde Helfen, zu bestimmen, 
welchen Inhalt ein Tutorial haben muss.

von Christian (Gast)


Lesenswert?

Hallo  Klaus!

Habe ehrlich gesagt nicht alle Antworten hier auf Deine Frage gelesen, 
allerdings immerhin Deine Frage komplett. (-; ^^

Vielleicht hast Du schon alles gefunden was Du brauchst, allerdings 
scheint mir vom ersten Eindruck ( so eben nach dem Lesen des Threads 
hier entdeckt ) Drakon ( http://drakon-editor.sourceforge.net/cpp/c.html 
) eine gute Lösung zur Visualisierung von C - Programmen zu sein. 
Insbesondere wie for-Schleifen dargestellt werden, fand ich sehr 
ansprechend.
Habe aber selbst bislang keine praktische Erfahrung damit, wollte es nur 
als weitere Alternative, gerade im Vergleich zu "einfachen" ( und damit 
meiner Meinung nach schnell unübersichtlich werdenden ) 
Programmablaufplänen oder komplexen (?) UML-Diagrammen nennen.

Weitere Links dazu:
- http://drakon-editor.sourceforge.net/
- https://en.wikipedia.org/wiki/DRAKON

Viele Grüße

Christian

von Johannes R. B. (Gast)


Lesenswert?

oh.. wenn jemand diesen alten OO-UML-Thread aufwärmt dann hab ich dazu 
auch noch zwei drei interessante Links wo sich in richtung embedded OO 
und embedded UML eine Menge tut:

http://mbed.org

http://www.avr-cpp.de

http://www.mystm32.de

http://www.infineon.com/dgdl?folderId=db3a304334fac4c601350a01037e11d2&fileId=5546d46146d18cb40146d6d7108a70b1

Gruß J.R.B.

von spess53 (Gast)


Lesenswert?

Hi

>Vielleicht hast Du schon alles gefunden was Du brauchst, ...

Nach vier Jahren sollte sich das Thema wohl erledigt haben.

MfG Spess

von texmex (Gast)


Lesenswert?

spess53 schrieb:
> Nach vier Jahren sollte sich das Thema wohl erledigt haben.

Hmm, ach, so würde ich das nicht sagen.

Erledigt ist so ein Thema wahrscheinlich nie ganz :-).

von Klaus (Gast)


Lesenswert?

> Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter
> Programmierung alles als funktionale Programmiersprache bezeichnet wird,
> was nicht objektorientiert ist.

Meine vereinfachte Vorstellung einer funktionalen Programmiersprache ist 
folgende: Sie ist die Beschreibung eines Schaltplans. So wie VHDL oder 
Veriolog.

von Thomas J. (jungthom)


Lesenswert?

Es gibt seit ein paar Monaten eine sehr interessante Alternative:

www.eclipse.org/etrice

Es handelt sich um ein ROOM-Tool.
ROOM = Realtime Object Oriented Modelling

Infos und Links:
http://de.wikipedia.org/wiki/Real_Time_Object_Oriented_Modeling

ROOM wurde speziell für embedded Echtzeitsysteme entwickelt. Die Methode 
stammt aus der Telekom.
ROOM wurde zu großen Teilen in die UML2 übernommen.

eTrice erzeugt den kompletten C-Applikationscode fürs Target.


Falls die benutzte IDE eine Eclipse basierte IDE (Kepler oder Luna)ist, 
sollte das Tool einfach über "help->Insall New Software" integriebar 
sein.

Für LPCXpresso habe ich das ausprobiert, funktioniert tadellos.

Ansonsten geht auch eine Stand-Allone Installation.

Viel Spaß
Thomas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.