8 UART's mit asm_pio PIO DMA / Micropython auf dem PI PICO
Worum geht es hier ?
Der PI PICO verfügt von Haus aus über 2 integrierte UART-Schnittstellen,
von denen eine meist für die Programmierung genutzt wird.
Mit den PIO's kann man bis zu 8 zusätzliche UART-Schnittstellen
(alternativ als Transmitter oder Receiver) an frei wählbaren Pins des PI
PICO einrichten - zusätzlich zu den vorhandenen beiden Schnittstellen.
Es folgen drei Versionen der Schnittstelle, die ersten beiden entstanden
bereits im Zusammenhang mit meinen "Spielereien mit asm_pio +
Micropython auf dem PI PICO".
Hier ging es darum auszuprobieren, was man mit den PIO's anstellen kann.
Die dritte und neue Version nutzt DMA für den Datentransfer mit den
PIO's.
Version 1 sendet bis zu 9 Byte nonblocking.
Der Empfang wird per Interrupt abgewickelt:
nach jedem empfangenen Byte wird eine ISR ausgeführt, die das empfangene
Byte abholt.
Die Software muss selbst erkennen, wann ein Datentransfer abgeschlossen
ist.
Eine weitere Variante erkennt das Übertragungsende (am Ausbleiben eines
weiteren Startbits).
Das Problem dieses Konzeptes ist, dass viele Interrupts ausgelöst
werden.
Micropython kann diese aber bei höheren Baud-Raten nicht mehr schnell
genug bedienen, so dass irgendwann Datenverluste drohen und auch das
laufende Programm ausgebremst wird.
Für moderate Baud-Raten und wenig zeitkritische Anwendungen funktoniert
das aber zufrieden stellend.
Ansatz der 2. Version war, die 32-Bit-Fifos der Statemachines als Puffer
zum Senden und Empfangen besser zu nutzen und damit die Anzahl der
erforderlich Interrupts zu reduzieren.
Die Beschränkung liegt hier im 32-Byte-Limit.
Der asm_pio-Code des Receivers belegt das gesamt Insturktion-Memory. Und
die Nachbereitung der empfangenen Daten ist etwas mühsam.
Zwischenzeitlich gibt es diverse Beiträge im Web, die aufzeigen, wie
PICO's DMA auch unter Micropython nutzbar ist.
DMA bietet den Vorteil, dass nicht nur die Statemachines, sondern auch
der Datentransfer im Hintergrund ablaufen..
Der Programmcode sieht auf den ersten Blick aufwändiger aus - aber das
täuscht.
Wenn Interesse besteht - weitere Erläuterung gibt's in der Anlage in der
readme.pdf.
Michael S.
Hier noch ein kleiner Nachtrag:
Es hatte mich einen guten ganzen Tag gekostet, ein unerwartetes
Verhalten der Statemachines zu beseitigen, leider zunächst ohne die
Ursache zu verstehen:
Immer dann, wenn mehrere Instanzen eines Receivers gestartet werden
sollten, arbeitete nie mehr als eine einzige Instanz auf jedem
PIO-Block.
Das heißt, manchmal schon - aber nicht mehr nach einem Reset.
Ein Blick in die Register zeigte merkwürdige Unterschied in den
Registern
- SMx_ADDR Register
- SMx_INSTR Register
Bei den nicht funktionierenden Statemachines waren die Register nicht
gesetzt.
Kopieren der Registerinhalte von der arbeitenden SM auf die anderen
brachte keine Veränderung.
Erst durch den Vergleich des Programmcodes mit meinen funktionierenden
Beispielen in den "Spielereien" entpuppte sich am Ende als Verursacher
das "statemachine.restart()".
Ohne selbiges funktionierte alles wie erwartet.
Ich habe mir das heute noch einmal genauer angesehen und das restart()
ohne Micropython durch Setzen der entsprechenden Bits in den
Controll-Registern ausgeführt.
Das funktioniert.
Sollte da ein Bug im "restart()" stecken ?
Den Programmcode meines Testes füge ich mal an Anlage bei.
Michael S.
23.07.2022
Michael S. schrieb:> Der PI PICO verfügt von Haus aus über 2 integrierte UART-Schnittstellen,> von denen eine meist für die Programmierung genutzt wird.
Ähem, nein, warum sollte man das tun? Es gibt doch SWD. Darüber kann man
dann auch debuggen und nicht nur programmieren.
Interssantes Projekt. Leider gibt es hier immer zu wenig Leute, die sich
für ein spezielles Thema interessieren. An deiner Stelle würde ich es
auf GitHub hochladen, dann kannst du auch sehen, wie viele Zugriffe es
gibt.
Das gab es hier im Forum auch mal, aber leider haben sie es abgestellt.
Noch ein letzter Nachtrag zu den UART-DMA-Varianten.
Mit dem Inline-Assembler hatte ich bislang noch nicht gearbeitet - und
so ist mir anfangs nicht aufgefallen, dass man in einigen Instruktionen
Konstanten verwenden kann (z.B. beim Shiften und Addieren).
Damit werden einige mov's überflüssig.
Bei der Gelegenheit habe ich auch die DMA_BASE-Adressen, die bislang per
Parameter übergeben wurden, direkt in den Programmcode eingebaut.
Die (interne) Funktion "bit_reverse_8()" unterscheidet zwischen Source-
und Targetadresse. Das Wechseln zwischen zwei unterschiedlichen
Empfangsarrays kann dadurch entfallen.
Diese Änderungen betreffen nur Objekt-Interna, nach außen bleibt alles
gleich.
Michael S.
25.07,2022
Hallo,
häufig denkt man komplizierter als erforderlich.
So war meine schlaue Überlegung gewesen:
Will man ein empfangenes Byte in ein Register der Statemachine
schreiben,
dann shiftet man es normalerweise von links nach rechts rein.
Um die Daten per DMA abzuholen, benöitgt man daher ein Array aus 32-Bit
Variablem.
Das ist wenig effizient.
Um Platz zu sparen, habe ich die Bits von rechs nach links in das
niedrigstweritige Byte geshiftet - und konnte es so mit 8-Bit Variablen
auslesen:
Dummerweise wird dabei die Bit-Reihenfolge verdreht.
Das musste eine Inline-Assembler-Routine richten.
Dabei geht es viel einfacher.
Die Statemachine kennt keine direkte Instruktion zum Shiften.
Aber man kann aus einer beliebigen Quelle Bits ins ISR shiften.
Ausgangspunkt (8 Bit empfangen):
Mit "in_(x, 24)" werden 24 (zufällige) Bits z.B, aus dem X-Register
hinterher geschoben - und schon passt die Byte-Position und die
Bit-Reihenfolge.
1
-> 24 Bit -> xxxx_xxxx-xxxx_xxxx-xxxx_xxxx-8765_4321
Was im "x" steht, das interessiert nicht, es wird ja nicht ausgelesen.
Mit Hilfe von "autopush" bleibt sogar die Anzahl der benötigten
Instruktionen unverändert.
Und das Invertieren der Bitreihenfolge entfällt.
Einfach ist eben einfach einfacher.
Michael S.
04.08.2022
Interessantes Projekt! Ich hatte bisher den PI pico als "Spielzeug"
abgetan. Nachdem ich mich nun genauer mit deinen Quelldateien und dem
Datenblatt beschäftigt habe wird mir dieser immer sympathischer. Es kann
gut sein, dass wir unsere STM32F0 durch den PI pico ersetzen. Vor allem
sind diese lieferbar.
Wenn etwas in der heutigen Zeit im Status:
> Vor allem sind diese lieferbar.
ist, wuerde ich eher von einer gewissen "Zurueckhaltung"
bei der Verwendung ausgehen.
Der Bastlermarkt macht den Kohl eben nicht fett.
Und in der Industrie scheint er, aus was fuer Gruenden auch immer,
nicht anzukommen.
Cartman schrieb:> Und in der Industrie scheint er, aus was fuer Gruenden auch immer,> nicht anzukommen.
Mag noch kommen – und sei’s eben nur aufgrund der Marktlage. Die
interessante Frage ist: sollte das kommen, können sie dann die Nachfrage
bedienen? Was jetzt zu haben ist, ist ja nur deswegen zu haben, weil es
[noch] keine große Nachfrage aus dem kommerziellen Bereich gibt, in dem
ordentliche Mengen umgesetzt werden.
Cartman schrieb:> Und in der Industrie scheint er, aus was fuer Gruenden auch immer,> nicht anzukommen.
Liegt vermutlich am nicht integrierten FLASH. Das war bei mir bisher der
Grund. Der vermeintliche Nachteil kann aber auch vorteilhaft sein.
Erstens ist externer QSPI-Speicher in der Regel günstiger und es müssen
nicht verschiedene µC-Derivate vorgehalten werden. Es wird einfach der
benötigte FLASH dazu bestückt. Der interne RAM ist bei PI pico eher
üppig.
Cartman schrieb:> Und in der Industrie scheint er, aus was fuer Gruenden auch immer,> nicht anzukommen.
Oh' doch. Aber Entwicklung braucht halt Zeit, insbesondere, wenn man von
einer unnötig fetten MCU-Sau mit lausig hingerotzter "mir gehört die
Welt"-Software auf was Schlankeres migrieren muss.
Zu "alten Zeiten" war sowas nicht durchsetzbar. Jetzt werden die BWLer
durch die Umstände dazu gezwungen, auch über sowas nachzudenken. Naja,
und auf einmal geht dann doch was.
Worauf sich die BWLer aber noch nicht so richtig eingestellt haben, ist
die wenig überraschende Tatsache, dass der Entwicklungsaufwand deutlich
hochgeht, wenn die Resourcen knapp werden. Aber: noch'n Winter und auch
die kommen dahinter...
Michael S. schrieb:> Der PI PICO verfügt von Haus aus über 2 integrierte UART-Schnittstellen,> von denen eine meist für die Programmierung genutzt wird.
Falsch. Beide UARTs sind frei, die Programmierung erfolgt auf separatem
Wege über USB.
Transputer schrieb:> Ich hatte bisher den PI pico als "Spielzeug" abgetan
Naja, Micropython in seinem aktuellen Status würde ich diesen Status
durchaus verpassen. Das Zeug läuft trotz vieler guter Ansätze
zeitverschwenderisch code-interpretierend, meist single-threaded und
noch lange nicht ausgereift und robust.
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang