Forum: Mikrocontroller und Digitale Elektronik C-Programmierung-->Bibliotheken,Standards,Portierbarkeit


von C-Beäugler (Gast)


Lesenswert?

Hallo liebe C-Programmierer Gemeinde,

bitte erschlagt mich nicht, aber vielleicht kann mir als Anfänger jemand 
einen kurzen Tip zu meinen Vorbetrachtungen geben.

Vorgeschichte:
Ich habe früher fast ein Jahrzehnt verschiedene Systeme in Assembler 
programmiert, wodurch ich gut mit der Funktionsweise solcher Systeme 
durch die hardwarenahe Programmierung vertraut bin.
Zeitraubend ist natürlich die Umstellung auf ein neues System, da man 
sich erst wieder auf seine Eigenheiten und den verfügbaren Befehlssatz 
einstellen muss.
Da wären wir dann auch schon bei dem entscheidenden Argument angekommen: 
die Portierbarkeit!
Wenn es der selbe Befehlssatz und Architektur ist(Bsp.Atmega8 vs. 
Atmega324) und nur die Peripherie angepasst werden muss , so ist die 
Portierbarkeit noch einigermaßen sinnvoll möglich.
Nehme ich eine andere Prozessorfamilie (Bsp.PIC),so fängt man von null 
an und schreibt "fix" alles neu.

Meine Interesse:
Nun schiele ich zu C und da wird die Portierbarkeit ziemlich groß 
geschrieben, zumindest lese ich dies oft.
Jetzt habe ich mir mal die Grundzüge von C angeschaut, 
Präprozessor...Compiler...Linker, alles super...man hat endlich die 
Unabhängigkeit und ist trotzdem noch nah an der Hardware.
Nur welche Bibliothek(en) nutze ich um wirklich Portabel zu sein?
Ich möchte z.B. den oft zitierten Text "Hello World!" mit dem selben 
Sourcecode über die serielle Schnittstelle am PC und an irgend einem 
Atmega (machen wir es mal am Atmega88 fest..)ausgeben, ist dies ohne 
Probleme möglich?
Welche Bibliothek(en) würde(n) dafür in Frage kommen und ist das 
praxistauglich, oder ist die Abstraktion bei so kleinen Controllern 
nicht so sehr sinnvoll?

Mir ist bewusst, das ich natürlich mit den entsprechenden 
Bitschubsereien durch einen Fünfzeiler in C die UART durch direktes 
initialisieren der entsprechenden Register sofort startbereit habe, 
allerdings eben nur auf diesem Prozessor :)
Super wäre ja, wenn man in einer Standard Bibliothek einer 
"Standard-Funktion"  einfach die Parameter zur Initialisation der 
seriellen Schnittstelle übergibt und mit mit anderen standard-Funktionen 
jetzt schreibt oder liest.
Wahrscheinlich sitzt ihr jetzt schmunzelnd da, weil meine Vorstellung 
des Ganzen etwas naiv ist :)
Ich versuche einen Ansatz zu finden um die für mich noch etwas 
verwirrende Library-Geschichte aufzudröseln....
Also,wenn jemand Lust hat mir ein wenig auf die Sprünge zu helfen, würde 
ich mich sehr freuen, ansonsten trotzdem danke fürs lesen!!

von Jay (Gast)


Lesenswert?

Im Embedded-Bereich ist nicht alles so portabel wie man es sich wünscht.

Innerhalb einer Prozessorfamilie mit ähnlicher Peripherie kann man meist 
mit etwas Zusatzaufwand und ein bisschen #ifdef portablen C-Code 
schreiben.

MCU-Hersteller bieten meist eigene Bibliotheken für ihre MCUs an. Leider 
ist die Qualität dieser Software häufig so bescheiden, dass man besser 
die Finger von lässt und den Controller und seine Peripherie statt 
dessen nach Datenblatt programmiert.

Algorithmen, die nicht oder kaum (und dann kontrolliert, isoliert) mit 
der MCU-Peripherie interagieren müssen, kann man, wenn man es nicht mit 
unstandardisierten C-Erweiterungen übertreibt, portable schreiben.

Portable ist meist auch C-Code, der nur die C-Standardbibliotheken für 
Freestanding Environments verwendet.

