Inhalt
Topic:.Devlp_emC.
Das emC ist nicht nur eine Ansammlung von Sources als Basis für embedded Programmierung sondern ein Konzept.
Topic:.Devlp_emC..
Wir kennen die Gegenüberstellung Wasserfallmodell vs. iterative Herangehensweisen. Ein Wasserfallmodell-Konzept kann freilich einmal richtig überlegt schnell und zielgerichtet umgesetzt werden. Das Problem hierbei ist nur das Wort richtig. Das Richtigsein wächst mit den Erfahrungen im Umgang. Vorher der Plan - dann die Ausführung. Dieses Prinzip gilt immer dann, wenn eine nachträgliche Korrektur aufwändig ist. Bei Software trifft das nicht zu, die Korrektur am Objekt selbst im Nachhinein heißt updaten. Statt von Bananensoftware - reift beim Kunden spricht man heute von DevOps - die Einheit der Entwicklung mit dem Einsatz, häufige Updates, Feedback von den Anwendern verarbeiten. Diese Herangehensweisen sind meistenteils richtig.
Was vom Wasserfallmodell übrigbleibt, ist der Konzeptgedanke. Das genaue Durchplanen der Einzelheiten ist die Herangehensweise von gestern. Aber ein Konzept muss stehen.
Bedeutung der Dokumentation: Ein Konzept wird mit der Dokumentation gefestigt. Wenn man ein Grobkonzept hat, danach arbeitet, Efahrungen gewinnt, und danach das Erarbeitete dokumentiert, dann zeigt sich in der Dokumentation, ob das Konzept in sich stimmig ist. Man darf eine (endgültige) Dokumentation also nicht am Anfang verfassen (das wäre das Wasserfallmodell), auch nicht am Ende nach Abschluss der Entwicklung. Die Dokumentation muss endgültig werden, wenn die Entwicklung bei etwa realen 90% angekommen ist. Also: Alle Dinge sind berücksichtigt, laufen, aber Änderungen können noch erfolgen und der Endtest darf wiederholt werden. Wenn man dann in der Dokumentation Widersprüche feststellt, dann sollte man ändern. Es gibt damit weitere Iterationszyklen.
Konzept und Pragmatik: In der Implementierungsphase wird ein Konzept aus Zeitgründen und nur vorübergehend, erstmal schnell verlassen. Damit etwas zum laufen kommt. Nun kommt es aber darauf an: Entweder die durch Praxis sich ergebende Herangehensweise beeinflusst dann doch das Konzept. Die Pragmatik war weiterführend. Oder es muss Zeit geben, die vorerst nur pragmatische Lösung wieder auf das Konzept zurückzuführen. Es gibt leider noch eine dritte Möglichkeit: es dabei bleiben zu lassen. Damit wird ein Konzept in der Implementierung verwässert. Letzteres kennen wir in der Software. Von außen sieht alles ganz gut aus, klare Bedienung, klares Verhalten. Eine Nachnutzung der Software darf solche verwässernden Implementierungen nicht enthalten, was Aufwand bedeutet.
Topic:.Devlp_emC..
Das Konzept von emC ist über Jahre unverändert. Folgend ist in der ersten Unterpunktebene das Konzept genannt, in der zweiten Unterpunktebene dann die iterative Entwicklung der Ausführung.
Grundgedanke, Sources unverändert auf PC zu testen und in verschiedenen Zielsystemen zu applizieren.
Keine Abweichung in der Ausführung. Diese Konzeptidee besteht seit den 90-ger und ist mit viel Erfahrung untermauert.
Die Variabilität kommt durch Includieren gleichnamiger Headerfiles, die in verschiedenen Verzeichnissen stehen. Mit dem Setzen des Include-Path beim Compilieren kann man selbst beim gleichen Zielsystem Variationen einbringen.
Ursprünglich hieß der zentrale gleichnamige Includefile complctr.h
mit einem 8-3-Filenamen, wie unter DOS notwendig. Das war etwa 1993. Die Feststellung damals war: Man muss für verschiedene
Compiler (oder Systemumgebungen) verschiedene Definitionen haben.
Später, in den 2000-er wurde der Name dann auf os_types_def.h
geändert. Namen müssen stimmen. Es geht eben nicht nur um den Compiler, sondern damals um die OperationSystem-Umgebung und
grundsätzliche Typdefinitionen.
Mit Anwendung des emC-Konzeptes auf verschiedenen Plattformen und der Dokumentation des Konzepts hat sich deutlich gezeigt,
dass es zwei bestimmende Headerfiles geben muss. Diese sind dann als applstdefJc.h
und compl_adaption.h
entstanden. Zuvor hat es einige im Anwenderbereich anzupassenden Headerfils wie fw_Platform_conventions.h
, BlockHeap_PlatformSpec.h
, assert_Fwc.h
usw. für verschiedene Teilaspekte gegeben. Das hat sich für die Anwender als schlecht durchschaubar herausgestellt.
Der derzeitige Stand ist: applstdef_emC.h
gibt es in verschiedenen vorgefertigten Versionen, mit und ohne Exceptionbehandlung usw. Dort befinden sich aktivierbare
Compilerschalter, und includierte Header aus dem Bereich sourceApplSpecific
. Dabei hat sich der Verzeichnisname von inclApplSpecific
nach source...
gewandelt, da h- und c-Files, die applikationsspezifisch eingebunden werden können, zusammengehören. applstdef_emC.h
darf auch in den Applikationsbereich kopiert und dort applikationsspezifisch angepasst werden.
Die compl_adaption.h
ist auf den verwendeten Compiler mit den Zielsystemeinstellungen ausgerichtet. Diese ist eigentlich nicht applikationsspezifisch.
Man darf keine Applikationsspezifität hineininterpretieren, nur weil für den einen oder anderen Anwender ein Compiler mit
einem bestimmten Zielsystem bzw. der darauf laufenden Applikation verbunden ist.
Von Anfang an haben Programmierkonzepte aus Java eine Rolle gespielt. Es hat die Information Pate gestanden, dass die ursprüngliche Intension der Java-Entwicklung aus 1990..95 aus dem embedded Bereich kam und Java daher bestmöglichst auf diesen Zweck ausgerichtet wurde. Es ist nicht für ganz kleine Systeme geeignet, die man aus damaliger Sicht wohl nur in Assembler programmieren kann. In den 90-ger Jahren hat sich ungeachtet dessen C etabliert, auch für ganz kleine Prozessoren, und hat diesen Java-Gedanken verdrängt. Die C-Systemumgebungen sind sehr verschiedenlastig. Mit Java hat man eine bessere Richtschnur für einen allgemeine Ansatz als etwa mit der Orientierung auf POSIX, oder Microsoft, oder usw.
Daher wurde das Basissystem ursprünglich CRuntimeJavalike genannt, auch für die Verwendung als Basissystem von automatisch aus Java nach C übersetzten Quellen. Dieser Java2C-Translator wurde entwickelt, um in Java programmieren zu können für die Zielsystemcompilierung in C. Er war nie dafür gedacht, um eigentlich in Java programmierte Dinge irgendwie auf einem C-System zu applizieren. Der Unterschied besteht darin, dass Programmier- und Schreibweisen in Java für die Zielsystemanwendung berücksichtigt werden.
Es hat sich beim Einsatz dann gezeigt, dass die große Masse der Embedded-Programmierer eher weniger dem Java zugeneigt sind, dass aber die CRuntimeJavalike-Sources gut für C taugen.
Damit hat eine Trennung stattgefunden. Die eigentlich nur für C gedachten Sources wurden in einem Unterverzeichnis Fwc
gehalten, als Filenamen mit fw_....
bezeichnet und mit dem Suffix der Identifier_Fwc
versehen. Dabei gab es allerdings immer schon eine gewachsene Vermischung mit dem Suffix Jc
(Java in C).
Der Name CRuntimeJavalike oder kurz CRJ war immer mal wieder etwas irritierend ('ist da Java drin - das geht doch gar nicht ...').
Daher, auch um eine größere Nutzerbreite zu erzielen, wurde der Name des Sourcepools und des Konzepts in 2018 in emC umbenannt. Wichtige Kennzeichen in diesem Namen sind das e für embedded, diese Plattform ist eben nicht für PC-Applikationen, sondern für den breiten Bereich der Embedded Programmierung mit Test auf dem PC gedacht. Das m steht für multiplatform wegen dem wichtigem Kennzeichen: Keine plattform- und applikationsspezifische Anpassung der Sources notwendig. Das C ist selbstsprechend, damit nicht im Widerspruch zu C++.
Mit dieser iterativen Entwicklung ist allerdings eine hohe Änderungsrate der Bezeichnungsschemata einhergegangen. Stabiles Konzept mit vollkommen geänderte Quellen (-?). Die Anpassung bestehender Anwendungsquellen an die geänderten Bezeichnungen hat sich mit überschaubarem Aufwand an Suchen/Ersetzen und Testcompilierung nicht eigentlich als Problem erwiesen. Refacturing wird von den Tools durchaus unterstützt.
Objektorientierte Entwicklung in C war von Anfang an Konzeptgedanke
und ist unverändert bis heute vorhanden.
Die Objektorientierung ist etabliert nicht als Eigenschaft einer Sprache (von Smalltalk, C++, C# und Java) sondern ist ein Softwarearchitektur-Konzept. C bietet Sprachmittel. Es gibt keinen Grund in C nicht objektorientiert arbeiten zu dürfen. Es gibt gute Gründe für die Objektorientierung.
Die Orientierung auf eine Basisklasse, ObjectJc
, adäquat der java.lang.Object
ist möglich aber nicht notwendig.
Die direkte Zuordnung der Reflection zu Daten, notwendig wenn ein Basistypzeiger verwendet wird, ist mit ObjectJc
unmittelbar unterstützt. Da man in C meist nicht mit abgeleiteten Typen arbeitet, funktionieren Reflection auch ohne die
Basisklasse. In diesem Fall ist der Reflectionbaum parallel zu den Daten gebaut. Der Typ der Daten ist in den Reflection bekannt.
Er muss zum tatsächlichen Typ passen. Das ist gewährleistet, wenn keine falschen Zeiger in Anwendungen vorkommen (das wäre
ein Softwarefehler) und wenn die Reflectiongenerierung versionsmäßig zu den Daten passt. Das funktioniert auch, hat sich im
Anlageneinsatz bewährt.
Damit ist die Bedeutung der Basisklasse ObjectJc
in Bezug auf Reflection vermindert, nicht unbedingt nötig. Das hat sich im Laufe der Nutzung der emC gezeigt.
Das dynamische Binden von Operationen an den Instanzyp (virtuelle Methoden) wird verwendet, meist aber nicht zentral in den Anwenderapplikationen. Die Möglichkeit besteht, wird wenig genutzt.
Der Einsatz des Reflection-Prinzips kommt aus Java. Damit wurde sehr erfolgreich ein Inspector-Konzept entwickelt und eingesetzt.
Anfänglich wurde eher auf C++ orientiert. Es sollten auch methods mit den Reflections zugänglich sein.
Da die Quellen zwar meist mit einem C++-Compiler übersetzt wurden, aber selbst in den Reflection-nutzenden Datenstrukturen
keine class
sondern struct
verwenden, ohne Mehrfachvererbung, sind die C++-spezifischen Teile nicht weitergepflegt worden. Dasss die Reflection auch
für class
immer noch voll anwendbar sind, muss noch getestet werden.
Die Einbeziehung der Methoden oder Operation in die Reflection ist immer schon etwas reduziert gewesen, bezüglich der Argumenttypen. Es wurde nicht darauf orientiert, sondern nur auf die Datenzugriffe.
Die Datenzugriffe einschließlich Einfachvererbung mit geschachtelten struct
ist insbesondere auch für Bitfields optimiert worden.
Das manuelle Schreiben der C-Quellen für die Reflections hat sich von Anfang an als ein zu sparender Aufwand erwiesen. Die eigentlichen Informationen sind in den Headerfiles enthalten. Nur für Basisstrukturen bestehen manuell erstellte C-Files der Reflections. Alle anderen C-Files sind generiert.
Für die Generierung wurde von Anfang an das Java-Programm org.vishia.zbnf.header2Reflection.Header2Reflection
verwendet. Das Syntaxfile ist zbnfjax/zbnf/CHeader.zbnf
Das Syntaxfile ist verfeinert und verbessert beibehalten worden und stabil.
Das Tool Header2Reflection
verwendet das direkte Auslesen des Parserergebnisses aus dem ZBNF-Parser. Die zu erzeugenden Sekundärquelltexte sind mit
hard coded direkter Zeichenkettenverarbeitung (printf) zusammengestellt. Damit ist eine nicht große Flexibilität verbunden, die notwendige Flexibilität muss mit einem überlagertem
Config-File erreicht werden.
Daher wird aktuell ein neuer Ansatz verwendet: Das Parsen der Headerfiles erfolgt immer noch mit dem gleichen Parser (ZBNF)
und dem Syntaxfile CHeader.zbnf
aber das Parserergebnis wird mit dem Java-Programm org.vishia.zbnf.header2Reflection.CheaderParser
abgelegt. Dabei erfolgt auf dieser Ebene eine Sortierung. Beispielsweise werden innere struct
mit einem Namen versehen und sind damit für einen Inspectorzugriff als Strukturelement sichtbar. Die Organisation des Parsens
und die Generierung der Header wird mit dem JZtxtcmd-Sript zbnfjax/jzTc/Cheader2Refl.jztxt.cmd
gesteuert, dass aus einem anwendungsspezifischen JzTxtCmd-Script heraus gerufen wird. Beispielsweise emc/make/genRefl_emC.jz.cmd
für alle Reflection der emC. Das ist aktueller Stand.
Ursprünglich, mit dem org.vishia.zbnf.header2Reflection.Header2Reflection
, wurde ein großes File der Reflection für die gesamte Applikation erstellt. Einzelne Teil-Files sind möglich, müssen dann
spezifisch für den Linker mit aufgenommen werden. Für flexible Applikationsgestaltung muss damit immer die Reflectiongenerierung
angepasst werden.
Mittlerweile, mit dem Cheader2Refl.jztxt.cmd
, wird pro Headerfile genau ein Reflectionfile mit der Endung .crefl
erzeugt. Da für eine gute Softwarestruktur immer die Zugehörigeit von einem Headerfile zu einem, oder nur für Varianten mehrerer
C-Files als CompilationUnit bestehen soll, wird das ....crefl
-File nunmehr in das implementierende ...c
-File includiert, und zwar bedingt nicht wenn keine Reflections in der Applikation verwendet werden sollen. Damit braucht
bei der Zusammenstellung eines Projektes nicht mehr Rücksicht auf die Reflection genommen werden. Die Reflection sind mit
dem zugehörigem Headerfile in der CompilationUnit vorhanden und werden vom Linker so gefunden.
Das Formulieren der Quellen in Java und nachfolgendes Übersetzen und Implementieren in C ist als Möglichkeit gegeben.
Der Java2C-Translator ist seit etwa 2008 brauchbar und wurde in den Folgejahren etwas weiterentwickelt. Das Grundkonzept funktioniert.
Die aus Java generierten Quellen sind fester Bestandteil der emC-Sources. Die Java-Quellen sind in emC nicht mit gespeichert, sie entstammen den Open-Source Java-Komponenten srcJava_vishiaBase und srcJava_vishiaRun. Diese sind unabhängig archiviert (Archiv bei github). Damit ist die Quellenzuordnung nicht fest.
Die Lesbarkeit der aus Java generierten Sources ist ausreichend. An sich sollte ein generierter Quelltext nicht verändert werden. Fehlerkorrekturen und Erweiterungen wurden teils direkt in den C-Sources betrieben und manuell in Java nachgepflegt.
Insbesondere die Quellen für den Inspectorzugriff emc/source/InspcJ2c
werden für selbigen Zweck auch direkt in Java verwendet. Mit der Generierung Java2C ist damit gleichzeitig sichergestellt,
dass die Konzepte Reflection in C und Reflection in Java nicht auseinanderdriften.
Verwenden für grafische Programmierung
Zu Anfang der emC (oder CRuntimeJavalike)-Entwicklung stand die Entwicklung mit UML im Vordergrund.
Mittlerweile wird emC als Basis für Simulink-generierte C-Codes und als Basis für S-Functions in Simulink (Simulink-Blöcke mit C realisiert) verwendet.
Es hat sich gezeigt, das emC in Verbindung mit grafischer Programmierung taugt.