beim austesten der machbaren Taktfrequenzen bin ich mit
dem Problem konfrontiert worden, dass der angezeigte
und der als alternate ausgebene Systemtakt nicht nur
nicht übereinstimmen sondern gewaltig differieren.
Beim 746 sagt er:
SystemCoreClock : 216 MHz
Beim 743:
SystemCoreClock : 400 MHz
und das ist auch jeweils das, was ich im Cubeide 1.13.2
konfiguriert habe.
Aber ein
while (1) {GPIOF->ODR ^= GPIO_ODR_OD1;}
bringt bei beiden nur rund 5MHz raus.
(4,75 und 5,25)
Beim 743 habe ich dann mal RCC_MCO_2 auf einen Port
gelegt und auch bekomme ich nur diese Frequenz angezeigt.
Interrupts sind aus und somit sollte der Port-Toggle
doch eigentlich der halben Taktfrequenz entstprechen.
Ich habe überigens keine Veränderung feststellen können, ob die
Ports auf "slow" oder "very fast" stehen - sollte ja eh eigentlich
nur die Stromaufnahme betreffen. Aber versucht hab ich das auch mal.
Dass GPIOF->ODR ^= GPIO_ODR_OD1 schnarchlangsam ist, ist ein alter Hut. (Da scheinen auch ein paar Tippfehler zu sein ...). Mit halbem CPU-Takt ist da nix.
Dass schafft selbst ein STM32G0 viel schneller.
Was die MCO-Ausgänge anbelangt: Die GPIOs können lt. Datenblatt unter günstigen Umständen garantiert bis zu 180 Mhz.
Aber man sollte vielleicht mal die RCC-Register "zu Fuß" kontrollieren, ob da wirklich das drinsteht, was man vermutet/erhofft. Insbesondere PLLRDY, die eingestellten Faktoren/Teiler und die SWS-Bits. Ach ja, die Teiler für MCO1 bzw. MCO2 nicht zu vergessen ...
Aber ein
while (1) {GPIOF->ODR ^= GPIO_ODR_OD1;}
bringt bei beiden nur rund 5MHz raus.
(4,75 und 5,25)
Beim 743 habe ich dann mal RCC_MCO_2 auf einen Port
gelegt und auch bekomme ich nur diese Frequenz angezeigt.
Interrupts sind aus und somit sollte der Port-Toggle
doch eigentlich der halben Taktfrequenz entstprechen.
Falsch. Die obige Schleife enthält mindestens eine Port-Leseoperation, eine logische Operation, eine Port-Schreiboperation und einen Sprung. Selbst wenn all dies in jeweils einem CPU-Taktzyklus abliefe, wären das schon vier Takte.
Und warum hältst Du es nicht für nötig, mal einen Blick in die Systemarchitekturen der beiden Microcontroller zu schauen, z.B. in dem jeweiligen Reference Manual, Kapitel "Memory and bus architecture"? Die GPIO-Register hängen da so ziemlich am Ende der Nahrungskette, d.h. die Zugriffe erfolgen über etliche Bus Bridges, die teils mit unterschiedlichen Takten laufen und dementsprechend einsynchronisiert werden müssen.
Wie kommt man bloß auf die absurde Idee, dass ein Lesezugriff, der ja für die o.a. XOR-Verknüpfung erforderlich ist, in nur einem Zyklus möglich wäre? Ganz im Gegenteil wird dadurch jegliches Pipelining bei der Buszugriffen völlig vereitelt.
Falsch. Die obige Schleife enthält mindestens eine Port-Leseoperation,
eine logische Operation, eine Port-Schreiboperation und einen Sprung.
Selbst wenn all dies in jeweils einem CPU-Taktzyklus abliefe, wären das
schon vier Takte.
Und dazu kommt noch: diese (hypothetischen) vier CPU-Takte würden nur die Hälfte der Wellenform erzeugen. Die Ausgabefrequenz wäre also bestenfalls 1/8 des CPU-Takts.
Auf jeden Fall ist es viel weniger als eigentlich ankommen
müsste - bei angeblichen 400HMz.
Und was ergibt Deine konkrete Berechnung der Latenzen anhand der Systemarchitektur? Nicht irgendwelche gefühlten Abschätzungen, sondern quantitative Berechnungen anhand der Taktverhältnisse zwischen den Bus-Bridges, usw.. Welche ganz konkrete Dokumentation von ARM zu den betreffenden IP-Blöcken hast Du hierfür herangezogen?
Ob da nun 3 oder 5 MHz beim GPIO-schreiben rauskommen
und ob er 2, 5 oder 10 oder auch 20 Zyklen pro Toggle
braucht:
Auf jeden Fall ist es viel weniger als eigentlich ankommen
müsste - bei angeblichen 400HMz.
Ja, ist auch klar.
Bei so einem STM32H7 ist wie bei allen ARM-und MIPS-MCUs/MPUs der Prozessorkern ein Zukaufteil, eine Black Box, wo der Chiphersteller keinen Zugriff auf die Interna hat. Die ganze Peripherie wird über asynchrone Busse angekoppelt, die mit einem Bruchteil des Prozessortaktes laufen. Das gilt im übrigen auch für den gesamten Speicher (Flash und RAM) mit Ausnahme des TCM. Deswegen ist die IO-Geschwindigkeit VIEL langsamer als der Prozessortakt.
Gegenbeispiel Microchip PIC24/dsPIC33: Hier ist der Prozessorteil kein Zukaufteil, sondern integraler Bestandteil. Die ganzen SFRs (Special Function Registers) sind genau wie das RAM und die Prozessorregister (die sich in den ersten Adressen des Datenadressbereiches befinden) direkt synchron an den Prozessorkern angebunden. Genau deswegen kann der PIC24 auch atomare Bitbefehle, wählend ARM und MIPS (z.B. PIC32) das von sich aus grundsätzlich nicht können - hier muss die Peripherie entsprechende Bit-Set, Bit-Clear und Bit-Toggle Register oder Bit-Banding bereitstellen.
Und wer schnelle, deterministische Signale erzeugen will, braucht extra Hardware dafür, entweder in Form von Prozessorperipherie oder eines FPGA-Blockes.
Dann stimmt deine Taktkonfiguration nicht, und die ganzen Überlegungen bzgl. GPIO-Zugriff, Prozessor-Latenz usw. sind hinfällig. Die Taktausgabe auf MCO kommt direkt aus dem Taktsystem/PLL und hat mit dem Prozessorkern, Busstruktur nicht viel zu tun. Lediglich die "analoge" Maximalfrequenz des GPIO-Treibers kann hier limitieren, aber einen verschliffenen Sinus sollte man bei 400 MHz noch erkennen können (sofern dein Oszilloskop das kann!).
Aus dem HSI so einen hohen Takt zu erzeugen ist fragwürdig, schau mal ins Datasheet ob das überhaupt erlaubt ist. Benutze einen externen Quarz/Keramik-Oszillator und prüfe mit dem Oszilloskop ob er anläuft.
Schau mal ob die RCC-Initialisierungsfunktionen Fehler zurückgeben (im Debugger durchsteppen).
"Schau mal ob die RCC-Initialisierungsfunktionen Fehler zurückgeben (im
Debugger durchsteppen)."
Guter Ansatz. Hatte ich nicht dran gedacht.
Ich habe mir aber grad mal die RCC_MC02 genauer angesehen:
Wenn ich HSE 1:1 durchleite, dann messe ich 8 MHz.
Und das was rauskommt, das kann man noch als Rechteck
durchgehen lassen.
Wenn ich SYSCLK/ 5 hinleite, dann sollten es 26MHz werden.
Es kommt aber nur noch Grütze an.
Ein Pegel von ca. 1.5 Volt mit ca. 0,5 Volt Jitter.
Und wenn man den genauer ansieht, dann sieht man:
der jittert mit 26,6MHz.
Mit einem Teiler von 10 sind es 40 MHz und mit 1 bin
ich in dem Bereich, den ich nicht mehr messen kann....
Also die Taktung stimmt also wohl. Und grundsätzlich
gehen auch Signale im 2-stellingen MHz-Bereich raus.
Ich weiss aber nicht, ob man solche Signale noch
sauber verarbeiten kann.
Mit welchen Geschwindigkeiten arbeitet Ihr denn so?
Wenn ich HSE 1:1 durchleite, dann messe ich 8 MHz.
Und das was rauskommt, das kann man noch als Rechteck
durchgehen lassen.
Wenn ich SYSCLK/ 5 hinleite, dann sollten es 26MHz werden.
Es kommt aber nur noch Grütze an.
Ein Pegel von ca. 1.5 Volt mit ca. 0,5 Volt Jitter.
Und wenn man den genauer ansieht, dann sieht man:
der jittert mit 26,6MHz.
Aha, und das soll daran liegen, dass der Prozessor kein ordentliches Ausgangssignal liefert? Das ist völliger Unsinn. Der tatsächliche Grund liegt vielmehr in Deinem Aufbau bzw. der Art und Weise, wie das Signal abgegriffen wird. Lass mich raten: Die Masseklemme ist nicht in unmittelbarer Nähe des Microcontrollers angeschlossen und auch nicht so kurz wie möglich. Womöglich handelt es sich auch noch um einen 1:1-Tastkopf oder gar ein einfaches Stück Koaxialkabel, so dass dort haufenweise Reflektionen auftreten können.
Bei 30 bzw. 50 MHz ist Schluss.
Unit-T und Peaktech
Dann ist ja wohl klar dass da nichts vernünftiges bei rauskommt. Du könntest mit einem Timer eine PWM erzeugen mit z.B. 1kHz und prüfen ob auch tatsächlich 1kHz raus kommen; wenn nicht, ist der Takt falsch.
Aha, und das soll daran liegen, dass der Prozessor kein ordentliches
Ausgangssignal liefert?
Hab ich das gesagt?
Nö, hab ich nicht.
Ich hab lediglich Fakten aufgezählt.
Sicher einige vergessen, nicht beachtet oder
bewusst vernachlässigt.
Den Verdacht, dass es (auch) ein HF-Problem ist, den hab ich
auch schon geäußert und werde das eingrenzen.
Wichtiger ist mir jetzt erst mal eine Testumgebung um
die Grenzen und Probleme richtig austesten zu können.
Das stelle ich grad zusammen und dann ins Netz.
"Dann ist ja wohl klar dass da nichts vernünftiges bei rauskommt."
Und wenn mit der Herr Erlkönig nun mal erklären könnten,
warum man mit einem 50HMz-Scope keine 30 MHz messen können soll...
Achja - mich interessiert nach wie vor:
Mit welchen Geschwindigkeiten arbeitet Ihr denn so?
warum man mit einem 50HMz-Scope keine 30 MHz messen können soll...
Kann man, wird halt ziemlich verschliffen/sinusartig. Aber ich dachte du
versuchst 400 MHz vom MCO messen?
Nein, nein, dass ich das mit den hier vorhandenen Geräten
nicht kann, das ist mir klar.
Aber ich war davon ausgegangen, das bis zu 10 MHz kein Problem
sein sollten - und war sehr überrascht, was ich dann so zu sehen
bekam.
Wie auch immer:
Mich würde wirklich interessieren, ob hier jemand praktische
Erfahrungen mit dem 743 oder 746 bei sehr schnellen
Signalen auf den IO-Ports hat.
Ich taste mich da jetzt so langsam ran
und wundere mich oft ;-)
Mich würde wirklich interessieren, ob hier jemand praktische
Erfahrungen mit dem 743 oder 746 bei sehr schnellen
Signalen auf den IO-Ports hat.
Schau dir das STM32F746NG Discovery an. Das hat SDRAM, ein paralleles Display und eine per SDIO angebunde SD-Karte. Letztere kann man problemlos mit 48 MHz ansteuern. Schau mal ins Datenblatt wie schnell SDRAM und Display sind, die funktionieren auch problemlos.
Wie auch immer:
Mich würde wirklich interessieren, ob hier jemand praktische
Erfahrungen mit dem 743 oder 746 bei sehr schnellen
Signalen auf den IO-Ports hat.
Was nützt das, wenn Du die relevanten Fragen eh hartnäckig ignorierst? Und noch einmal: Wie hast Du denn berechnet, welche Frequenz das Ausgangssignal haben sollte, wenn per Firmware an dem GPIO gewackelt wird?
Wie auch immer:
Mich würde wirklich interessieren, ob hier jemand praktische
Erfahrungen mit dem 743 oder 746 bei sehr schnellen
Signalen auf den IO-Ports hat.
Was nützt das, wenn Du die relevanten Fragen eh hartnäckig ignorierst?
Und noch einmal: Wie hast Du denn berechnet, welche Frequenz das
Ausgangssignal haben sollte, wenn per Firmware an dem GPIO gewackelt
wird?
Wem es nützt?
Jedem, der sich fragt: "Lohnt es sich, sich mit dem 746 oder
743 zu beschäftigen, wenn ich damit Signale im MHz-Bereich
erezugen oder erfassen will? Oder lohnt es sich nicht, weil
sich schon andere die Zähne dran ausgebissen haben?"
Ich habe überhaupt nichst errechnet. Dafür ist es noch viel zu früh.
Ich weiss aber, dass bei einem 400MHz Takt mehr als ein paar 100 kHz
raus kommen müssen - Ganz egal, wie verzwackt das interne
Bus-System ist.
Das taten sie auf Anhieb nicht und ich suche nach dem Grund.
Was ich dazu gerade tue, dass ist unter der obigen Link
Schritt für Schritt nachzulesen.
Wem es nützt?
Jedem, der sich fragt: "Lohnt es sich, sich mit dem 746 oder
743 zu beschäftigen, wenn ich damit Signale im MHz-Bereich
erezugen oder erfassen will?
Ja. Alles STM32 können Signale im unteren zweistelligen MHz-Bereich ausgeben. In Software wie gezeigt geht es zwar, ist aber wenig sinnvoll. Viel besser geht das mit Timern, DMA oder auch FSMC. Damit kommt man auf die maximale im Datasheet angegebene GPIO-Frequenz.
Ja. Alles STM32 können Signale im unteren zweistelligen MHz-Bereich
ausgeben. In Software wie gezeigt geht es zwar, ist aber wenig sinnvoll.
Viel besser geht das mit Timern, DMA oder auch FSMC. Damit kommt man auf
die maximale im Datasheet angegebene GPIO-Frequenz.
Wie Andreas schon erwähnt hat können die GPIO-Treiber des STM32F746NG bis zu 180 MHz ausgeben. Über die Peripherie-Blöcke erreicht man:
Mit Timern bis zu 108 MHz; der Timer läuft intern zwar bei 216 MHz, kann aber nur maximal die halbe Frequenz als "PWM" erzeugen
Der SDIO-Block kann 50 MHz
Der TFT-Controller kann 45 MHz
Der FMC kann bis zu 108 MHz je nach Speichertyp
Der QSPI ebenso 108 MHz
Der normale SPI kann 54 MHz
Das USB-ULPI Interface läuft bei 60 MHz
Das Kamera-Interface kann 54 MHz
Die 180 MHz kann man wohl nur mit dem MCO erreichen. Zum Vergleich: Die GPIO-Treiber des guten alten STM32F103RB können 50 MHz treiben, bei 72 MHz internem Takt können die Timer also 36 MHz maximale Ausgabefrequenz. Schnelle dedizierte Interfaces hat er leider keine.
Wie bei so gut wie allen schnellen Prozessoren ist die interne Taktfrequenz (hier: 216 MHz) nur für den Prozessorkern und den schnellsten Bus (AHB) relevant. Nahezu das ganze Drumherum läuft langsamer. Nur einige sehr schnelle Interfaces wie DDR-SDRAM, PCIe, USB-HS, HDMI, SD-bus mit UHS erreichen höhere Frequenzen, brauchen dafür aber ausgeklügelte (differentielle) Transceiver mit Selbstkalibration. Beliebige Bitmuster kann man damit nicht ausgeben.
Bei "richtigen" Prozessoren (SoC) der Cortex-A -Klasse ist das noch deutlicher; deren Prozessorkerne laufen zwar im GHz-Bereich, aber allein schon der Zugriff auf die GPIO-Register braucht Hundert(e) Takte, weil die GPIO-Peripherie und dessen Bus eben so langsam ist. Es kommt auch selten jemand auf die Idee, auf solchen Prozessoren schnelle GPIO-Zugriffe zu machen; die werden eher für Status-LEDs oder Buttons genutzt. Für schnelle Datenübertragungen werden auch hier dedizierte Peripherieblöcke genutzt. Controller wie der STM32F746NG sind da schon eher eine Besonderheit, weil der Prozessorkern schon recht schnell ist (im Vergleich zu "normalen" Mikrocontrollern) aber der GPIO-Zugriff ebenfalls noch recht direkt/schnell geht (im Vergleich zu Anwendungsprozessoren).
Bleibt also die übliche Frage: Was willst du eigentlich erreichen? Wenn du einfach nur einen schnellen Takt ausgeben möchtest, dafür gibt es PLL-ICs; manche Controller haben auch extrem schnelle PWM-Ausgänge.
hey, Danke!
Das sind mal schön zusammengefasste und verständliche Infos.
"Bleibt also die übliche Frage: Was willst du eigentlich erreichen?"
Das habe ich alles in dem o.g. Link zusammengenfasst.
Eigentlich wollte ich nur im µSec Bereich einlesen
und ausgeben können. Und das schien mir bei bis zu
480MHz Clock nicht _zu_verwegen.
Ich hab für den max7219 einen SPI "von Hand" geschrieben
(also ohne das SPI-Interface) um ein bisschen zu experimentieren.
Dann diese Signale mit einem 746 eingefangen und dargestellt.
Und beim Schrauben an den Timings bin ich auf das Eingangsproblem
gestossen.
Jetzt sehe ich schon ein wenig klarer und es geht weiter.
Den Code sollte man nach Möglichkeit in den ITCM RAM um Wait States zu vermeiden. Zur Sicherheit ist die Schleife so eingestellt dass sie in eine Cache-Line passt. Ist aber immer noch langsamer als per Timer.
Viel mehr, als mit einer HAL-GPIO-Schleife machbar war.
30nS von Pegelwechsel zu Pegelwechsel. Bei 400/2 MHz Sysclock.
Würde bedeuten 6 Zyklen pro Toggle. Das erscheint auf den ersten
Blick stimmig.
"Sinnvoll" ist das schon aufgrund der Signalqualität eher nicht.
Aber ein sehr schönes Experiment.
Ich habe das gerade mal mit meinem Nucleo553 Board probiert.
Aus dem MCO2 bekomme ich 480Mhz / 4 = 120 MHz. ( GPIO_SPEED_FREQ_VERY_HIGH)
Durch 3 dividiert schafft er nicht mehr jeden Takt.
Aber obwohl fastToggle jetzt bei 0x00 steht
scheint der Aufruf nach 0c80... zu gehen.
Das ist soweit normal, das ist ein "veneer" oder "Trampolin", eine Funktion welche einfach nur ans eigentliche Ziel springt. Das macht der Compiler, weil die Adresse der Funktion sehr weit weg ist, und in die Instruktionen für relative Sprünge ("bl") die Adresse nicht als Immediate hinein passt.
An genau dieser Stelle steht die Adresse der Zielfunktion, "fastToggle". Der Disassembler disassembliert dies fälschlicherweise, da steht eigentlich einfach nur 0x00000001. Das entspricht zufällig diesen beiden sinnlosen "mov"-Instruktionen. Das "ldr.w pc, [pc]" lädt diese Adresse in den PC, d.h. der Prozessor springt an eben diese Stelle, d.h. an 0x00000001. Soweit also alles richtig, nur blöd dargestellt.
Du hast ohne Optimierungen kompiliert... Die STR-Kette ist korrekt, aber die Schleife ist nicht sehr effizient, d.h. du solltest Jitter auf dem Signal sehen.
Wie kommt er darauf, dass das "HAL_EXTI_D3_EventInputConfig" sein
soll?
Wahrscheinlich wird diese (und andere) Funktionen wegoptimiert, aber das Symbol behalten und auf 0 gesetzt. Wenn der Disassembler aus der Adresse 0 das zugehörige Symbol herausfinden will, gibt er das erstbeste zurück, und das war jetzt zufällig nicht fastToggle sondern HAL_EXTI_D3_EventInputConfig. Auch nicht ungewöhnlich, nur lästig.
Ich denke schon dass die Funktion jetzt korrekt aus dem ITCM-RAM ausgeführt wird. Eventuell ist die Busstruktur vom H7 so "tief" dass es wirklich nicht schneller geht. Vielleicht ist aber doch der Prescaler HPRE zu groß. Bei den älteren STM32F4 u.a. geht der IO-Zugriff IIRC in 2 Takten, sofern man den Code aus dem RAM ausführt.
Der Trick mit BSRR sorgt dafür dass auch wenn zwischen den letzten beiden Zeilen ein Interrupt einen anderen Pin auf dem selben Port ändert, dieser nicht direkt wieder zurückgesetzt wird. Alte Versionen der Funktion haben das mit
Das klingt alles sehr logisch und erklärt
das Verhalten...
"du solltest Jitter auf dem Signal sehen"
Ich habe Sprünge zwischen 16.45 und 16.73 MHz.
Ganz selten taucht mal 17.01 auf.
Das habe ich für Messungenauigkeiten gehalten.
Aber das Signal zittert wirklich ein bisschen.
So um die 5 nS herum etwa.
Nachtrag....
Cube steckt immer wieder voller Überraschungen:
Nun sagt er beim Klick auf .ioc: "rendering UI"....
und wenn er dann fertig ist, dann ist das UI ein weisser
Bildschirm (bzw. ein weisses Fenster).
Keine Fehlermeldung, kein Menue, keine Buttons.
Kein nichts....
Hat das schon mal wer so gehabt?
Geändert waren ein paar M7-Einstellungen, weil ich mal
sehen wollte, wie die sich auswirken. (ob sinnvoll oder
nicht sei mal dahingestellt.)
Dass dann aber das ganze Cube-UI verschwindet, das hätte ich
so nicht erwartet.
Das .ioc aus dem Backup wieder zurück und dann ging es wieder.