Hallo! Ich versuche gerade meine Bibliotheken für externe Bausteine an µCer zu überarbeiten, so dass sie portierbar werden (und zwar Projekt- und µC-bezogen). Da kommen dann ja irgendwann so Probleme auf wie z.B. bei einem HD44780, der mit vier oder acht Datenleitungen angeschlossen oder nicht immer an PortX angeschlossen sein kann (Projektbezogen). Meine Lösung ist im Moment in den Bibliotheken solche "Schnittstellen" als externe Funktionen zu deklarieren. So muss man diese halt in seinem Prozessorspezifischen teil definieren um die Bibliothek zu nutzen. Ist das so schon die richtige Richtung oder geht das auch eleganter? Bin gespannt, Heiko
Hi, abstrahiere die Hardware in eine low-level Schicht und arbeite dann nur noch mit Interfaces. Soetwas nennt man Schichtentrennung oder Softwarelayer. Der eigentlichen Application ist es dann egal, welche Hardware darunter liegt. Deiner eigentlichen Application ist es auch egal, ob das Display über 4 oder 8 Leitungen angeschlossen ist. Application | Interfaces | Basis Software | Hardware Bei CAN wäre es dann Funktionen z.B. (C-Pseudo-Code) can_init(baudrate) can_transmit(msg) msg = can_receive() die low-level Funktionen der einzelnen Targets packt man in eine Libs und linkt die passende zur Application. Grüße
Die Hardware spezifischen Sachen mache ich gerne mit Makros, welche dann von meinen Anwendungen und Libraries verwendet werden. Zum Beispiel: #define POWER_LED_AN PORTA | =8; #define POWER_LED_AUS PORTA &= ~8;
Bleiben wir mal beim CAN- Controller und sagen wir mal, dass er per SPI kommuniziert. Nehmen wir jetzt einmal die Funktion "can_transmit(msg)", die von der CAN_IC- Bibliothek bereitgestellt werden soll. Die Funktion liegt in der Bibliothek, um mit dem Baustein selbst zu kommunizieren braucht man aber die "SPI- Kommandos" des µCs. Mein Ansatz war jetzt eine Funktion, z.B. uc_sendto_can_ic(data), in der Bibliothek als extern zu deklarieren. Auf der Seite die "einbindet" muss man diese Funktion dann definieren (das wäre dann das Interface?) und dafür sorgen, dass "data" an den CAN-Baustein gesendet wird. Das wäre dann ja quasi nur das low-level Zeugs, also der Hardware abhängige Code. Da wäre dann getrennt Anwendung, µC- Interface, Baustein- "Treiber". Das wäre also so schon ganz gut oder verstehe ich da etwas immer noch nicht? Mit den Makros wäre das Obige glaube ich etwas zu komplex?
Heiko L. schrieb: > Das wäre also so schon ganz gut Ja. Das wäre quasi die Essenz von dependency injection in C umgesetzt. Viel eleganter geht es in C nicht. Wenn Du irgendwann deine Bibliothek auf dem PC testen willst, kannst du ihr (vereinfacht) eine uc_sendto_can_ic(data) unterschieben, die data nach stdout loggt und eine uc_readfrom_can_ic(), die Testdaten liefert.
Nein, so war das nicht gemeint. Nichts hardwareabhänginges in der
Application. Deine Lib implementiert die Funktion. Du bindest
nur die H-Datei ein, die für alle Hardwarevarianten gleich ist und baust
für jede Hardwarevariante eine eigene Lib.
Z.B.
geinsamer Header (Prototype):
extern void CanInit(...);
Für Hardware A (Implementierung):
void CanInit(...) {
spi_init(...); /* can over spi */
}
Für Hardware B (Implementierung):
void CanInit(void) {
CanControllerInit(...);
}
Heiko L. schrieb: > Da kommen dann ja irgendwann so Probleme auf wie z.B. bei einem HD44780, > der mit vier oder acht Datenleitungen angeschlossen oder nicht immer an > PortX angeschlossen sein kann (Projektbezogen). Ich trenne die allgemeine Peripheriefunktionalität von der Hardwareinitialisierung. Für das hier verwendete CAN Beispiel bedeutet dies: CanInit() greift nur auf den CAN selbst zu. Am besten noch ein variabler Pointer/Handle, wenn dein Controller/deine Bibliothek mehrere gleichartige Periperiemodule unterstützt, z.B. mehrere CAN Controller. Heiko L. schrieb: > Meine Lösung ist im Moment in den Bibliotheken solche "Schnittstellen" > als externe Funktionen zu deklarieren. Genau. Auch bei mir gibt es an anderer Stelle die Hardware-Funktionen, welche den CAN-Takt und die Alternate-Function Konfiguration einstellen. Auch die Interrupthandler definiere ich außerhalb und verzweige von dort dann in die Lib. Einfach, da die Namensgebung manchmal fest ist. Innerhalb der Lib nutze ich nur in den seltensten Fällen externe Low Level Funktionen. Ich würde es aber machen, wenn die Lib einen Zugriff nach außerhalb benötigt. Cani schrieb: > abstrahiere die Hardware in eine low-level Schicht und arbeite dann nur > noch mit Interfaces. Soetwas nennt man Schichtentrennung oder > Softwarelayer. Der eigentlichen Application ist es dann egal, welche > Hardware darunter liegt. Zustimmung. Meine Aussage, welche sich mit dem Vorschlag vom TO deckt, legt die Trennung auf einen sehr niedrigen Layer (Hardwarekonfiguration). Cani schrieb: > nur die H-Datei ein, die für alle Hardwarevarianten gleich ist und baust > für jede Hardwarevariante eine eigene Lib. Dies wäre dann eine Ebene höher. Du erstellst z.B. eine Library für ein Protokoll (CANopen) und möchtest diese mit den verschiedenen CAN Controllern nutzen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.