Forum: Mikrocontroller und Digitale Elektronik Peripherie-Aufteilung beim STM32F407?


von Norbert G. (realist_50)


Lesenswert?

Hallo,

als langjähriger Nutzer von BASCOM AVR (Programmierung von Atmel 
8-Bit-Controllern unter BASIC - wobei ich aber über das Stadium eines 
Hobbyprogrammierers nie hinaus gekommen bin, d.h. ich habe z.B. nie 
irgendwelche zusammengesetzten Datentypen ("struct") benutzt, weil ich 
diese nie gebraucht aber auch nie verstanden habe - will ich jetzt 
endlich auf ARM-Controller umsteigen. Es war zu erwarten, dass trotz 
intensivster Bemühung meinerseits die Programmiersprache C und mit ihr 
auch die Entwicklungsumgebung CoIDE (mit dem GCC-Compiler), von der hier 
viel geschrieben wird, leider, leider nicht an mich gehen; ich blicke da 
einfach nicht durch. Das bedeutet, dass ich mit den zahlreichen, gut 
gemeinten und aufwändig geschriebenen ARM-Tutorials, wie ich sie hier im 
Forum gefunden habe, kaum etwas anfangen kann.

Ich habe aber eine sehr schöne Entwicklungsumgebung in BASIC gefunden, 
nämlich MikroBasicPro for ARM (gibt's auch in Pascal und C), die bei 
Bedarf auch ohne die ganzen komplizierten Strukte auskommt. Man kann 
z.B. jederzeit jedes beliebige Register mit einem einfachen Integerwert 
erreichen. Unter CoIDE ist mir das nicht gelungen, weil dort die 
Register gar nicht einzeln unter den im Manual verwendeten Namen 
definiert sind. Stattdessen kann man dort nur unter Zuhilfenahme 
spezieller Funktionen, deren Namen und Variablen man erst mal kennen 
muss, auf die Register zugreifen - was für mich als "Hardware-Mensch" 
immer undurchschaubar blieb. Da aber MikroBasicPro meinem geliebten 
BASCOM auch strukturmäßig ziemlich ähnlich ist und zudem ohne jenes 
endlose und für mich völlig unüberschaubare Einbinden unzähliger 
#include-Dateien auskommt, kam ich damit auf Anhieb gut zurecht. Somit 
scheint zumindest vorläufig die Compilerfrage gelöst. Das nur mal vorab 
zur Einschätzung meiner "Fähigkeiten" als Programmierer.

Hingegen traue ich mir hardwaremäßig wesentlich mehr zu. Nachdem die 
ersten Gehversuche mit einem STM32F407-Discovery-Modul ganz gut geklappt 
haben, will ich für eine erste konkrete Anwendung eine eigene Platine 
mit einem STM32F407VET bauen. Für das Projekt benötige ich 10 bis 12 
digitale Eingänge (für Taster), einen 8-Bit-A/D-Wandler (nebst Timer und 
Interrupt-Steuerung für ca. 350000 Samples pro Sekunde), einen 
D/A-Wandler für die Ausgabe von NF bis 8 kHz (nebst Timer), ein externes 
DRAM mit mindestens 4 Megabytes, eine Micro-SD-Card als Massenspeicher, 
ein USART (mit externem USART/USB-Konverter (z.B. FT232RL) zwecks 
Emulieren eines Virtuellen COM-Ports im PC, und eine batteriegepufferte 
Echtzeituhr. Auf die Verwendung eines der beiden USB-Module, die der 
STM32F407 bietet (anstelle der USART-Schnittstelle), will ich 
verzichten, weil ich von USB absolut keine Ahnung habe, bzw. weil ich 
beim Durchlesen der diesbezüglichen Abschnitte nur noch Bahnhof 
verstanden habe.

Mein Problem ist folgendes: Bei all der Fülle an Peripherie, die der 
STM32F407 bietet, bin ich bei der Frage, welches der einzelnen 
Komponenten ich letztendlich verwenden soll, vollkommen überfordert. 
Trotz intensiven Studiums des 1700 Seiten starken Reference Manuals 
nebst 178 Seiten Datenblatt fürchte ich nämlich, bei der Auswahl dieser 
Module grobe Anfängerfehler zu machen. So finde ich bei der Betrachtung 
der Alternate Functions Liste (Datenblatt, Table 9 auf den Seiten 60-68) 
z.B. 4 USARTs und 2 UARTs, außerdem 7 SDIOs (von denen ich wohl 2 Stück 
für die SD-Card und das DRAM brauche), 11 Timer usw. Dazu sehe ich eine 
Mehrfachbelegung mancher Anschlusspins, z.B. durch die unverzichtbaren 
SWD-Programmieranschlüsse, durch die beiden MCO-Taktausgänge, die ich 
fürs Debuggen gerne erhalten würde und sogar durch teilweise Überlappung 
gleichartiger Module. Ich frage mich also:

Ist der STM32F407 insofern streng "orthogonal" so dass all diese Module 
tatsächlich nebeneinander gleichberechtigt sind? Nur in diesem Fall 
könnte ich unter Vermeidung von Doppelbelegungen frei nach der 
Verfügbarkeit entscheiden. Oder ist es eher so, dass manche dieser 
Peripheriemodule gegenüber anderen zu bevorzugen sind, z.B. weil diese 
universeller sind oder weil dadurch andere wichtige Möglichkeiten 
verloren gehen?

Kann mir jemand einen Tipp für eine möglichst sichere, vielleicht sogar 
allgemein übliche Verwendung der von mir benötigten Peripheriemodule 
geben?

von Uwe B. (derexponent)


Lesenswert?

Also 7 SDIO hat der STM32F407 sicher nicht :-)

und Timer sind es sogar 14 (nicht 11)

es gibt eine schöne Übersicht im UserManual vom STM32F4-Discovery
da ist die CPU als Blockdiagramm gezeichnet mit allen "internen" Teilen

und zu deiner Frage :

da es sich das ganze Projekt etwas umfangreich anhört, würde ich
gar nicht mit einer eigenen Platine anfangen, sondern
das Discovery benutzen bis alle Teilfunktionen einzeln
auf einem "Breadboard" laufen

also :

1. UART
2. ADC
3. DAC
4. SD-Karte

usw

und wenn jedes Teil einzeln läuft, kannst du dich
an das erstellen deiner Platine wagen
und die benötigten CPU Pins entsprechend "aufteilen"

spätestens dann weißt du z.B. auch das der DAC nur an zwei Pins benutzt 
werden kann aber es 20 RX/TX-Pins gibt (und alle UARTs gleich 
funktionieren)

also...das ganze schritt für schritt angehen sonst geht es in die Hose

Gruss Uwe

von m.n. (Gast)


Lesenswert?

Uwe B. schrieb:
> da es sich das ganze Projekt etwas umfangreich anhört, würde ich
> gar nicht mit einer eigenen Platine anfangen, sondern
> das Discovery benutzen bis alle Teilfunktionen einzeln
> auf einem "Breadboard" laufen

> also...das ganze schritt für schritt angehen sonst geht es in die Hose

Dem kann ich voll zustimmen.
Du schreibst von DRAM, wobei ich nicht weiß, welches Du verwenden 
möchtest. Da würde ich zu einem STM32F429-Disco-Board raten. Der F429 
hat einen SDRAM-Controller und das recht günstige Disco-Board ein SDRAM 
mit 8MB. Das vorhandene Display kannst Du außer Acht lassen.

Wegen der IO-Belegung drucke Dir am besten die Tabelle aus dem 
ref-Manual aus und plane mit einem Bleistift die Verwendung der Pins. 
Die SWD-Pins sind keine Verschwendung sondern ein Segen, um selbst im 
Zielsystem noch entwickeln zu können.

von Norbert G. (realist_50)


Lesenswert?

Hallo Uwe,

herzlichen Dank für Deine Antwort! Du hast natürlich Recht; der 
STM32F407 hat nur einen SDIO. Ich hatte nicht richtig hingesehen und den 
Eintrag "SDIO_D7" für das 7. SDIO-Modul gehalten...

Das von Dir erwähnte Blockdiagramm im Discovery-Manual habe ich 
gefunden. Bei all den anderen, dickleibigen Infoquellen, mit denen ich 
inzwischen zu tun hatte, hatte ich dieses längst aus den Augen verloren.

Auch hinsichtlich des Breadboards hast Du wahrscheinlich Recht. Meine 
Überlegung war nur die, dass ich für die benötigten externen 
Peripherie-Bauteile (FT232RL, DRAM, Steckfassung für die Micro-SD-Card) 
- die ja alle nur in feinen SMD-Gehäusen erhältlich sind - ohnehin eine 
(teure) Musterplatine anfertigen lassen muss. Und wenn ich das schon 
mache, dann kann ich doch auch gleich noch einen STM32F407 draufsetzen 
und bin dann vom Discovery-Modul (mit all dem darauf befindlichen 
Spielzeug, das ich nicht brauche und das nur unnötig IO-Pins belegt) 
unabhängig.

Aber beim derzeitigen Stand der Entwicklung und in meiner Situation als 
absoluter ARM-Anfänger gibt es wohl tatsächlich noch viel zu viele 
Unwägbarkeiten. Dabei bin ich beim "In-die-Seile-Hängen" allerfeinster 
vielpoliger SMD-ICs mithilfe dünner CuL-Drähtchen über einer groben 
Versuchsplatine durchaus nicht ungeübt. Doch weil das (mit meinen 64 
Jahren) wirklich nicht mehr so ganz einfach ist, werde ich erst mal 
versuchen, eine selbst geätzte Platine nur mit den nackten ICs (zzgl. 
Stützkondensatoren) zu erstellen und die Signalleitungen (soweit nicht 
völlig klar) über ordentliche Lötaugen von Hand verdrahten.

Viele Grüße

Norbert

von Dr. Sommer (Gast)


Lesenswert?

Norbert Graubner schrieb:
> Unter CoIDE ist mir das nicht gelungen, weil dort die
> Register gar nicht einzeln unter den im Manual verwendeten Namen
> definiert sind.
Doch, du musst nur #include <stm32f4xx.h> schreiben. Wenn du tatsächlich 
unbedingt direkt auf die Register schreiben willst...

Man kann auch C erst am PC mit Büchern lernen, das geht ganz gut und 
dann kann man's. Aber egal.

Es gibt von ST das Programm microXplorer (scheinbar jetzt in STM32CubeMX 
umbenannt?!), das ist ungemein hilfreich dabei eine Pinbelegung 
festzulegen bei der sich keine Pins überschneiden.

Und wenn du DRAM verwenden willst, solltest du einen STM32F429 
verwenden, der hat einen DRAM-Controller.

von Norbert G. (realist_50)


Lesenswert?

Ein Hallo an den Gast, der mir soeben auch geantwortet hat!

Das 427-Disco-Board mit dem Display und dem 8-MB-DRAM habe ich bereits 
(zusätzlich zu dem 407-Discovery-Board). Ich habe mich bisher nur nicht 
dran getraut (es war mir sozusagen "heilig"), weil ich das schöne, 
anspruchsvolle Grundprogramm mit dem Touch-Display nicht löschen wollte. 
Es hat mir aber inzwischen jemand verraten, wo ich die Original-Firmware 
finde, so dass ich diese notfalls wieder einspielen kann.

Weil ich aber fürs Debuggen zuallererst eine Virtuelle COM-Schnittstelle 
haben möchte (so kenne ich das von BASCOM her), nützt mir dieses 
Disco-Board erst mal nicht allzu viel. Erst wenn ich etwas fitter 
geworden bin, werde ich mich näher mit der SWD-Schnittstelle auseinander 
setzen können. Ich habe beobachtet, dass z.B. die Entwicklungsumgebung 
CoIDE (mit dem GCC-Compiler) beim Debuggen direkt auf das Board zugreift 
- das wäre dann wohl der Zugriff auf den Controller. Aber mit CoIDE 
komme ich nicht zurecht und mein MikroBasicPro hat leider nur einen 
Simulator - da bleibt dann fürs echte Debuggen nur die Serielle 
Schnittstelle. Dass die Anschlüsse für die SWD-Schnittstelle zwingend 
notwendig sind, ist mir durchaus klar.

Viele Grüße

Norbert

von Dr. Sommer (Gast)


Lesenswert?

Norbert Graubner schrieb:
> Ein Hallo an den Gast, der mir soeben auch geantwortet hat!
Hallöchen ;-)

Debuggen mit SWD und einem "richtigen" Debugger wie in CooCox ist extrem 
hilfreich, damit kann man sehr gut mit wenig Aufwand genau betrachten 
was das Programm so macht, oder wo genau ein Crash passiert ist. 
Debuggen mit Ausgaben über die Serielle Schnittstelle dagegen ist 
ziemlich mühselig und bei Crashes eher Stochern im Dunkeln...

An das F429 Discovery Board kannst du dir wie bei allen anderen 
Mikrocontroller-Boards doch leicht einen TTL-UART -> USB Adapter (wie zB 
ebay 271361620831) dranhängen und darüber deine Ausgaben machen.

von Norbert G. (realist_50)


Lesenswert?

Hallo Dr. Sommer!

natürlich habe ich das mit allen möglichen #include-Direktiven versucht 
- auch mit #include <stm32f4xx.h>!

Ich habe es soeben nochmal überprüft. Obwohl diese Anweisung oben drin 
steht, kommt bei CoIDE bei der Zuweisung

// PLLQ = 7, HSE to PLL, PLLP1 = 2, PLLN = 336, PLLM = 8:
   RCC_PLLCFGR = 0x07405408;

die folgende Fehlermeldung:

4: error: 'RCC_PLLCFGR' undeclared (first use in this function) 
'

Dabei ist ein Register mit genau dieser Zeichenfolge im Reference Manual 
enthalten und wird z.B. auch von MikroBasicPro so akzeptiert.

Was das Erlernen von C am PC betrifft: Das habe ich seit ziemlich genau 
25 Jahren (zuerst mit Borlands Turbo C) in mehreren, wirklich ernst 
gemeinten Anläufen immer wieder vergeblich versucht. Diese Sprache mit 
ihren völlig uneinsichtigen Kürzeln (und vor allem: mit ihren Tücken!) 
finde ich derart grauenvoll, dass sie einfach nicht an mich geht. Wie 
schön ist doch dagegen eine strukturierte Sprache wie Pascal - das liest 
sich beinahe wie Klartext! Und das noch mit sauberen Typprüfungen, die 
Anfängerfehler erst gar nicht zulassen! Und dass das klassische C nicht 
einmal den Datentyp String kennt (so dass man das alles höchst mühsam 
über Zeigerarithmetik und Funktionen implementieren muss), empfinde ich 
inzwischen nicht nur verwirrend, sondern zunehmend auch unzeitgemäß.

Ich denke inzwischen, dass die Fähigkeit, die Sprache C zu begreifen, in 
erster Linie eine Mentalitätsfrage ist. Ich bin ein sehr konkret und 
real denkender Mensch; ich muss alles unmittelbar einsehen und die 
Zusammenhänge, bzw. Abläufe begreifen (im Sinne von Anfassen) können. 
Mit Abstrahierungen und "Structen" wie ich sie vor allem unter C immer 
wieder sehe (zuletzt bei SiSy ARM und auch bei CoIDE) (es scheint unter 
C-Programmierern geradezu eine Lust zu sein, alles, was nicht 
unmittelbar zum Problem gehört, zu verstecken oder zu abstrahieren um so 
angeblich die Lesbarkeit zu verbessern ...) verliere ich SOFORT den 
Boden unter den Füßen (daher z.B. auch mein Wunsch, selber auf die 
Register des Controllers zugreifen zu können).

Und so war es sicher kein Zufall, dass ich nach Turbo-Pascal nicht auf 
Visual C sondern zunächst auf Delphi gekommen bin (obwohl ich damals 
schon sehr genau wusste, dass C der weltweite Programmierer-Standard ist 
und ich mir das allein schon aus beruflichen Gründen nur zu gerne 
angeeignet hätte). Auf Basic, bzw. BASCOM AVR bin ich nur gekommen, weil 
ich im Studium schon mal das sehr ähnliche Fortran kennen gelernt hatte, 
deshalb Basic sofort verstand und weil ich hiermit eine äußerst leicht 
verständliche Entwicklungsumgebung für die 8-Bit-Controller von Atmel 
gefunden hatte.

Viele Grüße

Norbert

von Dr. Sommer (Gast)


Lesenswert?

Norbert Graubner schrieb:
> 4: error: 'RCC_PLLCFGR' undeclared (first use in this function)
Ah, es muss RCC->PLLCFGR heißen, in dieser Header-Datei sind immer die 
Register die zu einer Funktion gehören zu einem "Block" (struct) 
zusammengefasst, und man greift dann darüber zu. Hat zB bei GPIO's den 
Vorteil dass man die als Pointer übergeben kann. Ist halt blöde von ST 
die in der Doku mit "_" und nicht "->" zu beschreiben. Aber 
Dokumentation ist eh nicht deren Stärke...
> Was das Erlernen von C am PC betrifft: ...
Tja, deswegen verwendet man auch C++, das in Bezug auf Typen strenger 
ist und auch einen String-Typ hat ;-)
> Ich denke inzwischen, dass die Fähigkeit, die Sprache C zu begreifen, in
> erster Linie eine Mentalitätsfrage ist. ...
Abstrahierung ist nunmal eines DER zentralen Konzepte der 
Software-Entwicklung und ist absolut essentiell für größere Projekte. 
Zur "Übung" und zur besseren Skalierbarkeit wird das dann auch bei 
kleinen angewendet. Aber im Ernst - String ist doch auch eine 
Abstraktion! Wenn du keine Abstraktionen magst, ist C mit "char*" doch 
ideal, da siehst du immer genau was passiert.
In C am PC verwendet man fopen() um eine Datei zu öffnen - und keinen 
1000-Zeiligen Algorithmus, um die entsprechenden Blöcke auf der 
Festplatte zu finden, den Index des Dateisystems auszulesen etc. - das 
ist doch eine sehr sinnvolle Abstraktion.
Bei Abstraktionen mit "structs" und den entsprechenden 
Zugriffs-Funktionen (in OOP-Sprachen dann noch mehr mit Klassen) geht es 
doch darum, dass du dich eben nicht um jedes einzelne Detail kümmern 
musst, was die Code-Größe und Entwicklungsaufwand drastisch sinken 
lassen.