Etwas weniger portabel ist meist Code, der den vollen Satz der 
C-Standardbibliotheken verwendet.

Noch weniger portable ist C-Code, der z.B. über die 
C-Standardbibliotheken hinausgehende POSIX-API verwendet.

von Norbert H. (nobi)


Lesenswert?

Ja, das mit der Portierbarkeit geht im Embedded nur begrenzt.
In der Regel benutzt man hierfür verschiedene SW-Schichten.

Eine Basissoftware die auf dem Controller Aufsetzt, kann eine 
Abstraktion zur Verfügung stellen wie jetzt zum Beispiel eine 
Senderoutine für den Uart, Schreiben/Lesen auf/von IO ports, Analog 
Eingänge PWM, Auch Wlan Ethernet USB können abstrahiert werden.
Die Eigentlichen Applikation kann dann auf die Abstaktion zugreifen, und 
somit Daten lesen/schreiben ...
Wenn Die Abstraktion hier genormt ist, dann kann die Applikation 
zumindest problemlos portiert werden, die Basissoftware muss dann 
allerdings auf die entsprechenden Hardwaregegebenheiten angepasst 
werden.

von C-Beäugler (Gast)


Lesenswert?

Hallo Jay,

vielen Dank für Deine sehr hilfreiche Antwort :)
Ich hatte schon in Ansätzen diese Vermutung, also bleibt nicht viel 
übrig als die Bibliotheken mal zu durchstöbern und auf ihre Tauglichkeit 
zu prüfen.
Mal sehen welche Quellen sich da so finden und wie deren Qualität 
ist...ggf. müssen dann eben Stück für Stück eigene Bibliotheken her.
Würde mich zukünftig gern an den verschiedenen Cortex probieren, 
weswegen ich jetzt vorab den Einstieg in C auf vorerst vertrauten 
Architekturen suche.
Ich denke das mir durch die Vertrautheit des Systems gewisse Analogien 
beim Umstieg von Assembler auf C manche Hürde erspart und ich mich 
besser auf das Wesentliche konzentrieren kann, statt mich mit den 
Eigenheiten neuer Hardware rumzuschlagen.
Mal sehen wie mir das alles so gelingt ;)

Also Danke nochmal und einen schönen restlichen Donnerstag!!

von Peter D. (peda)


Lesenswert?

Der Trick ist, Hardwarezugriffe vom eigentlichen Programmablauf strikt 
zu trennen. Dann muß man nur noch diese wenigen Hardwarezugriffe 
anpassen.

Z.B. bei vielen MCs (PIC, 8051, AVR) kann man Portpins direkt zugreifen.
1
COOLING_FAN = 1;
Portabler ist man aber mit einer Funktion, dann muß man nur diese 
Funktion an das neue Target anpassen:
1
io_write(COOLING_FAN, 1);
Wenn dann diese Funktion inline oder als Macro definiert wird, gibt es 
auch keinerlei Overhead, d.h. sie ist nicht langsamer oder größer.

Für die UART schreibt man sich üblicher Weise ein putchar und getchar. 
Oftmals sind die aber schon in den Libs vorhanden oder in den 
Beispielen.

von Pandur S. (jetztnicht)


Lesenswert?

Viele Libraries braucht man nicht, ganzzahl math, und zwei drei 
umformungen, plus die prozessorspezifischen. Was man nicht braucht, resp 
unbedingt vermeiden sollte ist printf, dynamisches Memory und float.

von chris (Gast)


Lesenswert?

Oder D. schrieb:
> unbedingt vermeiden sollte ist printf, dynamisches Memory und float.

Wieso auf printf und float verzichten?
Wenn genug Flash vorhanden ist und die Laufzeit unkritisch ist, ist das 
doch sehr komfortabel.
Und einige µC haben sogar eine FPU eingebaut, da wäre es sinnlos, 
grundsätzlich auf float zu verzichten.

Man muss natürlich immer abwägen, wo man es sinnvoll einsetzen kann.

von C-Beäugler (Gast)


Lesenswert?

Hallo Norbert,

