Forum: Mikrocontroller und Digitale Elektronik Maskierter Portzugriff auf ARM M4


von Tom (Gast)


Lesenswert?

Hallo,

ich versuche mich gerade an der Programmierung eines Stellaris Boards 
(LM4F120)

Bisher habe ich wie folgt auf die Ports zugegriffen:
1
#define GPIO_PORTF_DATA_R       (*((volatile unsigned long *)0x400253FC))
2
GPIO_PORTF_DATA_R=GPIO_PORTF_DATA_R^0x02

Nun gibt es aber laut Datasheet die Möglichkeit auf den Port maskiert 
zuzugreifen. Dazu muss ein Offset zur Basisadresse hinzugrechnet werden.
Ich habe nun folgendes probiert:
1
#define GPIO_PORTF_ready         (*((volatile unsigned long *)0x40025000+0x020))  //PF3
2
GPIO_PORTF_ready=0xff

Damit sollte eigentlich PF3 gesetzt werden, doch es passiert leider nix.
Kann mir jemand sagen was ich falsch mache?

Vielen Dank.

von Irgendwer (Gast)


Lesenswert?

Tom schrieb:
> #define GPIO_PORTF_ready         (*((volatile unsigned long
> *)0x40025000+0x020))  //PF3

Wo hast du denn die merkwürdigen Speicheradressen her?

Table 2-6. SRAM Memory Bit-Banding Regions:
0x4200.0000 - 0x43FF.FFFF Peripheral bit-band alias
The following formula shows how the alias region maps onto the bit-band 
region:
bit_word_offset = (byte_offset x 32) + (bit_number x 4)


Normalerweise gibt es doch eigentlich für jeden µC eine fertige include 
wo die ganzen define mit den Adressen drin sind so das man sich da nicht 
selbst was zusammen phantasieren muss?

von Tom (Gast)


Lesenswert?

so wie ich es verstanden habe ist die Basisadresse für den PortF
0x40025000 (APB)
Auf diese muss ein offset addiert werden um die entsprechenden Bits 
"freizuschalten"
Wenn ich nur Pin PF3 beschreiben möchte, müsste der Offset 0x20 sein.

Beschrieben hier auf dieser Seite:
https://filderbaer.wordpress.com/2014/12/30/2-gpio-programming/

Aus der kurzen Beschreibung im Datasheet bin ich leider nicht schlau 
geworden.

von Christian K. (the_kirsch)


Lesenswert?