Wenn du structs nicht verstehst, stell sie dir einfach als 
mathematisches Tupel vor, oder als "IC" - heutzutage wird auch nicht 
jede Schaltung aus einzelnen Transistoren zusammengebaut, sondern 
fertige IC's verwendet die eine komplexe Funktion bieten.

von Uwe B. (derexponent)


Lesenswert?

Norbert Graubner schrieb:
> da bleibt dann fürs echte Debuggen nur die Serielle
> Schnittstelle

"debuggen" kannst du das nicht nennen, eher "monitoren"

aber ich kann mir schon denken was du meinst

eine neue CPU "ARM" und gleichzeitig eine neue Sprache "C" in einem so 
komplexen Projekt wird zwangsläufig schiefgehen

versuche soviel wie möglich unbekannte auszuschließen,
also wenn du mit deiner IDE zurechtkommst bleib dabei
(auch wenn sie keinen Hardware-Debugger unterstützt)

aber mach dich auf einen Alleingang gefasst, denn so gut wie alle 
Beispiele und Code-Schnippsel für den STM sind in "C" geschrieben

Hinweis zum externen RAM :
am 100Pin Package sind die Adressleitungen A0 bis A15 nicht
an der CPU zugänglich...also musst du Latches vorsehen

für 4MBit SRAM am STM32F407 hab ich mal ein Projekt gemacht :