das klingt einleuchtend, wäre eben gut wenn es da einen Standard auch im 
Embedded-Bereich gäbe.
Warscheinlich ist eben bei der Vielfalt an Systemen der Grat 
schmal,Komfort beim Programmieren und Flexibilität+Geschwindigkeit 
standardisiert unter einen Hut zu bringen.
Gerade zweiteres ist ja im Embedded-Bereich bei begrenzten Ressourcen 
wichtig...
Eure Ansichten sind echt hilfreich und vermitteln einen guten Überblick 
für mich als Anfänger.

LG C-Beäugler (Alias Bestromer)

von Jay (Gast)


Lesenswert?

chris schrieb:
> Wieso auf printf und float verzichten?

Hängt vom Controller ab.

> Wenn genug Flash vorhanden ist und die Laufzeit unkritisch ist, ist das
> doch sehr komfortabel.

Ich gehe da nach dem Motto vor, spare in der Zeit, dann hast du in der 
Not. Wenn ich z.B. printf nicht unbedingt brauche, dann wird es nicht 
aus Bequemlichkeit eingebaut. Es ist nämlich sehr ärgerlicher es nachher 
wieder ausbauen zu müssen, weil der Speicher doch zu knapp wurde.

> Und einige µC haben sogar eine FPU eingebaut, da wäre es sinnlos,
> grundsätzlich auf float zu verzichten.

Umgekehrt, man wählt eine Controller mit FPU wenn es klar ist, dass man 
float mit FPU-Unterstützung braucht.

Sollte man zufällig eine FPU haben weil man einen Controller aus anderen 
Gründen gewählt hat, dann kann es sich lohnen darüber nachzudenken, ob 
man float sinnvoll einsetzen kann, obwohl sich das Problem nicht 
verändert hat. Rein aus Bequemlichkeit stelle ich allerdings kein 
Konzept auf float um, nur weil float mit FPU-Unterstützung da ist. Da 
muss es bessere Gründe geben.

von Maxi (Gast)


Lesenswert?

Peter D. schrieb:
> Der Trick ist, Hardwarezugriffe vom eigentlichen Programmablauf strikt
> zu trennen. Dann muß man nur noch diese wenigen Hardwarezugriffe
> anpassen.

Genau und das nennt man dann Hardware Abstraction Layer.

von B. S. (bestucki)


Lesenswert?

Normalerweise versucht man das Programm zu unterteilen: 
Plattformabhänging und nicht plattformabhänging. Manchmal sind auch noch 
Bindeglieder zwischen diesen beiden Ebenen nötig, damit der 
plattformunabhängige Teil wirklich plattformunabhängig ist.
Der plattformunabhängigen Teil kann man dann nochmals unterteilen: 
Abhängig von Hardware oder unabhängig von Hardware. Der von Hardware 
unabhängige Teil erstelle und teste ich meistens am PC, das sind z.B. 
Algorithmen, Buffer, spezielle Datentypen und teilweise Bibliotheken.

Plattformunabhängigkeit bedeutet aber noch mehr. Unter anderem auch der 
Verzicht auf Datentypen wie int, long, uint8_t usw. Stattdessen besser 
die Typen size_t, uint_fast8_t, ptrdiff usw. benutzen. Im 
hardwareabhängigen Teil werden wenn nötig Datantypen wie uint8_t 
verwendet, da teilweise die Breite des Typs übereinstimmen muss. 
Sämtliche Dinge die undefiniertes oder implementierungsabhängiges 
Verhalten erzeugen, strikt vermeiden. Hier gibts mehr:
Plattformunabhängige Programmierung in C

von Daniel A. (daniel-a)


Lesenswert?

Maxi schrieb:
> Peter D. schrieb:
> Der Trick ist, Hardwarezugriffe vom eigentlichen Programmablauf strikt
> zu trennen. Dann muß man nur noch diese wenigen Hardwarezugriffe
> anpassen.
>
> Genau und das nennt man dann Hardware Abstraction Layer.