Lad dir die CMSIS Header Dateien für deinen Kontroller runter, da sind 
alle Basisadressen definiert. (müssten diese sein: 
http://www.ti.com/tool/cmsis_dsp_headers)


Dann gibt es für jeden Port (und alle anderen Hardware Register) fertige 
Makros.

von Tom (Gast)


Lesenswert?

Ich bin Anfänger und nutze eine vorkonfigurierte Umgebung von Keil.
Daher habe ich nicht soviel Ahnung von Headerdateien.

Der Tip mit der CMSIS Headerdatei klingt gut.
Ich habe mir die Dateien cmsis_ccs.h und core_cm4.h angeschaut, aber ich 
kann dort keine Registerdefinitionen finden.
Vielleicht habe ich die falsche Datei heruntergeladen.

Ich denke, da muss mir jemand noch auf die Sprünge helfen.

von (prx) A. K. (prx)


Lesenswert?

Bitbanding genauer beschrieben: ARM Bitbanding

von Tom (Gast)


Lesenswert?

Die GPIOs haben scheinbar einen eigenen Bereich, der nicht im Bitbanding 
Bereich liegt.

von (prx) A. K. (prx)


Lesenswert?

Kenne das aus der Zeit als die noch Luminary Micro hiessen. Die hatten 
ARMs PrimeCell PL061 als GPIOs drin. Ist offenbar immer noch so.

Da gibts einen Bereich von 256 Worten, in denen die Adressbits 9:2 eine 
Maske für die Daten darstellen. Weshalb auch nur 8 GPIOs per Port drin 
sind.

In den fehlenden Klammern liegt der Fehler. Der Cast bindet stärker als 
die Addition, daher wird 0x20 zum Pointer addiert und folglich 
implizit mit 4 multipliziert. Es kam also die Adresse 0x40025080 statt 
0x40025020 raus. PF5 statt PF3.

Entweder vor dem Cast 0x20 draufaddieren, oder 0x08 danach:
1
#define GPIO_PORTF_ready (*((volatile unsigned long *)(0x40025000+0x20)))  //PF3
2
#define GPIO_PORTF_ready (*(((volatile unsigned long *)0x40025000)+0x08))  //PF3

Wie schon gesagt solltest du mal in den Headern graben und die dortige 
Definition zu diesem 256-Worte-Bereich auftreiben. Wenn der Bereich dort 
beispielsweise GPIOFUBAR heissen sollte und ungefähr so aussieht:
1
#define GPIOFUBAR ((volatile unsigned *)0x40025000)
dann kann man man das eleganter so formulieren:
1
#define GPIO_PORTF_ready GPIOFUBAR[1<<3]  //PF3

: Bearbeitet durch User
von Tom (Gast)


Lesenswert?

Vielen Dank.
jetzt funktioniert es erst einmal.
Dazu noch eine Frage: Ist die Art der Maskierung bei allen ARMs gleich, 
oder betrifft das nur die von TI?

Das mit den Headerdateien schaue ich mir noch an, da wird sicher noch 
die eine oder andere Frage aufkommen

von (prx) A. K. (prx)


Lesenswert?

Tom schrieb:
> Dazu noch eine Frage: Ist die Art der Maskierung bei allen ARMs gleich,
> oder betrifft das nur die von TI?

Das sieht bei jedem Hersteller völlig anders aus.
Nur das Bitbanding haben alle ARM ab CM3.

Die Cortex Cores enthält zusätzlich zum Prozessor ein paar weitere 
Bestandteile, wie Debugging, Systick, Interrupt-Controller und je nach 
Typ das Bitbanding. Aber das wars dann auch. Der Rest ist davon 
unabhängig.

Daneben bietet ARM einige PrimeCell genannte Funktionsmodule. GPIO, 
Timer, UART, DMA usw. Die können Hersteller ebenfalls nutzen, oder 
eigene Entwicklungen einsetzen. Die meisten haben Ansprüche, die über 
diese PrimeCells hinausgehen. Bei Luminary Micro fand ich jedoch einige 
davon.

: Bearbeitet durch User
von Felix C. (felix_c13)


Lesenswert?

Tom schrieb:
> (*((volatile unsigned long *)0x40025000+0x020))

(*(volatile unsigned int*) reicht ein long ist sowieso auch 32 Bit lang.

Irgendwer schrieb:
> Normalerweise gibt es doch eigentlich für jeden µC eine fertige include
> wo die ganzen define mit den Adressen drin sind so das man sich da nicht
> selbst was zusammen phantasieren muss?

Wieso denn nicht. Besser kann mit der Hardware kaum vertraut werden, als 
im Datenblatt die Register nachzuschlagen.

Tom schrieb:
> so wie ich es verstanden habe ist die Basisadresse für den PortF
> 0x40025000 (APB)
> Auf diese muss ein offset addiert werden um die entsprechenden Bits
> "freizuschalten"
> Wenn ich nur Pin PF3 beschreiben möchte, müsste der Offset 0x20 sein.

So ist es.

A. K. schrieb:
> Bitbanding genauer beschrieben: ARM Bitbanding

Wieso braucht der Junge denn bitte Bitbanding?

Tom schrieb:
> Die GPIOs haben scheinbar einen eigenen Bereich, der nicht im Bitbanding
> Bereich liegt.

Sicher? Arbeite zwar eigentlich mit STM32 aber das kann ich mir kaum 
vorstellen.

A. K. schrieb:
> Das sieht bei jedem Hersteller völlig anders aus.

Jo is bei STM32 zB völlig anders. Iwie einfacher, jedenfalls was ich auf 
die Schnelle gesehen habe. Lies dir hier 
malhttp://www.mouser.com/ds/2/405/lm4f120h5qr-124014.pdf

10.2 durch, da ist alles was de brauchst.

Tom schrieb:
> Ich bin Anfänger und nutze eine vorkonfigurierte Umgebung von Keil.
> Daher habe ich nicht soviel Ahnung von Headerdateien.

Wenn du Keil benutzt, mach folgendes um die Adressen herauszufinden:

1. Ätzende Variante über Macros. Geh bei den Makros zB GPIOB->DDR (oder 
wie die auch immer bei TI heissen) auf go to definition (also nen 
rechtsklick auf "DDR" oder "GPIO") und guck dir an was da passiert. Da 
kriegst du die Adressen dann.

2. Oder, weil ihr für Keil immerhin ne Menge Geld zahlt, grad deren 
Funktionen nutzen. Im Debugger auf Peripherals -> dein GPIO Port und 
dort stehen dann alle Register mit deren Adressen.

Gruss

Felix

: Bearbeitet durch User
von Irgendwer (Gast)


Lesenswert?

Felix C. schrieb:
> Wieso denn nicht. Besser kann mit der Hardware kaum vertraut werden, als
> im Datenblatt die Register nachzuschlagen.

Im Datenblatt nachschlagen und auch mal einen Blick in die header 
werfen, ja.
Aber deswegen braucht man die ganzen defines im eigene Quellcode nicht 
nochmal abzutippen.

von W.S. (Gast)


Lesenswert?

Tom schrieb:
> Der Tip mit der CMSIS Headerdatei klingt gut.
> Ich habe mir die Dateien cmsis_ccs.h und core_cm4.h angeschaut, aber ich
> kann dort keine Registerdefinitionen finden.
> Vielleicht habe ich die falsche Datei heruntergeladen.

Nein, der Tip namens CMSIS ist de facto SCHLECHT. Warum? Weil du 
zugedröhnt wirst mit Zeugs, das keiner braucht. Guck stattdessen lieber 
in das Referenzmanual zu deinem Controller. Ich benutze die von TI 
aufgekauften Stellaris selber nicht, also kann ich dir lediglich 
allgemeinere Hinweise geben, die bei vielen - ABER NICHT ALLEN - 
Arm-haltigen Controllern zutreffen:

1. für normale Portzugriffe gibt es Register zum gezielten Setzen 
(MYPORT_PSOR) und zum gezielten Löschen (MYPORT_PCOR) von Output-Pins.

2. für die von dir genannte maskierte Ausgabe gibt es ein Register für 
die Maske, wo für jedes zu ändernde Bit im Port ein Bit gesetzt sein muß 
(oder umgekehrt) und wo man dann, wenn die Maske im Register ist, 
einfaach sein Bitmuster auf den Gesamtport (dessen PIN-Register) 
ausgeben kann, ohne die von der Maske geschützten Bits zu versauen.

3. für jedes Bit im Port gibt es eine zweite Zugriffsadresse, die man 
wie eine Boolean-Variable behandeln kann. Je nach Hersteller ein bool 
oder ein longbool. Nennt sich Bitbanding.

W.S.

von (prx) A. K. (prx)


Lesenswert?

CMSIS selbst betrifft nur Core und NVic, also die cm* Files. Die 
herstellerspezifischen Definitionen für GPIO, Timer, ... finden sich in 
den cm* Files nicht.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Nein, der Tip namens CMSIS ist de facto SCHLECHT.

Wenn du irgendwelche Libraries meinst bin ich dabei. Aber die 
Definitionsdateien für Adressen und Bits will man nicht unbedingt selber 
eintippen, wenn vermeidbar.

von Christian K. (the_kirsch)


Lesenswert?

W.S. schrieb:
> Nein, der Tip namens CMSIS ist de facto SCHLECHT. Warum? Weil du
> zugedröhnt wirst mit Zeugs, das keiner braucht

Da verwechselst du CMSIS mit der Cube-HAL

CMSIS sind nur defines und typedefs

A. K. schrieb:
> CMSIS selbst betrifft nur Core und NVic, also die cm* Files. Die
> herstellerspezifischen Definitionen für GPIO, Timer, ... finden sich in
> den cm* Files nicht.

Jain

Die CMSIS besteht aus zwei Teilen.
Der erste Teil kommt von ARM und enthält Definitionen für Core und NVic
Der zweite Teil kommt vom Hersteller des SoC und enthält 
Registerdefinitionen für die Peripherie

: Bearbeitet durch User
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.