Forum: Mikrocontroller und Digitale Elektronik STM32 HAL versus CMSIS


von Stefan F. (Gast)


Lesenswert?

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?

von pegel (Gast)


Lesenswert?

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.

von Kirsch (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von pegel (Gast)


Lesenswert?

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.

von pegel (Gast)


Lesenswert?

Ü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.

von Horst (Gast)


Lesenswert?

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.

von Martin B. (ratazong)


Lesenswert?

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.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch User
von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

> 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.

von Martin B. (ratazong)


Lesenswert?

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. . . .

von Mampf F. (mampf) Benutzerseite


Lesenswert?

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 ...

von Martin B. (ratazong)


Lesenswert?

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.

von avr (Gast)


Lesenswert?

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.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

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 :-)

von W.S. (Gast)


Lesenswert?

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.

von Martin B. (ratazong)


Lesenswert?

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.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

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?

: Bearbeitet durch User
von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von Martin B. (ratazong)


Lesenswert?

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.

von Nop (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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?

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
Noch kein Account? Hier anmelden.