Ich schliesse mich hier an. Angenommen man Programiert ein Modellauto, 
dann kann man sich ein Interface überlegen. Also z.B. hwInit setSpeed 
setDirection lightOn. Die Implementation dieser Funktionen ist dann 
Hardwarespezifisch, aber die gesammte Steuerlogik, welche diese 
Funktionen nutzt ist dann Hardware unabhängig. Das heisst, dass man nur 
den kleinen Hardwareabhängigen teil neuschreiben muss. Ich arbeite 
zurzeit am PC an einem TCP/IP Stack + Webserver, ich teste das Ding am 
PC, aber es ist so geschrieben, dass nur 2 andere von rund 35  c files 
dazugelinkt werden müssen um es für einen uc zu Kompilieren. Ist dieses 
Projekt: https://github.com/Daniel-Abrecht/DPA-UCS/

von Patrick B. (p51d)


Lesenswert?

Norbert H. schrieb:
> Ja, das mit der Portierbarkeit geht im Embedded nur begrenzt.
> In der Regel benutzt man hierfür verschiedene SW-Schichten.

Bei höheren Prozessorleistungen werden aus diesem Grund oft Kernels 
eingesetzt (z.B. FreeRTOS). Wenn noch mehr Leistung vorhanden ist, 
kommen Embedded OS (Linux, Android, Windows CE...) zum Einsatz. Somit 
gewinnt man auch gleich die ganzen Kommunikationsstacks.

Wenn es ohne gehen soll, sind die Bord Support Packages der Hersteller 
sehr interessant (STM-Cube). So bleibt die Portierbarkeit innerhalb des 
Prozessor-Herstellers respektive der Familie erhalten.

C-Beäugler schrieb:
> das klingt einleuchtend, wäre eben gut wenn es da einen Standard auch im
> Embedded-Bereich gäbe.

Es gibt schon Standards, die man eigentlich umsetzen sollte. Nur wird 
das nicht oft gemacht. MSIRA-C ist in vielen Gebieten Pflicht bei der 
Abnahme.

von B. S. (bestucki)


Lesenswert?

Be S. schrieb:
> Abhängig von Hardware oder unabhängig von Hardware.

Nachtrag: Ich meine damit, ob die Software darauf angewiesen ist, ob 
irgendwo ein Eingang für einen Taster oder ein Ausgang für eine LED 
vorhanden ist. Systenabhängig wäre das bessere Wort gewesen.

Patrick B. schrieb:
> Embedded OS (Linux, Android, Windows CE...)

Auch hier macht man üblicherweise eine Unterteilung zwischen 
systemabhängig und systemunabhängig. Ansonsten wird die Portierung von 
Linux zu Windows oder umgekehrt ein Krampf (oder zu einem anderen OS).

von W.S. (Gast)


Lesenswert?

C-Beäugler schrieb:
> Jetzt habe ich mir mal die Grundzüge von C angeschaut,
> Präprozessor...Compiler...Linker, alles super...man hat endlich die
> Unabhängigkeit und ist trotzdem noch nah an der Hardware.
> Nur welche Bibliothek(en) nutze ich um wirklich Portabel zu sein?

Bibliotheken? Wohl eher nicht.

Wenn du mal von den Befindlichkeiten absiehst, die man an einem PC hat 
und dich auf das konzentrierst, was in einem µC das Übliche ist, dann 
hast du ganz generell eben kein Betriebssystem + Anwendungen, sondern du 
hast eine Firmware, die eben das tun soll, wozu der µC auf der 
Leiterplatte sitzt.

So. Und eine Firmware ist zu einem ganz erheblichen Teil schlichtweg 
hardwareabhängig. Das berüchtigte "Hello World" ist noch keine wirkliche 
Firmware, sondern allenfalls ein allerersten und winziger Schritt auf 
dem langen Weg zu einer Firmware. Ja, auch Algorithmen sind da häufig 
nicht portabel, da sie zur Lösung der eigentlichen Aufgabe des Chips auf 
spezielle Eigenschaften eben dieses Chips aufbauen müssen.

Also, wa kannst du tun?
Du kannst und solltest deine Firmware modular aufbauen und zwar so, daß 
du getrennt Hi-Level Module und dazu passend sinnvolle Low-Level-Treiber 
schreibst, die selbstverständlich hardwarespeziell in ihrem Inneren 
sind, die aber nach außen hin deutlich die zugrundeliegende Hardware 
abstrahieren.

Also nicht "SetMyBit(PortX, BitY)" sondern besser "SchalteMotorEin()". 
Das erleichtert nämlich nicht nur das eventuelle Portieren, sondern auch 
die Lesbarkeit des ganzen Projektes.

