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!!
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.
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.
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!!
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.
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.
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.
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)
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.
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.
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
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/
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.
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).
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.
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.
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)
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.
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...
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.
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.