Da ich die Grundlagen lernen will, experimentiere ich mit einem
STM32F103 Mikrocontroller ohne HAL.
Jedes mal, wenn ich für mich zufriedenstellend herausgefunden habe, wie
man eine Funktion benutzt (Takt, ADC, PWM, RTC, usw) habe ich danach mal
in Tutorials geschaut, wie das denn mit der HAL gemacht würde.
Dabei ist mir immer wieder aufgefallen, dass die HAL Beispiele weder
kürzer noch übersichtlicher noch Hardware-Unabhängiger sind. Darüber
hinaus vergibt die HAL für Register und Bits neue Namen, die nicht mit
dem Reference-Manual überein stimmen, um die Verwirrung zu maximieren.
Ständig muss ich in die Quelltexte der HAL hinein schauen, um
nachzuvollziehen, was sie tut (denn die Doku ist Rotz, sorry). Das kann
doch nicht Sinn der Sache sein?
Ich glaube die HAL ist nur dann nützlich, wenn darauf aufbauende
Libraries auf höherer Ebene nutzt (z.B. für USB). Allerdings habe ich
auch dafür längst kompaktere und verständlichere Alternativen gefunden
(und zwar hier im Forum).
Ist meine Erkenntnis im Groben und Ganzen korrekt?
Ich denke nicht das es darauf eine Antwort gibt.
Jeder Bastler wie er mag, jeder Profi so wie er es vorbereitet
(vorgefunden) hat bzw. so wie ihm befohlen wird.
Ich verzichte auch auf die STM32Cube und verwende CMSIS. Gent meistens
sehr viel einfacher und direkert, zumindestens für die einfachen
Peripherie Funktionen wie UART, SPI, I2C, Timer und ADC.
Nur wenn ich einen Ethernet Controller mit LwIP verwende, benutze ich
dafür die STM32Cube da ich noch keine Zeit dafür gefunden habe einen
eigenen Treiber zu schreiben.
So meinte ich das nicht. Ich wollte keine Empfehlung für oder gegen die
HAL, sondern eine Einschätzung, ob meine Erkenntnisse bezüglich der
Nachteile korrekt sind. Ich habe mit der HAL ja noch fast gar nichts
gemacht und schätze die Situation daher womöglich völlig falsch ein.
> Nur wenn ich einen Ethernet Controller mit LwIP verwende ...
Heißt das: wenn du einen Treiber auf Basis der CMSIS hättest, würdest du
ihn bevorzugen?
Auf jeden Fall bin ich ganz froh darüber, dass man nach dem Erstellen
des Grundgerüstes mit Cube MX einfach mit CMSIS weiter arbeiten kann.
Niemand zwingt einen dazu, ALLES mit der HAL zu machen.
Ich finde HAL sehr gut.
Im Zusammenspiel mit CubeMX und der Auto-Vervollständigung vom SW4STM32
unterstützt es einen auch wenn das Gehirn nicht mehr alles selbst
speichert.
Ausserdem kommt man schnell ans Ziel.
Wenn du natürlich für alles Nötige deine eigenen Funktionen schon hast,
bleib dabei.
Übrigens ist das Meiste, dass die HAL Funktionen größer macht die
Sicherheit.
Man kann z.B. mit ein paar Bytes den Takt einstellen, man kann aber auch
den Erfolg jeder Funktion Abfragen und Auswerten, so wie HAL das macht.
Du weist aber schon, daß dioe CMSIS Bestandteil der HAL ist und auch von
der genutzt wird?
Wenn die Frage sinnvoll sein soll, dann eher "HAL, SPL oder ohne
Middleware?"
Wober es für die neueren STM32 keine SPL mehr gibt, da geht nur mit oder
ohne HAL.
Die HAL ist extrem resourcenfressend. Ich habe mal DMA fullduplex mit
HAL ausgemessen.
Aufsetzen der DMA frisst alleine 5 Mikrosekunden. Dann werden 3
Interrupts von der HAL ausgeführt, alle auch arschlangsam. HAL generiert
3 (!) Interrupts. Die machen einen Interrupt, wenn DMA halb leer ist
(völliger unsinn) und je einen wenn TxDMA und RxDMA fertig ist.
Insgesamt werden mehr als 12 us verbraten.
Ich habe es mit den ebenfalls in CubeMX enthaltenen Low level sourcen
nachgebaut und komme damit auf 1.3 us (72 MHz Takt, nucleo STM32F411)
Beim einfachen Setzen eines GPIO sieht es ähnlich aus. Mit den Low Level
erreicht man um die 30 MHz beim einfachen einauschalt Test. Mit Hal
gehts arg in die Knie.
Stefan U. schrieb:> Ist meine Erkenntnis im Groben und Ganzen korrekt?
Jap total!
Ich hatte im März rum mit den STM32 angefangen und bin mit HAL
gestartet.
Hatte aber damit nur Probleme und die Abstraktionsebenen waren mir zu
krass.
Da wird auch so ein Haufen an Overhead (vorallem alles, was mit
Interrupts gemacht wird) mitkompiliert, das hatte mir dann auch nicht
gefallen.
Nachdem ich quasi schon ein fertiges Projekt auf CMSIS umgebaut hatte,
war es nicht nur übersichtlicher, es lief auch wesentlich performanter.
Ich finde HAL schrecklich :)
Dummerweise wird man für neue STM32-µCs wohl keine StdPeriphLib mehr
erhalten :/
Ehrlich gesagt, ein Grund für mich von den STM32 auf lange Sicht wieder
zu verabschieden, obwohl ich im Grunde sehr zufrieden war.
HAL ist aber für mich ein Nogo ...
Allerdings verwende ich sehr gerne CubeMX, um die Peripherie für meine
Pins auszuwählen. Der Code, der dann für die GPIOs generiert wird, kann
schnell auf CMSIS umgebaut werden.
Eins der Dinge, die mich an der ST HAL ganz gewaltig stört, ist dass sie
einen interruptgesteuerten HW 1ms Timer ungefragt installiert - und zwar
zu dem einzigen Zweck, einen Timeout auf HAL Initialisierungsfunktionen
zu implementieren.
Das ist nicht nur für die meisten praktischen Zwecke sinnfrei (wenn die
Prozessorinitialisierung nicht durchgeht, gibt es in aller Regel kein
kontrolliertes recovery, also wozu einen Timeout? Was tut man, wenn der
zuschlägt? Und wenn es Sinn macht, den Fall zu unterscheiden, darf man
an der Stelle auch ruhig mal mit Busy Wait und Polling auf eine Flag
schaffen, da die Zeit eh nicht Anders genutzt werden kann), sondern hat
Auswirkungen auf alle möglichen Systemteile, wie z.B.
- Bootloaderkompatibilität (was wenn die IVT umgebogen werden muss?)
- Low Power Sleep Modus (wie verhindere ich, dass dieser nutzlose
ISR mich jede Millisekunde völlig effektfrei aufweckt?)
- Footprint
- Ressourcennutzung (ich würde in den meisten Fällen gerne selber
bestimmen, wie viele und welche Timer meine Applikation nutzt)
Etc pp.
Die STMLib war mir im grossen und Ganzen symapthischer, hat aber ihre
eigenen Probleme (z.B. wurden bibliotheksglobale Variablen gehalten, in
denen die Prozessorfrequenz zwischengespeichert wurde. Da man in der als
lib kompilierten Variante Probleme hat, das Layout der Variable zu
beeinflussen, gibt es i.Z. mit Bootloadern interessante Effekte, die so
manche Woche Entwicklungszeit für Fehlersuche schlucken).
Die CMSIS ist ja nichts weiter als ein PAL (Processor Abstraction
Layer), in den neueren Varianten ein PMAL (Processor and Middelware
Abstraction Layer). Da sie weniger Annahmen über die zu Grunde liegende
HW machen kann (eigentlich nur den jeweiligen Cortex Kern), ist sie
weniger invasiv.
Man muss sich aber immer vor Augen halten, dass all diese Layers nicht
(jedenfalls nicht primär) aus altruistischen Gründen (so wie dem
Entwickler das Leben zu erleichtern) gemacht wurden, sondern um
Geschäftsziele umzusetzen (Stichwort vendor lock in). Das ist erstmal
nicht verwerflich oder unmoralisch. Aber es sollte sich Niemand der
Illusion hingeben, dass die Verwendung so eines HAL (egal wie er heisst
und von wem er kommt) tatsächlich zu einem Plug and Play
Click-Compile-and-run Entwicklungszyklus führt.
Ich nutze übrigens lwip komplett ohne HAL, und es geht problemlos.
> Du weist aber schon, daß dioe CMSIS Bestandteil der HAL ist> und auch von der genutzt wird?
Ja natürlich. In der Tat habe ich CMSIS Files aus einem HAL Projekt
extrahiert da ich keine separate Quelle gefunden habe.
Hallo,
zum Bootloader habe ich auch noch eine Geschichte. Hatte länger dran
debuggt.
Der Bootloader lief, aber wie nun das zu loadende Programm generieren?
den *.ld file anpassen, damit die IVT stimmt, reicht leider nicht!
HAL generiert einen file namens system_stm32f4xx.c
darin enthalten ein define:
#define VECT_TAB_OFFSET 0x00
das muss man anpassen, es ist ein Offset!
bei mir lag die IVT bei 0x8010000 im *.ld file
dann muss man den offset als 0x10000 definieren, sonst funzt das Ganze
nicht.
so was ist einfach Sch....! Die load Adresse muss man händisch in den
generierten sourcen anpassen. Wenn man dann CubeMX noch mal generieren
lässt, weil man was vergessen hatte, muss man das wieder händisch
anpassen. Cube überschreibt das define wieder.
Beschrieben war das in einer UM, aber bis ich das fand. . . .
Martin B. schrieb:> bei mir lag die IVT bei 0x8010000 im *.ld file> dann muss man den offset als 0x10000 definieren, sonst funzt das Ganze> nicht.
Ähm, dann hast du obskure Linker-Scripte mit dem generierten Source-Code
von HAL gemixt ...
Wüsste in diesem Fall nicht, was HAL dafür können soll ...
Mampf F. schrieb:> Martin B. schrieb:>> bei mir lag die IVT bei 0x8010000 im *.ld file>> dann muss man den offset als 0x10000 definieren, sonst funzt das Ganze>> nicht.>> Ähm, dann hast du obskure Linker-Scripte mit dem generierten Source-Code> von HAL gemixt ...>> Wüsste in diesem Fall nicht, was HAL dafür können soll ...
Ich habe nichts gemixt, nur was geändert.
Der *.ld file wurde von CubeMX generiert und dort habe ich die Start
Adresse geändert. Ich wüsste nicht wo sonst.
in CubeMX habe ich keine Möglichkeit gesehen, die startadresse zu
ändern.
Vielleicht habe ich ja was übersehen.
Martin B. schrieb:> Die HAL ist extrem resourcenfressend. Ich habe mal DMA fullduplex mit> HAL ausgemessen.> Aufsetzen der DMA frisst alleine 5 Mikrosekunden. Dann werden 3> Interrupts von der HAL ausgeführt, alle auch arschlangsam. HAL generiert> 3 (!) Interrupts. Die machen einen Interrupt, wenn DMA halb leer ist> (völliger unsinn) und je einen wenn TxDMA und RxDMA fertig ist.> Insgesamt werden mehr als 12 us verbraten.>> Ich habe es mit den ebenfalls in CubeMX enthaltenen Low level sourcen> nachgebaut und komme damit auf 1.3 us (72 MHz Takt, nucleo STM32F411)>> Beim einfachen Setzen eines GPIO sieht es ähnlich aus. Mit den Low Level> erreicht man um die 30 MHz beim einfachen einauschalt Test. Mit Hal> gehts arg in die Knie.
Mit Optimierung und LTO? Compilerversion? Das mit dem GPIO-Toggle glaub
ich dir nicht. Und ohne LTO musst du gar nicht erst kommen, das macht
extrem viel aus. Ich nutze die HAL inzwischen bei jedem Projekt und
hatte mit ihr noch nie Geschwindigkeitsprobleme. Die hat man eher in den
Algorithmen, auf welche man sich dann konzentrieren kann. Was
interessiert mich ob die Initialisierung eine µs länger dauert?
Ruediger A. schrieb:> Man muss sich aber immer vor Augen halten, dass all diese Layers nicht> (jedenfalls nicht primär) aus altruistischen Gründen (so wie dem> Entwickler das Leben zu erleichtern) gemacht wurden, sondern um> Geschäftsziele umzusetzen (Stichwort vendor lock in).
Ja das liest man hier desöfteren. Aber der Vergleich hinkt, so lange du
keine Alternative vorweist, die herstellerunabhängig ist. Egal welche
sinnvolle Middleware ich nutze (dazu gehört mMn embed und Arduino nicht
dazu), ich bin an STM gebunden. Wer das nicht möchte und seine
Bibliotheken plattformunabhängig einsetzen möchte, der zieht eben nach
der STM-Middleware noch ein Abstraktionslayer ein und Dank LTO kostet
das exakt 0% Overhead.
Stefan U. schrieb:> Ist meine Erkenntnis im Groben und Ganzen korrekt?
Ja! Die HAL ist Rotz, schlecht dokumentiert, handwerklich schlecht
umgesetzt und abstrahiert exakt garnichts :-)
Stefan U. schrieb:> Ist meine Erkenntnis im Groben und Ganzen korrekt?
Klar und einfach: Ja.
Es gibt hier ganz viele Leute, die sehr fleißig all die XYZ_InitStruct's
ausfüllen, brav all die vielen dargebotenen Funktionen aufrufen, sich
ihre Einstellungen von Hilfszeugs wie Cube und so generieren lassen -
und die dabei erstens garnichts über das Pferd lernen, das sie reiten
wollen und zweitens glauben, das seien die Dinge, auf die es ankäme.
Sieh das mal so: All die herstellerseitigen Hilfestellungen sind zwar
nicht böswillig gemacht, aber sie sind dennoch sehr einseitig auf die
jeweiligen Produkte gerichtet. Es sind sozusagen die Würmer auf den
jeweiligen Angelhaken.
Funktionieren tut das erstaunlich gut, weil die Masse der
Möchtegern-Programmierer es rundweg ablehnt, die jeweiligen
Referenz-Schriften durchzulesen, ein klitzeklein wenig Assembler zu
lernen und das Aufrufen der Tools wie Compiler usw. zu erlernen. Kurzum:
was machen wollen, ohne was zu lernen und zu können. System
Schlaraffenland.
Obendrein lehnen es viele aus ideologischen Gründen ab, ihren Horizont
zu erweitern. Sie nehmen und kennen nix anderes als den Gcc und haben
keinen Begriff davon, wie andere Toolchains (z.B. Keil, IAR)
funktionieren.
Mein Rat ist immer wieder, nicht geradewegs drauflos zu programmieren,
sondern strikt getrennt nach Startcode (in Assembler), Setup-Units,
Treibern und höheren Programmschichten zu schreiben, wobei die Treiber
eine wirklich sinnvolle Schnittstelle nach oben hin haben sollen, also
funktional abstrahieren sollen.
Und dabei schafft man sich mit der Zeit sein eigenes Portfolio an
Quellen, von denen man einige völlig unverändert von einem System auf's
andere mitnehmen kann und andere bloß im Detail anzupassen braucht, um
sie zu portieren.
Auf diese Weise wird man weitgehend unabhängig von einzelnen Herstellern
- und man wird effektiv, weil man ne Menge Algorithmen weiterverwenden
kann.
W.S.
avr schrieb:> Mit Optimierung und LTO? Compilerversion? Das mit dem GPIO-Toggle glaub> ich dir nicht. Und ohne LTO musst du gar nicht erst kommen, das macht> extrem viel aus. Ich nutze die HAL inzwischen bei jedem Projekt und> hatte mit ihr noch nie Geschwindigkeitsprobleme. Die hat man eher in den> Algorithmen, auf welche man sich dann konzentrieren kann. Was> interessiert mich ob die Initialisierung eine µs länger dauert?
Habe einen GCC und alle Optimierungen ausgetestet. Weil die performance
bei mir das Problem war! Solche Untersuchungen, macht man nur, wenn man
muss.
Problem war:
Alle 15 us kommt ein Interrupt und dann müssen 27 byte per SPI
übertragen werden.
Wenn ich HAL benutze ohne DMA wirds richtig grausam. Ausser diskussion.
Low Level Funktion ohne DMA hatte ich um die 15 us, also 100%
nur mit LL und DMA läuft das Teil.
Warum die HAL so langsam erschliesst sich, wenn man die die Sourcen der
HAL guckt!
P.S.
wegen GPIO: Wenn Du das mal mit Oszi nachmisstst, brauchst Du Deinen
Glauben nicht bemühen.
Martin B. schrieb:> Ich habe nichts gemixt, nur was geändert.>> Der *.ld file wurde von CubeMX generiert und dort habe ich die Start> Adresse geändert. Ich wüsste nicht wo sonst.
Ah okay verstehe ...
Hmm, damals mit den alten SAM7Sxx hatte ich den Bootloader immer in das
Programm integriert und der Code, der vom Bootloader ausgeführt werden
muss, in das SRAM gepackt.
Im Grunde war das dann kein Bootloader sondern ein Flash-Tool, das
on-demand von der Applikation aus gestartet werden kann.
Die Alternative dazu war, den default-Bootloader zu verwenden. Die
hatten einen im ROM, war aber ultranervig zu verwenden. Jedesmal musste
man eine Boot-Recovery-Prozedur durchführen, die aufwändig war.
Haben die STM32 nicht auch einen Bootloader schon eingebaut?
avr schrieb:>> Ruediger A. schrieb:>> Man muss sich aber immer vor Augen halten, dass all diese Layers nicht>> (jedenfalls nicht primär) aus altruistischen Gründen (so wie dem>> Entwickler das Leben zu erleichtern) gemacht wurden, sondern um>> Geschäftsziele umzusetzen (Stichwort vendor lock in).>> Ja das liest man hier desöfteren. Aber der Vergleich hinkt, so lange du> keine Alternative vorweist, die herstellerunabhängig ist.
Welcher Vergleich?
Warum muss ich (oder irgendjemand Anders) eine Alternative vorweisen?
Die Frage war hier schlicht und einfach nach dem praktischen Wert der
STM HAL. Wie Viele Andere hier habe ich in der Praxis auftauchende
Probleme mit den HALs (also CMSIS, STMLib und der STM HAL) geschildert.
Daraus darf Jeder machen, was er/sie will. Wenn Dein Schluss daraus ist,
dass man (so interpretiere ich es jetzt erstmal) ja irgendwas nutzen
muss und dann eben die am Wenigsten schlechte Alternative nimmt - ist
erstmal legitim, ändert aber nichts an den potentiellen Problemen der
jeweiligen Layer (s.u.).
> Egal welche> sinnvolle Middleware ich nutze (dazu gehört mMn embed und Arduino nicht> dazu), ich bin an STM gebunden. Wer das nicht möchte und seine> Bibliotheken plattformunabhängig einsetzen möchte, der zieht eben nach> der STM-Middleware noch ein Abstraktionslayer ein und Dank LTO kostet> das exakt 0% Overhead.
Du meinst Link Time Optimierung ala Somnium? Wird der mir auch den
überflüssigen Timer ISR wegoptimieren? Automatisierte Optimierungen
können keine architektonischen Probleme lösen.
Mampf F. schrieb:>> Haben die STM32 nicht auch einen Bootloader schon eingebaut?
Die STM32 haben bootloader eingebaut. Die funktionieren auch, aber ich
will meinen Firmware file schützen durch crypten. Und das können die
nicht. Also selber schreiben.
W.S. schrieb:> Es gibt hier ganz viele Leute, die sehr fleißig all die XYZ_InitStruct's> ausfüllen, brav all die vielen dargebotenen Funktionen aufrufen, sich> ihre Einstellungen von Hilfszeugs wie Cube und so generieren lassen
Ist für Hobbybedarf ja auch OK, wenn man nur ein wenig basteln will.
Noch einen Schritt weiter in die Richtung geht dann gleich die
Arduino-Umgebung. Profis setzen das nicht ein, zumindest habe ich derlei
noch in keinem industriellen Projekt gesehen. Was wohl auch daher kommt,
daß man Leute, die ohne CubeMX nicht klarkommen, gar nicht erst
einstellt.
> Sie nehmen und kennen nix anderes als den Gcc und haben> keinen Begriff davon, wie andere Toolchains (z.B. Keil, IAR)> funktionieren.
Keil und IAR sind aber nur für Miniprojekte kostenlos und kosten
ansonsten schnell ein paar tausend Euro. Das würde ich privat auch nicht
ausgeben. Zudem spielt es auch keine wirkliche Rolle, weil Register an
absoluten Adressen sich mit GCC nicht anders beschreiben als mit Keil
und IAR. Die Syntax des Inline-Assemblers kann sich etwas unterscheiden,
aber das sind Bagatellen.
Zudem, wenn man privat Opensource-Projekte macht, dann ergeben Keil und
IAR keinen Sinn, weil das Projekt dann effektiv hinter einer Paywall
versteckt ist. Für Industrieprojekte ist hingegen entscheidend, daß man
bei Keil und IAR bei Bedarf schnell professionellen Support bekommt,
statt sich durch Foren zu wühlen.
Mich würde interessieren, welche Nachteile Du beim GCC siehst. Außer daß
er von sich aus den SVC nicht unterstützt und man das daher selber
reinbasteln muß, wenn man das benutzen will, was aber auch kein
Hexenwerk ist.
> wobei die Treiber> eine wirklich sinnvolle Schnittstelle nach oben hin haben sollen, also> funktional abstrahieren sollen.
Genau das! Und eben das leistet die HAL nicht, weil sie die Hardware
gerade nicht funktional abstrahiert.
Ich habe auch das Gefühl, dass die Hardware Abstraktion bei Arduino
deutlich gelungener ist, als bei Cube HAL. Und dass, obwohl ich ganz
sicher kein Fan von Arduino bin.
Cube HAL ist einfach nur klicki-bunti. Aber technisch nichts halbes und
nichts ganzes. Wetten, das wird spätestens in 5 Jahren wieder durch was
anderes angelöst?