Aber mit "Bibliotheken" und gar noch von irgend einem Hersteller wird 
das alles nix. Laß dich also zuvörderst NUR auf all das ein, was im 
jeweiligen Referenzmanual des µC steht - und (soweit es geht) nicht auf 
irgendwelche Hersteller-Kits usw. weil die in aller Regel genau das 
Gegenteil von Portierbarkeit und Allgemeinverständlichkeit im Sinn 
haben. Das ist halt ein Interessenkonflikt zwischen Herstellern der 
Chips und den Entwicklern von Geräten, wo solche Chips hinein sollen. 
Hier hat es z.B. schon viele Leute gegeben, die sich auf die ST-Lib 
eingelassen haben - und? Nun ja, sie verstehen die zugrunde liegende HW 
immer noch nicht und sind dennoch auf ST festgenagelt, weil sie mit dem, 
was sie dabei gelernt und an Moduln geschrieben haben, bei allen anderen 
Herstellern nichts anfangen können. Kundenbindung eben. Das Gleiche in 
Grün gilt für NXP mit LPCxpresso und so weiter...

W.S.

von B. S. (bestucki)


Lesenswert?

W.S. schrieb:
> Also nicht "SetMyBit(PortX, BitY)" sondern besser "SchalteMotorEin()".
> Das erleichtert nämlich nicht nur das eventuelle Portieren, sondern auch
> die Lesbarkeit des ganzen Projektes.

Am besten beides. SchalteMotorEin rurf dann SetMyBit auf. Hängt der 
Motor nach einem Umbau plötzlich an einem Treiber an der UART, ruft man 
trotzdem nur SchalteMotorEin auf. SchalteMotorEin muss dann natürlich 
entsprechend umgeschrieben werden, dass der entsprechende Befehl nun via 
UART gesendet wird. Das Ganze nennt sich Kapselung, also, dass eine 
Änderung (egal ob HW oder SW) möglichst wenige Auswirkungen auf das 
Gesamtsystem hat.

: Bearbeitet durch User
von C-Beäugler (Gast)


Lesenswert?

Hallo Jungs :)

hatte gestern Spätdienst, bin nun wieder am Start und echt überwältigt 
von den vielen Beiträgen....echt tolle Gedankengänge welche für mich als 
Anfänger super nützlich sind und man dankend annimmt!!!
Ich glaube dadurch eine gute Richtung bekommen zu haben.

Peter D. schrieb:
> Der Trick ist, Hardwarezugriffe vom eigentlichen Programmablauf strikt
> zu trennen. Dann muß man nur noch diese wenigen Hardwarezugriffe
> anpassen.

...das ist ein guter Merksatz ;)
Ich hatte zu Zeiten der Assemblerprogrammierung immer sehr kompakten und 
effizienten Code geschrieben, leider war damit die Pflege und vor allem 
die Portierbarkeit sehr schlecht.
Folglich kam die Ära des Modularisierens, wobei insgesamt alles besser 
wurde, aber ich mich sehr schwer tat eine sinvolle und klare Trennung 
für die einzelnen Module zu finden.
Die Wiederverwendbarkeit in der selben Prozessorfamilie war schon gut, 
aber wenn die Peripherie zu stark abwich wurde es schon haarig.
Mir fehlte quasi oftmals die Entkopplung von den Hardwarezugriffen, da 
ich immer wieder dazu neigte die strikte Trennung nicht zu erkennen.


chris schrieb:
> Wieso auf printf und float verzichten?
Jay schrieb:
> Hängt vom Controller ab.

...das würde ich mir in dem jeweiligen Fall anschauen und abwägen ob 
der Programmieraufwand oder die benutzten Ressourcen mehr ins Gewicht 
fällt.
Ich glaube da kann man mit der Zeit auch viel lernen :)


Maxi schrieb:
> Genau und das nennt man dann Hardware Abstraction Layer.

...ja, so ist es... schon oft gehört, aber leider hab ich dieser 
wichtigen Sache nicht die nötige Aufmerksamkeit gewidmet!!!


Daniel A. schrieb:
> Ich schliesse mich hier an. Angenommen man Programiert ein Modellauto...