http://mikrocontroller.bplaced.net/wordpress/?page_id=2067

Gruss Uwe

von Norbert G. (realist_50)


Lesenswert?

Hallo Dr. Sommer,

ich bin sehr froh, dass ST jedem einzelnen Register seinen eigenen Namen 
zugeordnet hat. Genau deswegen verstehe ich das ja. Hingegen kann ich 
mit der Ausdruck RCC->PLLCFGR gar nichts anfangen. Wer ist RCC und wer 
ist PLLCFGR? Es doch zusammen nur ein einziges, ganz bestimmtes Register 
mit einer klar zugewiesenen Adresse (zugegeben: es ist das 
Konfigurationsregister für die PLL im Reset-&Clock-Control-Block)! Und 
dass es sich bei dem merkwürdigen Zeichen zwischen den beiden Namen um 
einen Zugriffsoperator für einen Indirektzugriff handelt, habe ich nur 
mit Mühe in einem C-Tutorial von Andreas Hammer gefunden. Aber was der 
genau macht, habe ich noch nicht rausgekriegt.

Für einen 8-Bit-Atmel-Controller (ATMega162) habe ich in Assembler mal 
einen ganz netten, sogar ziemlich schnellen Grafikcontroller für ein 
QVGA-Display geschrieben. Da habe ich auch indirekte Adressierung machen 
müssen. Aber das fand ich durchaus überschaubar. Eben weil es fast auf 
Maschinenebene ablief. Hingegen erkenne ich gar keinen Sinn und keine 
Notwendigkeit, ein einzelnes Register im RCC-Block indirekt adressieren 
zu müssen. Jedes der dort befindlichen Register hat doch ganz 
unterschiedliche Aufgaben! Da kann man doch auch direkt drauf zugehen.

