Hallo Zusammen,
In den Vorüberlegungen für ein vmtl. doch recht umfangreich werdendes
Projekt mit nem STM32 hat sich mir die Frage aufgeworfen, ob man besser
die HAL (aus dem STM32Cube-Bündel) oder libopencm verwendet oder direkt
in den Registern rumstochert.
HAL
+ Umfassende Unterstützung aller Peripherieeinheiten
- gewöhnungsbedürftige API (wenn man POSIX gewöhnt ist)
1
GPIO_InitTypeDefGPIO_InitStruct;
2
GPIO_InitStruct.Pin=GPIO_PIN_0;
3
GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
4
GPIO_InitStruct.Pull=GPIO_NOPULL;
5
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
- Fragwürdige Lizenz im Zusammenhang mit OSS-Projekten (auf einigen
Seiten von ST steht was von wegen BSD, in den Quellen selber nicht)
- Nur mit dem CubeMX-Codegenerator gut zu verwenden
- Abstraktion, ein Problem mehr (Feature im Datenblatt gefunden,
wie mach ich's mit der HAL?)
libopencm
+ schöne API
- eigene Registerdefinitionen
- nicht vollständige Unterstützung aller Peripherieeinheiten
Registerzugriff
+ sehr gute Dokumentation (Reference Manual)
- umständlich
Für große Peripherieeinheiten, wie z.B. USB führt natürlich kein Weg an
der HAL und der Middleware von ST vorbei.
Was sind eure Meinungen und Erfahrungen dazu?
Lukas
holger schrieb:> Wird libopencm überhaupt noch gepflegt?> Selbst die einfachsten Sachen sind da ja noch rot markiert.
Der letzte Commit war vor 3 Monaten, ganz tot isses wohl noch nicht,
aber lebendig sieht auch anders aus.
Lukas K. schrieb:> - gewöhnungsbedürftige API (wenn man POSIX gewöhnt ist)
Wie sieht denn das POSIX-API zum Konfigurieren von Pins aus? Wie sähe
denn ein nicht-gewöhnungsbedürftiges API aus (ernst gemeinte Frage)?
Keine Structs mit bescheuerten Namen (GPIO_InitTypeDef ?!) ausfüllen und
an eine Funktion übergeben. Principle of least surprise und so
Beim API-Design sollte man sich IMO an vorhandenem orientieren und nicht
mit was vollkommenem anderen anfangen (oder machen das mit structs als
kwargs für arme noch andere so?)
Wahrschein's wollte ST damit das Fehlen von keyword-args in C
kompensieren, denn Funktionen wie die oben von libopencm sind sehr
anfällig gegen vertauschen von Parametern.
Lukas K. schrieb:> denn Funktionen wie die oben von libopencm sind sehr> anfällig gegen vertauschen von Parametern.
In der Tat, beim CAN zB wären es schlappe 11 Parameter - da ist der
struct doch lesbarer, weil immerhin Namen dranstehen und man halbwegs
erahnen kann was die Parameter bedeuten?! Und wenn du mit C++11
kompilierst kannst du immerhin sowas machen:
PS: Oohps, kann man nicht, die Funktionen wollen Pointer.
Aber man kann 1 struct an mehrere Aufrufe der jeweiligen Funktion
übergeben, um zB 10 Pins mit den selben Einstellungen zu initialisieren.
Spart auch etwas Code.
Lukas K. schrieb:> Für große Peripherieeinheiten, wie z.B. USB führt natürlich kein Weg an> der HAL und der Middleware von ST vorbei.
Wiebitte???
Ich halte das für Unsinn. Den Gegenbeweis hatte ich mir vor einiger Zeit
selbst gegönnt und mir einen virtuellen COM (als device) selber
geschrieben. Das ist auf lange Sicht wesentlich angenehmer und
praktikabler als das von ST vorgefertigte Zeugs. Letzteres ist nämlich
keine echte Erleichterung für den Programmierer, weil es keine echten
Treiber sind, sondern nur ein die Hardware umschreibendes Zeug ist, so
daß man als Programmierer zuletzt ja doch wieder alles selber machen
muß.
Gleiches gilt auch für das SD-Karten Interface.
Lukas K. schrieb:> Registerzugriff> + sehr gute Dokumentation (Reference Manual)> - umständlich
Ich halte das überhaupt nicht für umständlich, allerdings stehe ich auch
auf dem Standpunkt, daß man sich selbst seine Low-Level-Treiber
schreiben sollte, in deren Interface (also der zugehörigen .h) kein
Hardwarebezug mehr stehen darf. Also nicht ein Treiber, der Port1.Pin7
auf Hi setzt, sondern einer der "Maschine_kleine_Fahrt_vorwärts" macht,
also sein Interface auf der logischen Anwendungsebene hat.
W.S.
Dr. Sommer schrieb:> um zB 10 Pins mit den selben Einstellungen zu initialisieren.
Kann libopencm auch. gpios ist ne bitmaske
Dr. Sommer schrieb:> In der Tat, beim CAN zB wären es schlappe 11 Parameter
Bei komplexeren Peripherieeinheiten hat libopencm dann mehrere
Funktionen, um diese zu initialisieren.
Auch wenig schön an der HAL ist, dass es nicht vorgesehen ist, einzelne
Parameter der Peripherie zu ändern. Entweder alles initialisieren, oder
gar nichts.
W.S. schrieb:> Hmm.. merkst du noch was?
Ja, vergessen dass die Funktionen Pointer wollen und keine "const T&"
(dann würde es gehen). Ist halt C. egal.
Lukas K. schrieb:> Dr. Sommer schrieb:>> um zB 10 Pins mit den selben Einstellungen zu initialisieren.>> Kann libopencm auch. gpios ist ne bitmaske
Na hoffentlich gilt das für alle anderen Periphals auch, also alle 3
SDADC's mit einem Befehl initialisieren oder Pins aus GPIOA und GPIOB
ohne alle Parameter zigmal hinzuschreiben etc.
Wenn Du experiementierfreudig bist, kannst Du NUT/OS
http://www.ethernut.de/ einsetzen. Im Sourceforge Trunk habe ich einiges
fuer STM32 gemacht und verwende es fuer Projekte bei der Arbeit.