...sehr anschauliche Beschreibung, Danke :)


Patrick B. schrieb:
> Bei höheren Prozessorleistungen werden aus diesem Grund oft Kernels
> eingesetzt (z.B. FreeRTOS). Wenn noch mehr Leistung vorhanden ist,
> kommen Embedded OS (Linux, Android, Windows CE...) zum Einsatz.

...da hat man natürlich die beste Portierbarkeit, sowas ist dann 
tatsächlich für die reine Anwendungsentwicklung prima.
Langsam wird mir die Abstufung und der jeweilige Einsatzfall immer 
deutlicher!!!


Be S. schrieb:
> Hier gibts mehr:
> Plattformunabhängige Programmierung in C

...verdammt, irgendwie habe ich diesen wertvollen Link nicht gefunden, 
das ist ja schon fast peinlich!!
Danke :)


W.S. schrieb:
> Aber mit "Bibliotheken" und gar noch von irgend einem Hersteller wird
> das alles nix. Laß dich also zuvörderst NUR auf all das ein, was im
> jeweiligen Referenzmanual des µC steht....

...Das sind vertraute Gewässer, weshalb ich diesen Ratschlag gerne 
annehme!
Der Irrglaube lies mich annehmen durch C von dieser Pflicht entbunden zu 
sein :)

W.S. schrieb:
> Also, was kannst du tun?
> Du kannst und solltest deine Firmware modular aufbauen und zwar so, daß
> du getrennt Hi-Level Module und dazu passend sinnvolle Low-Level-Treiber
> schreibst

...genau diese Trennung fiel mir irgendwie schwer, ich weiss noch nicht 
warum mir dies erst beim erlernen einer neuen Programmiersprache so 
bewusst wird?
Warscheinlich war meine Herangehensweise damals ein vermeindlich guter 
Weg, da ich relativ anspruchsvolle Projekte mit gutem Erfolg sehr 
kompakt im engen Zeitrahmen umgesetzt bekommen habe.
Leiter ist mir das Ganze wie ein Bleiklumpen auf die Füsse gefallen, als 
auf dem Markt für MC's immer mehr bewegung kam und auch mal geliebten 
Kandidaten die Abkündigung bevorstand.
Ein Umschwenken auf andere Kandidaten war dann "mal eben schnell" nicht 
möglich :)


An alle noch einmal recht herzlichen Dank für das Interesse und die 
damit investierte Zeit!
Toll das es Leute wie Euch gibt, mit denen man fundiertes Wissen kompakt 
austauschen kann.


LG vom C-Beäugler (Alias Bestromer)

von W.S. (Gast)


Lesenswert?

C-Beäugler schrieb:
> ...genau diese Trennung fiel mir irgendwie schwer, ich weiss noch nicht
> warum mir dies erst beim erlernen einer neuen Programmiersprache so
> bewusst wird?

Also erstens ist Assembler im Allgemeinen nicht wirklich portierbar, 
weswegen man bei der Assembler-Programmiererei auf solche Dinge nicht so 
viel Wert legen sollte - da ist viel eher Kompaktheit und Effizienz 
gefragt.

Zweitens scheint es mir (nach deinen Worten) ein bissel so, daß du 
bislang zu eher unstrukturierter Schreibweise geneigt warest. Aber auch 
das ist bei Assembler nicht unüblich, ich denke mal an Konstrukte, die 
man in keiner abstrahierender Sprache so schreiben kann wie sowas:
Hex32Out:
   PUSH  R0
   LD    R0,R1
   CALL  Hex16Out
   POP R0
Hex16Out:
   PUSH  R0
   SWAPW R0
   CALL  Hex8Out
   POP   R0
Hex8Out:
   PUSH  R0
   SWAPB R0
   CALL  HexNibbleOut
   POP   R0
HexNibbleOut:
   AND   R0, 15
   LD    R0, CharTafel+R0
CharOut:
   ....
   RET

Sowas geht eben NUR in Assembler...

W.S.

von c-hater (Gast)


Lesenswert?

C-Beäugler schrieb:

> Wenn es der selbe Befehlssatz und Architektur ist(Bsp.Atmega8 vs.
> Atmega324) und nur die Peripherie angepasst werden muss , so ist die
> Portierbarkeit noch einigermaßen sinnvoll möglich.