Dass man eine Datei auf der PC-Festplatte über ihren Namen, also über 
eine Abstrahierung anspricht und das Zusammensuchen der Blöcke und 
Sektoren einer Funktion (oder gar einem externen Controller) überlässt, 
finde auch ich sehr sinnvoll, denn es bewirkt eine starke Vereinfachung. 
Hingegen empfinde ich den Zugriff auf ein einzelnes Register mithilfe 
eines Structs als eine künstliche, in meinen Augen (zunächst?) unnötige 
Verkomplizierung.

Es mag sein, dass ich das nur deshalb so sehe, weil ich beim 
Programmieren nie die höheren Weihen erlangt habe; ich habe stets nur 
mit den Grund-Datentypen und evtl. Arrays hiervon gearbeitet. Mag sein, 
dass meine Programme umständlich und manchmal zu aufwändig waren. Aber 
sie haben funktioniert und waren auch für andere Leute immer leicht 
verständlich. Man brauchte kein Hintergrundwissen über die Namen 
irgendwelcher Konstanten und Spezialfunktionen. Alles was man fürs 
Verständnis brauchte, stand im Quelltext - und wenn er 6000 Zeilen lang 
war! Auf diese Weise sind mehrere, sehr schöne, große Anwendungen 
entstanden. Wenn ich jetzt auf einen ARM -Controller wechseln will, dann 
nur wegen dessen höherer Leistung, bzw. Rechengeschwindigkeit, z.B. weil 
ich für ein neues Projekt eine FFT oder wenigstens massenweise 
Multiplikationen mit mehreren hundert kHz Takt brauche. Dabei würde es 
mir vollkommen genügen, wenn ich das mit meiner bisherigen, schlichten 
(und meinetwegen aufwändigen und umständlichen) Programmiertechnik 
erreichen würde. Ein schlichter Programmierstil muss ja nicht 
zwangsweise zu einem langsamen Programmablauf führen.

