Hallo zusammen, ich bin gerade am überlegen wie ich meine Software am besten so gestalte, dass ich sie leicht von einem Controller auf den nächsten portieren kann. Modular und gekapselt habe ich bisher schon programmiert, aber bei der Hardware hört es bisher immer auf. Jeder Controller hat ja unterschiedlich viel Funktionalität. Nun habe ich schon an verschiedenen Stellen etwas über HALs gelesen. Allerdings war dies nur sehr oberflächlich. Ich habe also nichts darüber gefunden, wie man an so eine Sache herangehen kann. Vor allem habe ich noch keine genaue Vorstellung wie man einen HAL optimal programmieren kann, dabei meine ich zum Beispiel die Verwendung von Interrupts usw.. Wie Schaffe ich es, die unterschiedlichen Strukturen verschiedener Controller durch eine einheitliche Schnittstelle zu beschreiben? Hat vielleicht einer ein paar Tips bzgl. Literatur oder Websites wo etwas zu diesem Thema zu finden ist? Über Tips aus der Praxis würde ich mich auch freuen. Zunächst möchte ich sowas auf einem ATMEGA zusammen mit dem GCC umsetzen. Viele Grüße, Ralf
Ein HAL ist erstmal nur eine Schnittstellen-definition, mehr nicht. Sie sollte natürlich möglichst portierbar und einheitlich zur unterschiedlichen Hardware sein, was ja auch der Unterschied zu anderen Schnittstellen ist. Allerdings lohnt sich ein HAL nur für große CPU's. Im Falle eines AVR's oder PIC's wäre er softwaretechnische "überdimensioniert" bzw. viel zu umständlich. Der HAL vom PalmOS zb. übernimmt einiges an intelligenter Funktion nebst eigenem ausführbarem Code. Das macht dort auch Sinn da man dort normalerweise keine Interruptroutinen oder System-Link-Bibliotheken selber programmieren wird oder kann. Auf einem AVR würde das aber bedeuten das man keine "Echtzeit-Systeme" mehr programmieren kann. Denn nun würde der HAL mit einer ziemlich komplizierten IRQ Logik verhindern das man zb. die Timerspezifischen PWM Eigenschaften der AVR's wirklich ausnutzen kann. Bedenke der HAL ist ein Abstractionlayer in Software der sich auf einem gemeinsammen Nenner an Funktionalität einigien muß. D.h. er ist zwar portable aber auch unspezifisch. Er kann also spezielle Unterschiede zwischen AVR, PIC oder ARM's nicht eingehen. Deshalb mache ich sowas immer anders. Alles was HW abhängig ist wird in einen Mini-HAL als Headerdatei ausgelagert. Je nach Hardware sind dann nur wenige Sourcedateien betroffen die geändert werden müssen. Ergo, ist es kein eigenständiger HAL mehr sondern nur noch eine einheitliche Schnittstellendefinition zur Hardware. Die HAL's die ich bisher gesehen habe, besonders der vom PalmOS, kann man sich vorstellen als Library die vergleichbar zum PC das BIOS + Windows Treiber repräsentieren. Also die unterste Ebene zur Hardware. Der restliche Programcode muß dann immer über das HAL arbeiten damit er auch in Punkto Portabilität überhaupt Sinn macht. Damit das funktioniort kann der HAL aber keine Platformspezifischen Funktionen enthalten und diese dürfen dann aber auch nicht am HAL vorbei zusätzlich benutzt werden. Ergo: auf Echtzeitsystemen ist ein HAL eher störend als sinnvoll. Nur meine 10 Cent Meinung :=) Gruß Hagen
Du könntest in deinem Hauptprogramm eine Variable CPU erstellen und dort z.B. über einen int Wert einstellen welchen uC du verwendest. Dann könntest du in einer oder mehrerer Header Datei/en den hardwarenahen Code für die jeweiligen uCs schreiben und jeweils in einer if(CPU == XYZ) Abfrage kapseln.
Wenn Du etwas portabel machen möchtest, dann gibt es dazu im Prinzip zwei Ansätze: a) Man beschränkt sich auf die Gemeinsamkeiten - und verliert dadurch viel Funktionalität b) Man bildet fehlene Funktionalität nach - und schleppt einen riesigen Overhead mit. Ich schließe mich da Hagen an: Für einen richtigen HAL sind die üblichen 8-Bit-Microcontroller zu klein. Markus
Hallo zusammen, danke für eure Tips! @ Heinz: So in der Art habe ich es bisher gemacht. Der Nachteil den ich darin sehe ist, dass mit steigender Anzahl von Funktionen und Controller der Code immer unübersichtlicher und schwer wartbar wird. Aus diesem Grund möchte ich solche Compilerschalter möglichst auf ein Minimum reduzieren. Teilweise habe ich dann ja auch noch Schalter für Debugzwecke im Programm. @all: Bei der Ansteuerung der Interrupts und der verschiedenen Timer von Controllern hatte ich auch die eigentlichen Probleme gesehen. Ich habe schonmal einen HAL für kleinere Controller gesehen. Dabei gab es allerdings das Problem, dass verschiedene Routinen zur Interruptsteuerung relativ lange dauerten wodurch es nicht mehr möglich war Zeiten sehr genau zu messen. Ich denke mal, dass es bei Schnittstellen wie CAN oder der seriellen einfacher sein wird eine gewisse Standardisierung zu erreichen. Gibt es vielleicht irgentwelche Konzepte wie man am besten festlegt wo man den Schnitt zwischen hardwarenahem, controllerspezifischem und allgemeinem Teil der Software macht? Was mich halt stört ist, dass man immer gezwungen ist relativ viel zu ändern wenn der Controller gewechselt wird. Wenn man bei den AVRs bleibt geht das ja noch, aber wenn es dann ein Wechsel auf eine andere Controllerfamilie ist, dann wird es schon aufwändiger. Viele Grüße, Ralf
Schau Dir mal zB FreeRTOS an, die Mischen die ganze Sache ein wenig. Es gibt Abstrakte #defines, ISRs werden für jeden Controller neu geschrieben und halten sich an einen bestimmten Standard. Für die UART hat man Beispielsweise einfach nur den "Funktionsrumpf" bestimmt, wodurch gewährleistet ist, daß die aufrufende Funktion überhaupt nichts von der darunterliegenden, hardwarenahen Funktion wissen muss, ausser den Parametern, die sie zurückgibt und erwartet. Wenn man sich da strikt dran hält, kann man das Ganze dann später wirklich mit nur einem einzigen Symbol beim Compileraufruf für eine Architektur/CPU oder vielleicht sogar nur ein "Application-Board" Kompilieren...
Ausserdem kann man so auch "Testsuites" auf dem PC Programmieren und die Grundsätzliche Fufnktion einer Applikation nachweisen. Ganz einfach indem man sich "Ersatzfunktionen", welche die Hardware "Simulieren", erstellt. Kann oft sehr hilfreich sein...
FreeRTOS habe ich mir auch schonmal runtergeladen (allerdings noch nicht richtig angeschaut) Wie sieht es denn bei einem RTOS mit den Reaktionszeiten auf Interrupts aus. Ich meine wenn ich z.B. Zeiten im Bereich von etwa 200us messen muss und kein Capture mehr frei habe? Bekommt man damit noch gute Zeiten hin oder ist dann eine Sonderlösung doch besser?
@Ralf >Was mich halt stört ist, dass man immer gezwungen ist relativ viel zu >ändern wenn der Controller gewechselt wird. Wenn man bei den AVRs >bleibt geht das ja noch, aber wenn es dann ein Wechsel auf eine andere >Controllerfamilie ist, dann wird es schon aufwändiger. Verständlich aber irgendwie doch ein Wiederspruch in sich. Um einen guten HAL zu schreiben muß man sich schon recht gut mit dem entsprechenden Controller auskennen. Hat man diese Kenntnisse dann ist der HAL aber wieder überflüssig weil man dann ,aufgrund der guten Kentnisse,auch gleich die Anwendung anpassen kann. Normalerweise bleibt man bei einer Familie aber das will ich hier nicht breittreten. Eine HAL macht im Grunde keinen Sinn da sie die Effektivität eines jeden Systems nur vermindern kann. Sie dient nur der Bequemlichkeit der Programierer. In zeiten wo jeder PC Speicher und Plattenplatz satt hat,wo Rechenleistung en Mass bereitsteht kann ich nur erahnen zu welchen Leistungen er eigentlich fäghig wäre wenn man sich seine Software mal nicht aus bauklötzen zusammenstecken würde. Den Vorteil der direkten effektiven Programierung willst du wirklich freiwillig aufgeben ?
Hallo @Ratber Ich habe natürlich nicht vor die flexible Programmierung aufzugeben, aber ich hatte halt schon ein paar mal das Problem (jobtechnisch), dass der Controllertyp gewechselt werden soll. Dabei ging es dann darum möglichst schnell zu entscheiden mit welchem neuen Typ eine Portierung möglich ist und wie lange eine Portierung braucht bis sie auf dem neuen Controller läuft. Sowas kommt irgentwie halt schonmal häufiger vor wenn andere Controller billiger sind. Meine Probleme sind dabei vor allem, dass ich relativ viele zeitkritische Funktionen in meinem Programm habe (Motorregelung, d.h. z.B. Drehzahl- Positionserfassung, PWM-Berechnung usw.) was also eigentlich ein Widerspruch zu einem HAL ist. Ich bin nun auf der Suche nach Möglichkeiten, diese möglichen Wechsel durch eine gute Programmierung in Zukunft zu vereinfachen. Dabei bin ich nun auf HALs gestoßen. Erste Erfahrungen wollte ich nun z.B. auf einem AVR sammeln (Hobby, vielleicht lässt sich das ganze ja auch hier nutzen :-)). Ich möchte also in erster Linie Erfahrung sammeln, wie ich an soetwas herangehe, wie ich die Schnittstellen gestalten muss, wo die Nachteile sind (da habe ich ja hier schon was erfahren :-)), usw. Im Moment habe ich nicht so wirklich eine richtige Vorstellung davon wie sowas in der Realität aussieht (vieleicht habe ich ja schon was ähnliches in meinem Programm und weiß nicht das es dafür so tolle Begriffe wie HAL gibt). Ich bin also auf der Suche nach verständlichen Erklärungen am besten mit Praxisbeispielen. Sowas wie HALs für Dummys oder so. In den Linux Quelltext zu gucken ist denke ich für eine Einarbeitung etwas aufwändig. Trotzdem danke für eure Hinweise! Bis denne, Ralf
Trennt euch doch BITTE von dem Gedanken, einen PC-ähnlichen HAL zu stricken! Das kann ja gar nicht Sinn der Sache sein. Eine "minimalistische" Form eines HALs bringt auch nicht sonderlich viel Overhead mit sich! Man kann sich ja für den Anfang auf eine Art ucHAL.h begrenzen, da einige inline-Funktionen und #defines hineinverlagern und Feddisch! Sowas mache ich sogar schon, wenn ich innerhalb einer Familie bleibe. Ja, es gibt auch Unterschiede zwischen Tiny26 und Mega128! ;) Auf letzterem arbeite ich, bis die Applikation "so gut wie Fertig" ist, auf dem Ersten wird dann die "Release" realisiert...
@Oldbug Natürlich will ich das nicht mit einem HAL unter Windows vergleichen sondern die Richtung aufzeigen. @Ralf Ich verstehe schon deine Gründe aber ich persönlich würde mir mal überlegen ob die häufige Springerei zum billigsten Controller überhaupt Sinn macht wenn du (Natürlich am Ende die Firma) damit jedesmal Arbeit und damit auch Kosten hast und sich das überhaupt lohnt. Es ist ja nunmal so das man sich mit der Zeit auf eine Familie einschießt und dort erweiterte Kenntnisse erwirbt. Das macht man sich mit einem Wechsel dann wieder zunichte und artet instress aus. Gut,ich weiß nicht wie das bei euch ist aber wir müssten bei jedem Wechsel das komplete Produkt neu beim Kunden zulassen und das kostet dann richtig Zeit und Geld. So,das wars von mir. Ich kann dir bei deiner Kernfrage leider nicht viel weiterhelfen und ziehe mich mal wieder zurück aber ich lese noch etwas mit und Fragen deinerseits beantworte ich auch gerne soweit möglich. Ratber
Ich dachte das dies oben schon erklärt wurde. Also man kann sagen das es zwei Formen von HAL's gibt. Den durchimplementierten HAL der wie zb. im PalmOS oder Windows aus eigenen Treibern, ergo eigenem lauffähigem Code besteht. Und den virtuellen HAL der im Grunde nur aus wenigen Header Dateien mit allerhöchstens par Makro's besteht. Der erstere soll den direkten Zugriff auf die Hardwareresourcen durch Anwendungsprogrammierer möglichst komplett unterbinden und somit benötigt man für jede neuere Hardware auch einen Treiber der zum HAL hinzugefügt wird. Der zweitere Typ ist auf einen einzige Software bezogen nur eine Sammlung von Schnittstellen und Funktionen die die spezifische Hardware ansteuert. Wenn, dann würde ich für MCU's nur diesen HAL empfehlen. Praktisch bedeutet das eine Software zb. aus 50 Quelltextdateien besteht wovon 1 oder 2 den HAL darstellen. Die restlichen Quelltexte greifen immer über diesen HAL zu. Dieser HAL ist spezifisch auf ein Board auf dem eine MCU sitzt. Zb. hat das Board 3 LED's und 1 PWM gesteuerten Motor und einen AVR. Im HAL sitzt nun der Code um diese LED's und den Motor zusteuern. Dabei steuert er dann direkt den AVR an. Wird nun der AVR durch einen PIC ausgetauscht so wird NUR der Quelltext des HAL's an den PIC angepasst, die restlichen 48 Quelltextdateien deiner Software bleiben unberührt da sie losgelösst von der eigentlichen Hardware sind. Im Grunde arbeiten wir tagtäglich mit einem "HAL", zb. die Runtime Libraries von WinAVR wäre so ein HAL. Das einheitliche Interface dieses HAL's sind die standardisierten C-Funktionen, wie printf() usw. Oder, wie es guter Programmierstil ist, benutzen clevere Programmierer ihre Includes und Header Dateien die in ihrer Funktion ausschließlich hardware-/nichthardware bezogen sind. Man unterteilt also sauber die komplette Software in verschiedene Teile wobei eben ein Teil der HAL ist. Ein HAL -> Hardware Abstraction Layer -> ist also nur eine Schnittstelle, eine Definitionssache. Ob diese nun mit eigenen Treibern oder aus einfachen Header-/Includedateien besteht ist erstmal nicht entscheidend. In beiden Fällen soll er den Rest der Software oder eben ganze Programme unabhängig von der Hardware machen. Ich handhabe es am liebsten so das zu jeder Bibliothek es immer eine Header/Include Datei gibt die den kompletten HW-nahen Code enthält. Der Dateiname enthält dann das Kürzel "HW_" oder meinetwegen auch "HAL_". Will man nun die Software anpassen konzentriert man sich nur auf diese Dateien. Gruß Hagen
@Hagen: Aber auch bei einem minimalistischen Hal bist Du doch darauf angewiesen, daß die MC gleich mächtig sind. Klar, wenn zwei verschiedene MC jeweils einen Hardware-UART haben, dann kann man dessen Benutzung schön in ein Headerfile packen. Aber was, wenn einer (weil er billiger ist) keinen UART hat? Packst Du dann den Software-UART ebenfalls in den HAL? Das ganze Spiel gilt natürlich auch für Interruptprioritäten, Anzahl Timer usw. usf. Deswegen bringt ein kleiner HAL meiner Meinung nach nicht so furchtbar viel. Markus
@Hagen Schön,dann hab ich ja mit Bascom mein Hal schon. LCD-ausgaben erledige ich auch nur per "LCD ........" Nur hilft mir das bei anderen Sprachen recht wenig da es den Befehl LCD nicht gibt. Ich nüßte ihn als Prozedur definieren die den Befehl nur durchreicht aber da fängt der spaß mit der Zeitverschwendnug schon an und die will Ralf ja vermeiden. Eine effektive Programierung ist immernoch "Direkt" Die Hersteller müßten sich schon im Groben auf einen festen Grundwortschatz einigen und wie Chancen für diesen Fall stehen brauche ich ja nicht zu schreiben. gg Meine Frage an Ralf wäre dann sowas in der richtung wie "Wieviel Performance und Reaktionszeit bist du freiwillig bereit abzutreten ?" Ohne Kompromiss ist da ja nun wirklich nix zu machen. Nur mal so als Anmerkung oder so.
>>billiger ist) keinen UART hat? >> Packst Du dann den Software-UART ebenfalls in den HAL? Nein eben nicht. Es würde drei Sourcem geben, Header + C Source für die UART Funktionen und 1 Header mit Makros die die Hardware anspricht speziell für die UART Funktionen. In den UART Source stünde also zb. sowas drinnen: void UART_Put(char c) { UART_DATA_REG = c; } und UART_DATA_REG ist in der HAL-Header Datei als Makro/Define etc. definiert -> #define UART_DATA_REG UDR -> für einen AVR. Wird nun ein Softare UART draus ist das auch kein Problem, denn nun würde man den HAL-Header mit anderen Makros/Defines umschreiben. Der Compiler linkt diese Sachen ja direkt in das Program ein, ergo ist die Frage von Ratber ebenfalls beantwortet, es wäre genauso effizient wie eine "direkte" Programmierung. Wie gesagt es ist doch reine Definitions- bzw. besser Organsiations-Frage. Nämlich wie sauber und strukturiert man programmiert. Wichtig ist doch nur das sich die Schnittstellen zur Hardware namentlich und funktionstechnisch nicht unterscheiden, egal ob der HAL für den AVR oder den PIC benutzt wird. Wir alle arbeiten doch "meistens" schon so. Alle Ports/Pins/Register sind doch schon in separate Dateien gepackt worden und mit diesen arbeiten wir. Das muß man nur noch konsequenter in seiner täglichen Arbeit umsetzen, zb. auch die Namensgebung dieser Dateien, und schwups könnte man sagen alle Dateien die mit "HAL_" beginnen sind die einzigsten Dateien in meinem Projekt die die Hardwarespezifischen Sachen enthalten, ergo diese Dateien SIND unser HAL. Der Sinn eines HAL's ist doch nur eine Verbesserung der Arbeitsabläufe bei der Programmierung. Einerseits um eine Software schneller portieren zu können und/oder andererseits damit ein DAU-Programmierer mit unserer Software arbeiten kann, sozusagen ein Baukastenprogrammierer damit zurecht kommt. Gruß Hagen
Moin moin, ich denke jetzt habe ich mal wieder etwas mehr verstanden. Bisher habe ich immer so programmiert, dass ich zum Beispiel ein UART-Modul hatte das nur in der Lage war einzelne Bytes zu übertragen. Bei der PWM sieht es ähnlich aus. Das PWM-Modul stellt eigentlich immer nur den Dutycycle ein und erledigt die Basisinitialisierung der PWM-Timer. Also hatte ich ja prinzipiell schon einen HAL und wusste nicht, dass es da so tolle Begriffe für gibt :-). Ich hatte mir da wohl eine größere Sache drunter vorgestellt (was es auf dem PC ja wahrscheinlich auch ist). In meiner Software muss ich teilweise auch verschachtelte Interrupts verwenden da mein Controller diese nicht unterstützt, d.h. ich deaktiviere zunächst alle nicht benötigten Interrupts und aktiviere dann die anderen global. Aber ich denke mal, dass ich an dieser Stelle wohl nichts verbessern kann, sodass dieser Teil allgemeingültiger wird. Man müsste dann ja grundsätzlich immer alle möglich Interruptquellen behandeln auch wenn diese in der jew. Software garnicht verwendet werden was dann wohl eine große Verzögerungszeit mit sich bringt. Ich habe im Moment die Anforderung, dass ich optimalerweise nur Verzögerungszeiten von etwa <5us in Kauf nehmen kann, da sonst meine Zeitmessung nicht genau genug ist was dann wieder andere Nachteile für mich hat. @Markus: >> Aber auch bei einem minimalistischen Hal bist Du doch darauf >> angewiesen, daß die MC gleich mächtig sind. Da ist wohl was dran und für mich dann wohl auch ein 'nein' für die Programmierung eines richtigen HALs. Wenn bei uns der Controller gewechselt wird, dann ist das im Moment eigentlich nur der Fall, wenn der andere billiger ist. Dann hat der neue meist auch noch weniger Funktionen sodass sich da eigentlich nicht so viele Gemeinsamkeiten feststellen lassen (bei mir war es z.B. der Fall dass ich von einem C164 auf einen H8Tiny wechseln musste). Bis denne und viele Grüße, Ralf
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.