Sowas geht in C kein bissel besser als in Asm!

> Nehme ich eine andere Prozessorfamilie (Bsp.PIC),so fängt man von null
> an und schreibt "fix" alles neu.

Klar. Deswegen vermeidet man es auch, die µC-Familie für eine 
existierende Anwendung zu wechseln, solange es irgendwie geht.

> Meine Interesse:
> Nun schiele ich zu C und da wird die Portierbarkeit ziemlich groß
> geschrieben, zumindest lese ich dies oft.

Ja, aber mindestens die Hälfte davon ist reines Wunschdenken. Das war 
mal der Plan, aber es funktioniert in aller Regel nicht. Allein die 
riesigen #ifdef-Orgien im existierenden Code sollten dich stutzig 
machen. Bei einer Portierung von einer Plattform mit Bitbreite X zu 
einer anderen Plattform mit gleicher Bitbreite X wirst du ganz sicher 
mindestens ALLES anfassen müssen, was in diesen ganzen verdammten 
#ifdefs eingekästelt ist.

Von den subtilen (viel schwerer zu findenden und behebenden) Problemen 
beim Wechsel auf ein System mit andere nativer Bitbreite mal ganz zu 
schweigen...

> Nur welche Bibliothek(en) nutze ich um wirklich Portabel zu sein?

Natürlich keine mit irgendwelchen Abhängigkeiten von irgendeiner 
konkreten Hardware. Das ist als Forderung einfach aufzustellen, aber de 
facto äußerst schwierig zu kontrollieren. Es läuft darauf hinaus, den 
Code im Detail zu verstehen. D.h.: es ist nur minimal leichter, als ihn 
gleich selbst für das neue Ziel zu schreiben...

von Stefan F. (Gast)


Lesenswert?

Ich kann zwei Beispiele nennen, wo die Portierbarkeit recht gut ist: Und 
zwar der µIP Stack (Für Internet Kommunikation) und die AVR FAT32 
Library (für SD Karten).

Beide Libraries setzen auf einen separaten Layer für den Zugriff auf die 
Hardware.

Wenn du diese Libraries mit einer anderen Hardware verwenden willst, 
musst du nur den Hardware Layer umschreiben. Der größte Teil kann 
unverändert blieben.

Ein anderes Beispiel: Eine Net-I/O Firmware. Diese war ursprünglich 
(nicht von mir) für Atmega32 + EN28J60 geschrieben und wurde dann auf 
Atmega644 + CP2201 portiert. Ich habe den Code dann nochmal auf 
Xmega128D3 portiert.

All diese Änderungen erforderten prinzipiell nur minimale Anpassungen an 
wenigen Dateien.

Leider ist es nicht in jedem Programm so einfach. Wenn man 
Portierbarkeit im Sinn hat, sollte man Zeit investieren, den Code 
dementsprechend zu strukturieren. Damit die Hardware-Spezifischen 
Befehle eben nicht über den gesamten Code verstreut sind.

von W.S. (Gast)


Lesenswert?

c-hater schrieb:
> Von den subtilen (viel schwerer zu findenden und behebenden) Problemen
> beim Wechsel auf ein System mit andere nativer Bitbreite mal ganz zu
> schweigen...

Da hast du ja im Prinzip ganz recht.

Es gibt nur relativ wenige Dinge, die sich wirklich leicht portieren 
lassen. Hauptsächlich sind das richtig geschriebene Headerdateien, also 
die Schnittstellen zwischen den verschiedenen Moduln. Und es sind Dinge, 
die nach reiner EDV aussehen. Ich nenn da mal ein paar Beispiele aus der 
berüchtigten Lernbetty: conv.c und conv.h, die Fonts, der Rumpf des 
Hintergrund-Monitors, die Header der seriellen Schnittstelle(n), das 
Prinzip des Systemticks und der Event-Verwaltung. Das alles läuft bei 
mir inzwischen auf recht unterschiedlichen Plattformen, ja sogar auf 
solchen mit anderer Endianess. Aber man sieht auch, daß es sich dabei 
eben IMMER um Dinge handelt, die recht hardwareunabhängig sind.

W.S.

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.