[C] Bibliotheken für z.B. Display, CAN-Controller, (.) portierbar gestalten

OP #4263572
Lesenswert?
• ▲
▼
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
Gast #4263596
Lesenswert?
• ▲
▼
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
Gast #4263789
Lesenswert?
• ▲
▼
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;
OP #4264008
Lesenswert?
• ▲
▼
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?
Gast #4264032
Lesenswert?
• ▲
▼
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.
Gast #4264035
Lesenswert?
• ▲
▼
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(...);
}
#4264091
Lesenswert?
• ▲
▼
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.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.