Hallo,
ich verwende das picoboard RP2040 mit arduino framework. Weiss jemand ob man ähnlich wie bei Atmega, Attiny Serie den GPIO Port/Pin direkt per Register ansprechen kann wie z.B.?
1 |
|
2 |
|
statt via pinMode(), digitalWrite()...?
Danke
|
Anzeige
|
Picoboard, Arduino, Gpio / Port direkt per Register-Zugriff steuern?Hallo, ich verwende das picoboard RP2040 mit arduino framework. Weiss jemand ob man ähnlich wie bei Atmega, Attiny Serie den GPIO Port/Pin direkt per Register ansprechen kann wie z.B.?
statt via pinMode(), digitalWrite()...? Danke Ja, kann man machen. Liess das Datenblatt da stehen die Register drin. Vanye
und wie findet man den Layer wo diese Register benannt sind? Und sonst, wie sieht das aus? Irgendwie 0x0000xxx = 0x0000xxx; Sorry das geht mir zu tief, bzw. weiss nicht wo anfangen... Beispiele wären cool, da kommt man dann schnell rein.
Datenblatt finden und lesen. https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf Chapter 2.19 scheint wohl der GPIO Teil zu sein. geht das so?: 0x40014000 = 0x1000 //bit13 setzen, Dann ist GPIO0 als Ausgang definiert :-D ?
Du suchst im Datenblatt nach SIO (Single-cycle IO) bzw. Atomic Register Access. Umschalten eines Portpins dauert bei 125MHz dann lediglich 8ns.
Nö. Es gibt sicher Headerfiles im Compiler vom Arduino, wo die Register per Namen ansprechbar sind.
Wozu glaubst du, das tun zu müssen? Gerade auf dem Raspberry PI Pico ist das setzen der IOs so schnell, da kann man in den allermeisten Fällen das einfache digitalWrite() bzw. pinMode() nehmen. Das dauert vermutlich weniger als 1 us.
Mein Gott, ab Seite 29 stehen FERTIGE C-Funktionen, die GENAU DAS tun was der OP will. Man muss sie nur kopieren! Ob das Gen-Z noch hinkriegt?
ne glaube ich nicht, bei ca. 400..500KHz ist Schluss....
Kannst ja Mal in das RP2040 SDK reinschauen wie die das machen. Auch wenn du es nicht verwenden möchtest. https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#hardware_gpio https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_gpio/gpio.c Da siehst du dass das gpio_put() auf ein gpio_set_mask() oder gpio_clr_mask() rausläuft. Was wiederum ein sio_hw->gpio_set = mask; bzw sio_hw->gpio_clr = mask; macht.
Nein. So aber vielleicht: *((unsigned int *)0x40014000) = 0x1000; Wenn da wirklich ein Register liegt die auch mit 32 bit beschreibbar ist und man keine Speicher oder Register Protektion aktiv hat (wenn es auf dem Ding sowas gibt) dann müsste das klappen.
Sagt wer? Du?
ja, hatte ich mit gpio_put() getestet... irgendwie sehr lahm, aber wohl dem MUX geschuldet..
Das Glauben überlassen wir doch besser den Klerikern. Die haben Jahrhunderte lange Übung im alles Glauben und nichts Wissen. Uns reicht da schon ein Blick auf's Oszilloskop. ;-)
Wer viel mißt, mißt Mist. Sooo, mal wieder wurden die urban legends widerlegt. Siehe Anhang. Als zufälliger Besitzer eines RP2040 hab ich einfach mal gemessen. Pin wackeln in Endlosschleife. Laut Arduino-IDE läuft die CPU mit 133 MHz. digitalWrite() ~ 800kHz Register set/clr ~33MHz(!) Register togl ~ 22MHz(!) Sollte reichen. Da kommt mein olles DS1052 schon an seine Grenzen!
Mach das mal mit Assembler. Da ist noch ne gewaltige Menge Luft nach oben. In einer Endlosschleife addieren sich die Zeit des str[hb] Befehls auf die SIO (XOR) und der branch Befehl. Wenn du die Flash-delays raus haben möchtest, dann noch im RAM laufen lassen. Da war selbst mein 50MHz anal. Philips überfordert. Konnte nur im time x10 etwas sehen.
Nö. Die 2. Version braucht 4 (VIER) CPU-Takte für die gesamte Schleife!
Genau, anal. Voll für den Arsch! ;-)
33% zu viel! Laut Datasheet braucht der str[bh] Befehl nur einen Takt für SIO Operationen und der unconditional branch nur zwei. Macht Drei. Also 41 2/3 MHz. (bei 125) Wenn man den branch mal vergisst, im Sinne eines Loop unroll, dann kann man also mit einem Taktzyklus toggeln. Ergo 8ns. Ps. Man sieht's auf dem Scope, man kann's messen, sieht nur nicht mehr so schön aus. ;-) ziemlich sinnfrei diese ständigen Pintoggle Rekorddiskussionen. Der RP2040 hat die PIO, für schnelle Spezialaufgaben macht es mehr Sinn sich damit zu beschäfftigen.
Ich weiß es ;-) Zunächst müssen einige Initialisierungen passieren, ob Eingang oder Ausgang, Pullup oder Pulldown, ggf. Stromstärke oder Schmitttrigger. Dafür kannst Du wohl die Arduino-Befehle verwenden. Um sehr schnell einen Ausgang zu setzen oder zu löschen, gibt es spezielle Adressen, die ein atomares SET, CLEAR oder XOR durchführen. Diesen Adressen haben einen Offset zur Basisadresse und man findet sie beispielsweise in RP2040.h. Im Datenblatt findet sich eine kurze Beschreibung auf Seite 18, Kapitel 2.1.2 Beispiel-Code hätte ich auch zu bieten, wenn es notwendig sein sollte.
Schon mal die anderen Beiträge gelesen? Du bist Stunden zu spät, außerdem ohne Substanz (Beispiele).
Nein, finde ich gar nicht. Hier geht es einzig und allein darum, falsche von richtigen Informationen zu trennen. Und während ich ausgesprochen gerne die PIO Statemachines nutze, alles kann man mit den zwei mal 32 Instruktionen auch nicht erledigen.
Beitrag #7401336 wurde von einem Moderator gelöscht.
Kleine Ergänzung. Die Funktionen aus der Doku des RP2040
gibt es schon in den Untiefen der Includes im gcc für den RP2040. Kann man ohne zusätzliche #include nutzen. Mit konstanten Argumenten wird das auch so weit optimiert, daß der einzige Registerzugriff übrig bleibt, die Schleife ist so schnell wie der Test 2 mit den direktem Registerzugriff!
Wenn man mit variablen Argumenten arbeitet, was ich hier mal mit einer volatile Varible erzwungen habe, wird es langsamer, aber immer noch SEHR flott! Umschaltfrequenz ~11MHz, d.h. ein Funktionsaufruf dauert ca. 40ns!
Ich hätte erwähnen sollen, dass es mir darum geht mehrere Pins gleichzeitig zu toggeln (oder min. 10pins). Mit gpio_put_all habe ich nur paar 100KHz erreicht. Messung kann ich ggf. am Nachmittag nachreichen.
Tja, und schon wieder versagt Gen-Z kläglich. Schon mal über die Wirkungsweise der Funktionen gpio_set_mask(uint32_t mask) nachgedacht?
Tja . . .
Ein Codeschnipsel für direkte Zugriffe.
Kann ich nicht bestätigen. Bei mir sind es mit deinem Code in einer while(true) um die 13.8MHz bei Debug und ca. 31.25MHz mit Release (siehe Anhang). Verwendeter Code:
Geb dir mal den CLK_SYS an einem Pin aus. Hier ein Beispiel am PIN21 (Achtung, da geht nicht jeder Pin). Geteilt durch 10.0f damit man es besser messen kann.
Bei mir messe ich dann 12.5MHz, also 125MHz als Sys-Clock. Was anscheinend Default ist. Die Zeiten vom Anhang werden also noch leicht schneller sein wenn man auf die erlaubten 133MHz erhöht. Und wie schon oben gesagt: Soll es noch schneller sein nimm eine PIO. Das hier duerfte so ziemlich die Minimalversion sein: https://github.com/dwelch67/raspberrypi-pico/tree/main/blinker00 Und ja, es ist natuerlich schon schoener wenn man sich ein Headerfile mit den Registern besorgt. .-) Was leider fuer Anfaenger etwas verwirrend ist das ist dieser zweistufige Bootprozess mit Pruefsumme. Deshalb schaut euch das was dwelch67 da gemacht hat genau an. Das erleichtert den Einstieg ernorm. Vanyo
Einen habe ich noch übrig.
Nicht unbedingt schneller aber auf jeden Fall komplizierter.
Ja, einen an der Waffel. Keiner braucht dein 2,4MB Headerfile, da ist bei jedem Compiler schon dabei.
Bei meinem nicht. Ich musste mir das aus der kranken Entwicklungsumgebung der RP2040 macher rausklauen. Vanye
Vielen Dank für diese Hinweise. Ich verwende platformIO / Arduino mit folgendem Setup, und im Anhang die Messung. Das Signal ist komisch, aber immerhin jetzt mehr als paar 100kHz, d.h.: gpio_put_all: unsymetrisches Signal ca. 7.3MHz sio_hw->gpio_set u. clr: unsymetrisches Signal ca. 6.9Mhz sio_hw->gpio_togl: symetrisches Signal ca. 3.6MHz
Code:
Gibt es nicht bei mir.
Hier ist dein Fehler. Loop wird zwar dauerhaft ausgeführt, ist aber eine Funktion, die aufgerufen wird. Ein while(1) {} ist da schneller.
Tatsächlich, Signal ist immer noch nicht schön symetrisch aber jetzt bei 31 Mhz mit put_all.... Tolle Sache :-) Hier mal eine gescheite HF-Messung des IO-Pins. Gemessen mit einem nagelneuen LeCroy Wavesurfer 4054HD (500MHz, 5 Gs/s, 12Bit) und einem selbstgebauten Z0-Tastkopf mit 1k Eingangswiderstand. Die IOs sind RATTENSCHNELL! Dargestellte Anstiegszeit ca. 1ns, davon sind aber ca. 0,7ns schon das Oszi! (toszi~0,35/f3dB). tr = Wurzel (tg^2 - toszi^2) = Wurzel (1ns^2-0,7ns^2) = 0,7ns Alter Schalter! Die beiden ersten Messungen wurden mit interner Terminierung mit 50 Ohm gemacht, da hat man schon eine sehr gute Signalqualität. Die dritte Messung mit externer Terminierung an einem T-Stück und Oszi auf 1M Eingangswiderstand. Das ist DEUTLICH schlechter! Ob das am schon etwas älteren, leicht oxidierten T-Stück oder dem Oszi liegt, ist unklar.
Wenn Du 100 MHz brauchst, lass den RP2040 mit 4xx MHz laufen. Ich denke, jetzt ist der Zeitpunkt gekommen, zu sagen, was das ganze überhaupt soll. Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|