Forum: Compiler & IDEs ARM Einstieg - 2 Fragen


von deep d. (deepdiver99)


Lesenswert?

Hallo!

Versuche mich gerade nach dem AVR in die ARM-Welt einzuarbeiten. Habe 
mir dazu das günstige STM32F4-Discovery Board zugelegt. Hätte da jetzt 
mal zwei Fragen.

1. Kann man wie beim AVR Variablen(const) im FLASH ablegen und zur 
Laufzeit auslesen? Hintergrund ist es RAM zu sparen das ich für andere 
Zwecke bräuchte.

2. Bei der GPIO Konfiguration gibt es das "GPIO port bit set/reset 
register (GPIOx_BSRR)" und das "GPIO port output data register 
(GPIOx_ODR)". Eigentlich würde doch eins von den beiden reichen?! Gibt 
es ein Grund warum ST dort diese zwei Register "angelegt" hat?

Viele Grüße Deepdiver99

von Norbert (Gast)


Lesenswert?

deep diver99 schrieb:
> Hallo!
>
> Versuche mich gerade nach dem AVR in die ARM-Welt einzuarbeiten. Habe
> mir dazu das günstige STM32F4-Discovery Board zugelegt. Hätte da jetzt
> mal zwei Fragen.
>
> 1. Kann man wie beim AVR Variablen(const) im FLASH ablegen und zur
> Laufzeit auslesen? Hintergrund ist es RAM zu sparen das ich für andere
> Zwecke bräuchte.

Problemlos.

> 2. Bei der GPIO Konfiguration gibt es das "GPIO port bit set/reset
> register (GPIOx_BSRR)" und das "GPIO port output data register
> (GPIOx_ODR)". Eigentlich würde doch eins von den beiden reichen?! Gibt
> es ein Grund warum ST dort diese zwei Register "angelegt" hat?

Atomic operation.

Steht aber alles im RM

von deep d. (deepdiver99)


Lesenswert?

Und wie geht's mit dem dem Flash?

Das "Note: For atomic bit set/reset, the ODR bits can be individually 
set and reset by writing to the
GPIOx_BSRR register (x = A..I/)." hab ich gelesen. Trotzdem leuchtet mir 
nicht ein warum 2 Register dafür da sind, wenn man mit beiden das 
gleiche Ergebnis erreichen kann.

von Norbert (Gast)


Lesenswert?

1)
static const


2)
Each I/O port bit is freely programmable, however the I/O port registers 
have to be accessed as 32-bit words, half-words or bytes. The purpose of 
the GPIOx_BSRR register is to allow atomic read/modify accesses to any 
of the GPIO registers.

In this way, there is no risk of an IRQ occurring between the read and 
the modify access.

von deep d. (deepdiver99)


Lesenswert?

Also ist der Zugriff über das BSRR-Register Interruptsicher :-).

Danke für deine Hilfe Norbert!

von deep d. (deepdiver99)


Lesenswert?

Noch ein Frage :-)

Gibt es beim STM32F4 ein Input Capture Timer wie beim AVR mit dem ich 
die Takte zwischen zwei Signale einer externen Quelle messen kann?
Bin aus dem ReferenzManual nicht so richtig schlau geworden.

von Norbert (Gast)


Lesenswert?

deep diver99 schrieb:
> Noch ein Frage :-)
>
> Gibt es beim STM32F4 ein Input Capture Timer wie beim AVR mit dem ich
> die Takte zwischen zwei Signale einer externen Quelle messen kann?
> Bin aus dem ReferenzManual nicht so richtig schlau geworden.

Klar, gibt es...

Sogar noch besser als beim AVR, der STM32F4 kann beim capture event 
einen DMA Request erzeugen und den Counter ohne CPU 
Intervention/Interrupt lesen und im Speicher ablegen. Und das kann er 
sauschnell mehrmals hintereinander.
Hab's noch nicht gebraucht, aber mein Bauchgefühl sagt mir locker im 
zweistelligen MHz Bereich.

vgl. RM0090 (Doc ID 018909 Rev 4) S.371ff  -  14.3.6 Input capture mode

von deep d. (deepdiver99)


Lesenswert?

Geht es auch ohne DMA so wie beim AVR das der Zähler dann in ein extra 
Register(am besten 32Bit :-) ) geschrieben wird?
Das mit DMA ist mir noch ne Nummer zu groß für den Anfang. Will jetzt 
erst mal eins zu eins das AVR Board auf das ARM übertragen.

von Norbert (Gast)


Lesenswert?

Ja, geht wie beim AVR auch ohne DMA.
Einfach nach dem capture event das Counter Register auslesen.
Ist aber nur 16bit ohne Tricks. ;-)

von deep d. (deepdiver99)


Lesenswert?

