Hallo miteinander,
den Einstieg in die STM32 Welt habe ich erst mal geschafft. Als
Testboard dient das Discovery zusammen mit Yagarto und traditionellen
makefile's. Zum Debuggen nehme ich den st-link gdb server und Eclipse.
Die lite Version von Atollic habe ich auch probiert, ist mir aber doch
zu sehr beschränkt.
Allerdings stehe ich mit den STM32F10x_StdPeriph_Driver'n ein bischen
auf Kriegsfuß. Am Anfang sieht das ja ganz nett aus. Wenn man dann aber
die Doku zum Stm32 durcharbeitet lernt man die Register kennen. Und
sieht sie auch schön im Debugger. Wenn ich einfache Ports z.B. mit der
Lib programiere, dann fehlt mir irgendwo am Ende die Sicht auf die
Register. Und der Code wird auch aufgebläht. Das ist mir jedenfalls zu
fett in einigen Beispielen, wenn für die 2 Leds neben der Lib auch noch
die STM32vldiscovery.c benutzt wird. Da sieht man dann die Leds schön
blinken, zum Verständnis des Controllers trägt das aber nicht bei.
Deshalb hier die Frage: Programmieren alle nur mit dieser Lib oder gibt
es auch Verweigerer? Was ist ohne diese Lib nur umständlich zu lösen?
Was fragst du hier nach? Du hast doch für dich schon entschieden, das
dir die LIBs nicht gefallen. Also können jetz 1000 Leute schreiben
"Mensch sind die toll, weil [...]"...du würdest bei deiner Meinung
bleiben.
Ansonsten gibts hier auch ne Suche...
Juergen schrieb:> Allerdings stehe ich mit den STM32F10x_StdPeriph_Driver'n ein bischen> auf Kriegsfuß. [...]
Damit bist du nicht allein. Die Lib führt zudem zu mehr erforderlicher
Doku, denn mit der Doku der Lib ist es meist nicht getan, die
Register/Funktions-Doku braucht man trotzdem.
> es auch Verweigerer? Was ist ohne diese Lib nur umständlich zu lösen?
In manchen Fällen kann man sie als Hinweis nehmen. Als Beispielcode. Und
bei sehr komplexer Peripherie wie CAN oder USB kann sie nützlich sein.
Also, immer schön ruhig bleiben. Ich habe gerade den Einstieg durch und
nicht die ganze Peripherie. Meine Entscheidung ist auch noch nicht
endgültig getroffen. Und meine Frage war: "Was ist ohne diese Lib nur
umständlich zu lösen". Ich dachte ich kann von den Erfahrungen anderer
lernen ohne angemacht zu werden!
Die Lib hat mit ihrer Favorisierung von Structs eine Aufrufkonvention,
die wohl geistig von anderen Controllern wie 8-Bittern abstammt, die
aber bei ARMs umständlich, zeitraubend und zeilenfressend ist.
So erschliesst sich mir nicht, weshalb man für GPIO-Inits derart viele
Zeilen benötigt, wie sie die Lib frisst. Sieht bei mir so aus:
Übersichtlich, kurz, kompakt, wartbar, ohne Driver Library, und man kann
es leicht in andere Projekte übernehmen ;-)
Fertige Libs verwende ich nur bei komplexen Sachen wie TCP/IP, USB,
SD-Karte.
VG,
/th.
Mit dem Ansatz hätte ich ein Problem, denn der funktioniert nur, wenn
man sämtliche GPIO-Configs eines Ports an einer Stelle zusammen zieht,
auch wenn die Pins zu 5 verschiedenen Funktionsmodulen gehören.
Will man das hingegen modularisieren, d.h. die Port-Inits in das Modul
packen, das die jeweiligen Pins tatsächlich verwendet, dann funktioniert
dieser Ansatz nicht mehr so einfach.
Ausserdem erschwert es symbolische Namen für die Portpins.
Random ... schrieb:> funzt auch ausserhalb noch genau so gut:
Das setzt voraus, dass in CRx vorher 0 drin steht. Tut es ab Reset aber
nicht.
> und ebenfalls mit symbolischen Namen:
Nicht ganz, denn die Unterscheidung CRH/CRL muss da noch rein, abhängig
von der Bitnummer. Sonst ist der Ärger vorprogrammiert.
Deine ODR-Manipulation ist nicht Interrupt-fest. BSRR/BRR statt ODR
empfohlen.
> Das setzt voraus, dass in CRx vorher 0 drin steht.> Tut es ab Reset aber nicht.gnarff das hab ich mir jetzt verkniffen, weil ich es als bekannt
vorrausgesetzt hab und es nur ums Prinzip ging:
> Nicht ganz, denn die Unterscheidung CRH/CRL muss da noch rein,> abhängig von der Bitnummer.
Klar, etwas denken muss man dabei noch, das nimmt einem auch die beste
DriverLib nicht ab!
Dann sollte man da aber eher nen Function call draus machen, mit
if(pin<8) {CRL=...} else {CRH=...}. Diese Transferleistung hab ich aber
den Lesern dieses Threads überlassen, ich wollte nur auf die
Möglichkeiten hinweisen.
Ausserdem kann man mit dieser Lösung (mit etwas Nachdenken) alle
benötigten PINs (nach CRL/H, ob nun Eingang, Ausgang oder
AlternateFunction) eines Ports in einem Schwung gemeinsam setzen,
während eine Unterscheidung nach CRL und CRH nur das Setzen eines
Portpins zulassen würde (vielleicht einer Liste, das wäre dann eine
Schleife).
Mit dieser Lösung kann man das sehr geschickt und übersichtlich bündeln.
Z.B. brauche ich für SPI 4 Pins, 2 als GPIO OUT und 2 als
AlternateFunction (MOSI, SCK), alle aus CRH.
> Deine ODR-Manipulation ist nicht Interrupt-fest.> BSRR/BRR statt ODR empfohlen.
Warum ist ein 16Bit Zugriff auf dem Cortex-M3 nicht Interrupt-fest?
Hallo Jürgen,
wahrscheinlich hat kaum einer (öffentlich) mehr über diese Lib geflucht
als ich. (siehe hier: Beitrag "Literatur für ARM-CORTEX-M3" )
Im endeffekt mach ich es mittlerweile so, dass ich die Lib hernehme um
etwas zum laufen zu bringen und nach und nach dann den code selber
nachschreibe. Um es kurz zu sagen, für erste schritte ganz okay, aber
für mehr würde ich die nicht verwenden.
Gruß Tarkan
Vielen Dank an alle. Ich denke ich werde die lib nur zum Lernen benutzen
und beim Selberschreiben der Register den STM32 am besten kennen lernen.
Interessant wäre es ja, wenn es für die häufigsten Aufgaben (GPIO,
USART, SPI) eine Lib geben würde die sowohl den stm32 als auch andere
Cortex M3 Controller unterstützt.
Tarkan D. schrieb:> Im endeffekt mach ich es mittlerweile so, dass ich die Lib hernehme um> etwas zum laufen zu bringen und nach und nach dann den code selber> nachschreibe.
Ich mache es genauso.
Random ... schrieb:> Warum ist ein 16Bit Zugriff auf dem Cortex-M3 nicht Interrupt-fest?
Weil
ODR |= 0x01
nicht ein Befehl ist, sondern bezogen auf ODR zwei:
Ra = ODR
Ra |= 0x01
ODR = Ra.
Das sieht in der Praxis irgendwann so aus:
R1 = ODR ; Bit 0,1=0
R1 |= 0x01
R2 = ODR ; ISR setzt Bit 1
R2 |= 0x02
ODR = R2
ODR = R1 ; Bit 0=1, Bit 1=0
Bit 1 ist nun wieder im Zustand vor der ISR.
Mehmet Kendi schrieb:> Ich habe jetzt mal den Code von A.K. etwas studiert.> Sehr clever. Werde ich mir merken!!
Wenn man diese Funktionen inlined, dann dampft zumindest GCC sie zudem
pro Aufruf netto auf diese 4 Befehle
Ra = CRx
Ra &= const1
Ra |= const2
CRx = Ra
ein. Was auch nicht länger ist als der Aufruf.
Juergen schrieb:> Interessant wäre es ja, wenn es für die häufigsten Aufgaben (GPIO,> USART, SPI) eine Lib geben würde die sowohl den stm32 als auch andere> Cortex M3 Controller unterstützt.
Da die UARTs verschiedener Familien verschieden sind, sind die
Implementierungen von Treibern für die UARTs notwendigerweise auch
verschieden. Gemeinsam können sie nur die Schnittstelle nach aussen
haben. Und da liegt der Hase im Pfeffer: Wie muss diese aussehen?
Darüber würden sich Komitees so lange streiten, bis ein Monster
rauskommt, das niemand verwendet.
Folglich gibts sowas öffentlich de fakto nur auf sehr hoher Ebene in
Form von Betriebssystemen.
ST hätte das allerdings für deren verschiedene Controller-Familien wie
STM8 und STM32 machen können (sollen), das hätte sich m.E. als
Argument angeboten. Ist natürlich nur mit begrenzter Grundfunktion
sinnvoll, damit alle Hardware-Funktionen voll abzudecken wäre zu gross
und zu unübersichlich geworden, aber grad bei UART gibts eine klare
Grundfunktionalität. Die vorhandenenen Libs sind ja wenig mehr als
Wrapper um die Register, ein relativ übersichtlicher UART-Support mit
Pufferung und ISR hätte sich da angeboten.
Was nicht heisst, dass man sich das nicht selber stricken kann. So mache
ich das. Wie beispielsweise ein Treiber für UART, mit sehr ähnlichem
Interface bei LPC2000, STR9, STM32. Ebenso CAN für AVR/MCP2515, LPC2000,
PIC16, STM32.
Das lohnt sich aber nur, wenn sich ein einheitliches Interface nach oben
anbietet und die Varianz der Funktionalität der Hardware sich verbergen
lässt. Bei SPI scheint mit das eher zweifelhaft. Auch bei GPIO lohnt
sich das eigentlich nur für die Port-Init. Bei CAN lassen sich die sehr
unterschiedlichen Komplixitäten bei der Filterung aber nicht gut
verbergen.