Die Vorteile, die ein erhöhtes Maß an Abstrahierung - sinnvoll 
eingesetzt - mit sich bringen können, sehe ich sehr wohl. Mein Problem 
besteht aber darin, dass ich bei diesem - von der Hardware weitgehend 
losgelösten - abstrakten Denken gar zu schnell an meine persönlichen 
Grenzen komme; ich schaffe es einfach nicht!

Viele Grüße

Norbert

von Norbert G. (realist_50)


Lesenswert?

Hallo Uwe,

über Deine anteilnehmende Stellungnahme zu meiner enormen Schwierigkeit 
beim gleichzeitigen Erlernen einer unbekannten CPU und einer unbekannten 
Programmiersprache bin ich sehr erleichtert. Erschwerend kommt noch die 
mir total gegen den Strich gehende Tendenz zum Abstrahieren hinzu; als 
Ingenieur habe ich seit nunmehr fast 40 Dienstjahren eher das Gegenteil 
- also immer die Konkretisierung bestehender Aufgaben und deren 
Auflösung bis hin zum kleinsten Widerstand - angestrebt.

Dass ich mich bei meiner jetzigen IDE auf einen Alleingang gefasst 
machen muss, ist mir schon klar. Das war aber unter CooCox auch schon 
so, denn die in C verfügbaren Beispiele habe ich ja wegen der 
Abstrahierung (wenn überhaupt) ohnehin meist nur ansatzweise verstanden.