So hatte ich das auch schon raus gelesen. Ist denn das Counter Register 
auch das Register was hoch gezählt wird? Das wäre nämlich ungünstig da 
ich dann ja nicht die genaue Taktanzahl bekomme durch den zeitlichen 
Versatz bei der Eventauslösung.
Bei den 32Bit Timern geht das auch nicht? Und mit DMA? Würde mir gerne 
den Overflow Interrupt sparen :-).

von Norbert (Gast)


Lesenswert?

Ne, hab' mich unpräzise ausgedrückt.

Der jeweilige Zählerstand wird bei einem capture event in das 
entsprechende capture/compare Register transferiert und bleibt dort 
stehen bis zum nächsten capture event.

von deep d. (deepdiver99)


Lesenswert?

Ach so. Dann probiere ich mich heute Abend mal. Vielen Dank, würde mich 
gerne noch mal melden wenn ich nicht weiter komme :-)

von Joachim .. (joachim_01)


Lesenswert?

deep diver99 (deepdiver99)
> 2. Bei der GPIO Konfiguration gibt es das "GPIO port bit set/reset
> register (GPIOx_BSRR)" und das "GPIO port output data register
> (GPIOx_ODR)". Eigentlich würde doch eins von den beiden reichen?! Gibt
> es ein Grund warum ST dort diese zwei Register "angelegt" hat?

Sinngemäß würde ich sagen, daß es das gleiche ist; trotzdem macht sowas 
niemand ohne Grund. Vermutlich geht's wie üblich um den durch das 
Schreiben gelatchte Bit (GPIO port output data register) einerseits und 
um den echten Port-Zustand (GPIO port bit set/reset register 
(GPIOx_BSRR))andererseits.
Manchmal ist der kognitive Zusammenhang den Chip-Designer im Kopf haben 
für SW-Schreiber nicht auf den ersten Blick sichtbar;-) Bin aber kein 
Experte für STM, ich kenn' nur AT91SAM.

von LTC1043 (Gast)


Lesenswert?

deep diver99 schrieb:
> 2. Bei der GPIO Konfiguration gibt es das "GPIO port bit set/reset
> register (GPIOx_BSRR)" und das "GPIO port output data register
> (GPIOx_ODR)". Eigentlich würde doch eins von den beiden reichen?! Gibt
> es ein Grund warum ST dort diese zwei Register "angelegt" hat?

Der Hauptgrund wird wohl sein dass du so echte "bit set" und "bit reset" 
Funktionen hast . Stell dir mal folgendes vor, an deinm Port sind 16 
LEDs angeschlossen. Du willst nun LED0, LED1 ansteuern

GPIOx_ODR = 0x0003;  // Funktioniert wunder bar. Nun noch LED15 dazu...
GPIOx_ODR = 0x8000;  // Uupps nun leuchtet aber nur noch LED15

Also macht man üblicherweise:

GPIOx_ODR |= 0x8000;  // LED15 ansteurn, restliche LEDs belassen

Dies wird "read modify write" "rmw" genannt und dauert aber länger da 
nun gelesen, verodert und geschrieben werden muss

Hässlich wirds nun wenn dein TimerIrq regelmässig LED8 ansteuert und der 
IRq genau auftritt wenn der Read Part des "rmw" abgeschlossen ist. Das 
verodern bassiert dann auf alten Daten und die werden mit write 
geschrieben. Die LED8 aus dem Irq leuchtet also nicht. Die "rmw" sequenz 
ist also nicht "atomic".

Desshalb wird folgendes häufig angewendet:

Disable Irq
GPIOx_ODR |= 0x8000;  // LED15 ansteurn, restliche LEDs belassen
Enable Irq

Und nun wird das ganze nochmals länger und langsamer...

Moderne uC wie die STM32 bieten aber bessere Möglichkeiten, es können 
einzelne bits an den outputports gesetzt/gelöscht werden ohne die 
anderen zu beinflussen!

Du kannst also

GPIOx_BSRR = 0x0003;  // LED0, LED1 an
GPIOx_BSRR = 0x8000;  // LED15 noch dazu, LED0, LED1 beleiben an

Dein TimerIrq würde
GPIOx_BSRR = 0x0100;  // LED8 an

Löschen kannst du auf zwei verschiedne Arten
GPIOx_BSRR = 0x00030000;  // LED0, LED1 löschen, vorsicht muss im high 
word stenen
GPIOx_BRR = 0x8000;  // LED15 löschen

Das geht aber auch kombiniert
GPIOx_BSRR = 0x80000003;  // LED15 löschen, LED0 LED1 an

Fazit: Es gibt weniger Befehle und IO Operationen sind vereifacht.

Die Cortex M3/4 können das auch für das RAM machen, nennt sich "bit 
banding". Es gibt eine "Bitband Are"im Adressraum, welche das ganze 
interne SRAM bitweise ansprechen lässt. Somit lassen sich bit set bzw. 
bit clear befehle auf alle Variablen anwenden.

Cheers

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.