Danke auch für Deinen Hinweis zur Verwendung eines externen SRAMs! Sowas 
habe ich schon mal gemacht - auch mit einem Latch und zwar mit einem 
Atmel XMega128A1, einem AHC573 und einem IS61WV10248B. Das hat fast auf 
Anhieb bestens geklappt. Weil aber dieses 8-MegaBit-SRAM eigentlich noch 
zu klein war, noch größere Chips aber richtig teuer werden, will ich 
jetzt im Folgeprojekt erstmals ein deutlich billigeres und größeres DRAM 
verwenden (damals hatte ich noch Schiss davor...). Das soll meine 
nächste Herausforderung (an einem Cortex M4) sein.

Viele Grüße

Norbert

von Dr. Sommer (Gast)


Lesenswert?

Norbert Graubner schrieb:
> Hallo Dr. Sommer,
>
> ich bin sehr froh, dass ST jedem einzelnen Register seinen eigenen Namen
> zugeordnet hat. Genau deswegen verstehe ich das ja. Hingegen kann ich
> mit der Ausdruck RCC->PLLCFGR gar nichts anfangen. Wer ist RCC und wer
> ist PLLCFGR?
RCC ist der Block an Registern der die "RCC"-Einheit konfiguriert (Reset 
and Clock Control), und PLLCFGR ist eines dieser Register.
> Es doch zusammen nur ein einziges, ganz bestimmtes Register
> mit einer klar zugewiesenen Adresse (zugegeben: es ist das
> Konfigurationsregister für die PLL im Reset-&Clock-Control-Block)! Und
> dass es sich bei dem merkwürdigen Zeichen zwischen den beiden Namen um
> einen Zugriffsoperator für einen Indirektzugriff handelt, habe ich nur
> mit Mühe in einem C-Tutorial von Andreas Hammer gefunden. Aber was der
> genau macht, habe ich noch nicht rausgekriegt
Das steht auch in jedem C-Buch. Beim RCC macht das ganze nicht so viel 
Sinn weil der Controller nur einen hat, da ist das nur aus Gründen der 
Konsistenz so gemacht. Aber beim GPIO schon mehr. Da kann man sich zB 
schreiben:
1
void configurePort (GPIO_TypeDef* port) {
2
  port->MODER = 0xAEAEAEAE;
3
  port->ODR = 0xAAAAAAAA;
4
}
5
int main () {
6
  configurePort (GPIOA);
7
  configurePort (GPIOB);
8
  configurePort (GPIOC);
9
}
(Werte frei erfunden) so kann man abstrakt eine GPIO-Einheit an eine 
Funktion übergeben, und die Funktion macht etwas mit dieser Einheit.
>
> Für einen 8-Bit-Atmel-Controller (ATMega162) habe ich in Assembler mal
> einen ganz netten, sogar ziemlich schnellen Grafikcontroller für ein
> QVGA-Display geschrieben. Da habe ich auch indirekte Adressierung machen
> müssen. Aber das fand ich durchaus überschaubar. Eben weil es fast auf
> Maschinenebene ablief. Hingegen erkenne ich gar keinen Sinn und keine
> Notwendigkeit, ein einzelnes Register im RCC-Block indirekt adressieren
> zu müssen. Jedes der dort befindlichen Register hat doch ganz
> unterschiedliche Aufgaben! Da kann man doch auch direkt drauf zugehen.
Die Aufgaben gehören aber alle zum RCC... Die ATmega haben auch mehrere 
Register die zusammen gehören, wie Timer-Register oder Pin-Register - 
die hätte Atmel auch zusammenfassen können.
> Hingegen empfinde ich den Zugriff auf ein einzelnes Register mithilfe
> eines Structs als eine künstliche, in meinen Augen (zunächst?) unnötige
> Verkomplizierung.
Es bleibt ja meist nicht bei einem Register, ein Timer hat davon einen 
ganzen Satz...
> Es mag sein, dass ich das nur deshalb so sehe, weil ich beim
> Programmieren nie die höheren Weihen erlangt habe; ich habe stets nur
> mit den Grund-Datentypen und evtl. Arrays hiervon gearbeitet. Mag sein,
> dass meine Programme umständlich und manchmal zu aufwändig waren. Aber
> sie haben funktioniert und waren auch für andere Leute immer leicht
> verständlich. Man brauchte kein Hintergrundwissen über die Namen
> irgendwelcher Konstanten und Spezialfunktionen. Alles was man fürs
> Verständnis brauchte, stand im Quelltext - und wenn er 6000 Zeilen lang
> war!
Im Endeffekt steht immer alles im Quelltext - du kannst dir die 7000 
Zeilen der stm32f4xx.h auch in deinen Code kopieren, dann steht auch 
alles drin und ist einfach verständlich.
Aber mit dieser Einstellung wird man in der IT-Branche auf nicht viel 
Gegenliebe stoßen; die meisten Programmierer ziehen es vor mehr 
Konstrukte EINMAL zu lernen und dadurch kompaktere Programme schreiben 
zu können, als immer wieder in jedem Programm riesige Mengen Quellcode 
lesen zu müssen, die vielleicht keine besonderen Konstrukte verwenden...

> Auf diese Weise sind mehrere, sehr schöne, große Anwendungen
> entstanden. Wenn ich jetzt auf einen ARM -Controller wechseln will, dann
> nur wegen dessen höherer Leistung, bzw. Rechengeschwindigkeit, z.B. weil
> ich für ein neues Projekt eine FFT oder wenigstens massenweise
> Multiplikationen mit mehreren hundert kHz Takt brauche. Dabei würde es
> mir vollkommen genügen, wenn ich das mit meiner bisherigen, schlichten
> (und meinetwegen aufwändigen und umständlichen) Programmiertechnik
> erreichen würde. Ein schlichter Programmierstil muss ja nicht
> zwangsweise zu einem langsamen Programmablauf führen.
Das kannst du ja für dich so machen, aber wenn du eben externen Code 
einbindest wie die ST-Header-Dateien mit den Register-Definitionen oder 
die ST USB-Library, musst du dich mit deren Konventionen abfinden...
> Die Vorteile, die ein erhöhtes Maß an Abstrahierung - sinnvoll
> eingesetzt - mit sich bringen können, sehe ich sehr wohl. Mein Problem
> besteht aber darin, dass ich bei diesem - von der Hardware weitgehend
> losgelösten - abstrakten Denken gar zu schnell an meine persönlichen
> Grenzen komme; ich schaffe es einfach nicht!
Hm, das verstehe ich wieder nicht ganz... Wenn man sich z.B. das sehr 
abstrakte Arduino-API ansieht, hat man Funktionsaufrufe im Code wie:
1
 pinMode(9, OUTPUT);
2
analogWrite(9, 55);
Das reicht schon um eine PWM einzuschalten. Man braucht keine 
komplizierten Bitrechnereien um die Registerinhalte zu bekommen, sondern 
kann sehr leicht erkennen was der Code macht. Solch Abstraktion ist doch 
nicht so schwierig?!

von m.n. (Gast)


Lesenswert?

Lade Dir folgende Datei: 
http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf
Unter Punkt 7 findet sich die Beschreibung von RCC mit seinen Registern 
und unter Punkt 7.3.25 die Abbildung der RCC-Register im Speicher.

von Norbert G. (realist_50)


Lesenswert?

@ Gast:

Danke für den Tipp! Bei dem Dokument handelt es sich um das Reference 
Manual - für mich in der Tat die einzige wirklich tragfähige "Referenz"! 
Schon vor mehreren Wochen hatte ich mir den kompletten Abschnitt 7 
(zuvor auch Abschn. 8 über die GPIOs) mit den darin enthaltenen genauen 
Beschreibungen der einzelnen Register ausgedruckt und durchgearbeitet. 
Bei insgesamt 1700 Seiten ist das ein ziemlich mühsamer Weg, aber auf 
genau dieser Grundlage (direkter, leicht verständlicher Zugriff auf die 
einzelnen Register) komme ich unter MikroBasicPro bisher gut damit 
zurecht.

von m.n. (Gast)


Lesenswert?

Nach dem, was Du geschrieben hattest, kennst Du auch noch die schönen 
Handbücher (Hardware Manual), die man auf dem Sofa, dem Bett, an einem 
stillen Ort ausgiebig studieren konnte. Die gibt es leider nicht mehr 
:-(

Wenn ich mit Peripherie-Geschichten neu zu tun habe, drucke ich mir das 
betreffende Kapitel insgesamt aus und lese es komplett durch, bevor ich 
nur eine Zeile Code schreibe. Dabei bekomme ich einen Gesamteindruck, 
was geht, oder was ich erwartet hatte, aber nicht vorhanden ist. (Der 
hochgelobte F407 hat nämlich auch seine Schattenseiten.)
Vielleicht liegt Dir diese Vorgehensweise.

von Dr. Sommer (Gast)


Lesenswert?

m.n. schrieb:
> Wenn ich mit Peripherie-Geschichten neu zu tun habe, drucke ich mir das
> betreffende Kapitel insgesamt aus und lese es komplett durch,
Wenn das mal alle machen würden, wäre dieses Forum ein friedlicherer 
Ort...

Aber diese 1700 Seiten sind ja noch nicht alles, man muss sich ja noch 
die 1020 Seiten für den ARM Kern durchlesen:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0403c/index.html


@ Norbert:
Warum machst du dir so einen Aufwand mit dem RCC? Es gibt von ST 
wunderbare Beispiel-Codes, wie man den RCC initialisiert sodass er auf 
maximalem Takt läuft; den muss man nur in sein Projekt kopieren und dann 
kann man sich den interessanteren Hardware-Teilen widmen, wie I/O Pins 
und Timer etc. Falls man dann doch irgendwann mal einen niedrigeren Takt 
haben will kann man das immer noch anpassen. Lediglich die einzelnen 
Takte für die einzelnen Peripherie-Module muss man noch einschalten, 
aber das sind ja nur einzelne Bits.

von Bernd N (Gast)


Lesenswert?


von Norbert G. (realist_50)


Lesenswert?

@ Gast:
Das mit dem Bett wollte ich zuerst schreiben, dachte aber, dass das 
vielleicht doch etwas zu naiv und altmodisch wirkt. Aber in der Tat: Ich 
bin mehrere Abende extra etwas früher ins Bett gegangen und habe mir 
dort die ausgedruckten Kapitel in aller Ruhe und ganz entspannt zu 
Gemüte geführt. Auszugsweise habe ich diese anschließend für einen 
Freund sogar schriftlich ins Deutsche übersetzt (auch dabei lernt man 
noch was). Erst danach habe ich aus eigener Einsicht - d.h. mit dem 
zugehörigen Verständnis im Hinterkopf - die erste Zeile Code 
geschrieben.

Die Bücherwand in meinem Arbeitszimmer ist übrigens immer noch voll mit 
besonders wertvollen Datenbüchern (Analog Devices, Burr Brown, Harris, 
International Rectifier, Maxim, Microchip, Motorola, National 
Semiconductor, Philips, Siemens, Texas Instruments ...)


@ Dr. Sommer:
Der Aufwand, den ich mir mit dem RCC mache, rührt daher, dass ich dieses 
System erst mal verstehen lernen musste. Im AtMega gabs nur einen 
einzigen Takt, wenn man Glück hatte vielleicht noch eine PLL (Xmega) - 
aber das wars dann auch. Als ich (über SiSy ARM) zum ersten Mal Kontakt 
mit einem ARM-Controller bekam, war ich allein von der Komplexität des 
RCC total irritiert ("wozu so viele verschiedene Takte???"). Ich bin 
halt der vielleicht etwas altmodischen Auffassung, dass man nur dann 
optimale Ergebnisse erwarten kann, wenn man ein System verstanden hat. 
Beim Abschreiben (oder gar Kopieren) von fremdem Code lernt man aber 
nicht genug.

So blieb für mich die RCC-Konfigurierung unter Huwalds SiSy ARM - obwohl 
sie auf Anhieb funktionierte - ein Buch mit Sieben Siegeln. Erst nachdem 
ich im Reference Manual die Seiten über GPIO und RCC durchgelesen hatte, 
was es für mich ein Leichtes, die paar Register selber zu konfigurieren. 
Das funktionierte beinahe auf Anhieb. Jetzt arbeitet mein STM32F407 mit 
quarzgesteuerten 168 MHz und auch die Peripherie hat die richtigen 
Taktfrequenzen.

Danke für den Tipp zum Handbuch über den ARM-Kern! Das werde ich mir 
dann auch noch zu Gemüte führen ...


@ Bernd:
Den ersten von Dir genannten Link hatte ich schon mal aufm Bildschirm. 
Leider handelt es sich um eine (nicht gerade billige) professionelle 
Entwicklungsumgebung. Die darin enthaltenen Tipps sind sicher wertvoll, 
aber ich muss auch darauf achten, dass ich meine nicht unendliche Zeit 
und Kraft auf die richtigen Pfade lenke. Ich werds mir aber nochmal 
näher ansehen.

Hingegen könnte der zweite Link sehr interessant werden. Noch vor 
wenigen Wochen hätte ich sonstwas drum gegeben, ein C-Tutorial auf Basis 
eines ARM-Controllers zu finden. Ich war in mehreren Buchhandlungen, 
habe dort aber nur Standardwerke über C gefunden, die allesamt (mit der 
allseits beliebten Funktion printf() ) auf einem PC laufen. Eines davon 
habe ich gekauft, aber wie Du hier nachlesen kannst, nützte es mir 
herzlich wenig. Vielleicht wird Dein Link für mich doch nochmal ein 
(verzweifelter) Anlauf, in die Sprache C einzusteigen (seuftz...) ...

Viele Grüße an Alle!

Norbert

von Bernd N (Gast)


Lesenswert?

Der erste Link führt zu einem EMBlocks tutorial und EMBlocks ist 
kostenlos, hier mal der direkte Link zur Software...

http://www.emblocks.org/web/

C lernt man nicht auf einem MC aber alles was du brauchst gibts auch 
hierfür kostenlos.

http://www.it-ebooks.info/book/704/

PDF Version ist frei zu haben. Wenn du das durcharbeitest verstehst du 
auch die STM Libs denn die C Grundlagen hierfür sind im PDF bestens 
erklärt. Also schau noch einmal genauer hin.

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.