Zugriff auf Redd Tyres auf FTDI-Brücken

Wir haben einen großen theoretischen Block abgeschlossen, in dem gezeigt wird, wie ein FPGA-Subsystem für den Redd-Komplex erstellt wird. Wie organisiert man die Kommunikation zwischen dem FPGA und dem zentralen Prozessor des Komplexes? Wie einfach ist es, Hochgeschwindigkeitsdatenströme im RAM zu speichern, das direkt mit dem FPGA verbunden ist, um sie anschließend gemächlich an den Zentralprozessor zu übertragen (oder umgekehrt, um Daten in diesem RAM für die anschließende schnelle Ausgabe an den Kanal zu speichern). Wir haben die Verfolgungstechniken des Nios II-Prozessors überprüft. Wir sind in der Lage, die Leistung des auf Nios II basierenden Prozessorsystems so zu optimieren, dass die Arbeit so effizient wie möglich verläuft. Im Allgemeinen haben wir alle notwendigen Minimum-Theorien studiert, und es wäre an der Zeit, mit der Praxis fortzufahren, indem wir ein nicht sehr komplexes, aber praktisch nützliches Gerät entwerfen ... Aber es gibt ein ABER.

Aus den Kommentaren zu den Artikeln ging hervor, dass einige Leser glauben, Redd und FPGA seien wie Lenin und die Partei. Dass sie untrennbar miteinander verbunden sind. In der Tat ist dies überhaupt nicht so. Ich wollte nur ein Gespräch über den Redd-Komplex mit etwas Interessantem beginnen, aber was könnte interessanter sein als FPGA? Nun, und ein Gespräch zu beginnen, auf einen Blick zu unterbrechen, ist dumm. Und schließlich ist der große logische Block abgeschlossen. Und um zu zeigen, dass FPGAs weit von Redd entfernt sind, schlage ich vor, ungefähr drei Artikel über Dinge zu verfassen, die nichts damit zu tun haben. Nun, und nachdem Sie diesen Block abgeschlossen haben, gehen Sie bereits zur FPGA-Praxis.



Einleitung


Das Erstaunlichste ist, dass mich die guten Chefs, sobald ich mich zu einem Exkurs zu anderen Themen entschlossen hatte, in eine schwierige Auseinandersetzung mit einem Projekt gestürzt haben, an dem mit der VHDL-Sprache und Xilinx-FPGA gearbeitet wird. Zum einen habe ich deshalb lange Zeit keinen Stift mehr in die Hand genommen, und zum anderen ist klar, dass die Erstellung von praktischen Artikeln eine Vielzahl von Experimenten erfordert. Es ist etwas schwierig, gleichzeitig mit VHDL / Verilog und Xilinx / Altera umzugehen. Ein Bruch in den Geschichten über FPGAs müsste also trotzdem gemacht werden.

Also Im ersten Artikel der Reihe haben wir bereits das Strukturdiagramm des Redd-Komplexes untersucht. Lass es uns noch einmal tun.



In dem heutigen Artikel werden Linux-Experten wahrscheinlich keine wertvollen Informationen finden, aber es lohnt sich, die Bilder oberflächlich zu betrachten. Diejenigen, die wie ich an die Arbeit mit Windows gewöhnt sind, finden eine Liste vorgefertigter Techniken, mit denen Sie mit dem Komplex arbeiten können. Im Allgemeinen wird dieser Artikel die Fähigkeiten dieser und anderer Lesergruppen auf einen Nenner bringen.


UART-Blöcke (serielle Ports)


Im Blockdiagramm sehen wir den FT4232-Controller, der 4 serielle Ports (UART) implementiert:



Wenn Sie jedoch globaler sprechen, verfügt der Redd-Komplex nicht über vier, sondern über sechs serielle Anschlüsse. Die gerade erwähnten vier haben CMOS-Ebenen und zwei weitere sind auf der Hauptplatine verlötet, da der Komplex auf einem normalen PC basiert.



Dementsprechend haben sie Pegel - RS232 (plus oder minus 12 Volt). RS232-Ports - alles ist klar, sie werden in Form von zwei Standard-DB-9-Anschlüssen angezeigt.



und wo nach Leitungen mit CMOS-Pegeln suchen? Im Allgemeinen - an einem gemeinsamen Anschluss. Die Belegung ist im Stromlaufplan dargestellt. Es gibt unter anderem Kontakte, die UART entsprechen.



Äußerlich sieht dieser Anschluss folgendermaßen aus:



Wie man es benutzt, hängt von der jeweiligen Aufgabe ab. Sie können für jedes Gerät einen Kabelbaum erstellen. Dieser Ansatz ist nützlich, wenn jemand den Redd-Komplex verwendet, um regelmäßig hergestellte Geräte der gleichen Art zu testen. Der Hauptzweck des Komplexes ist jedoch immer noch das Debuggen der zu entwickelnden Ausrüstung. In diesem Fall ist es einfacher, eine temporäre Verbindung herzustellen. Dieses vorübergehende Muster ist auf Bildschirmschonern für alle Artikel sichtbar: Aruino-Drähte werden direkt in den Stecker eingeführt. Natürlich ist das Zählen von Kontakten immer noch ein Vergnügen, und wenn sie versehentlich abbrechen, ist es so schwierig, das Umschalten wiederherzustellen, dass es einfacher ist, alles von Grund auf neu zu verbinden. Um das Leben zu erleichtern, gibt es daher eine Riser-Platine, an die Sie mindestens mit Hilfe von zweireihigen Steckverbindern, mindestens mit derselben Arduino-Verdrahtung, anschließen können.



UART-Softwarezugriff


Die serielle Schnittstelle ist ein gut etabliertes und standardisiertes Element. Die Arbeit mit ihr erfolgt daher nicht über bestimmte FTDI-Bibliotheken, sondern über Standardverfahren. Schauen wir uns an, wie diese Tools unter Linux aussehen.

Portnamen


Aus einer Reihe von Artikeln und Foren im Netzwerk geht hervor, dass die von USB-Serial-Adaptern bereitgestellten Portnamen im Format / dev / ttyUSB0, / dev / ttyUSB1 usw. vorliegen. Unter Linux können alle Geräte mit denselben Befehlen angezeigt werden wie normale Verzeichnisse (Geräte sind nämlich dieselben Dateien). Mal sehen, welche Namen in unserem System sind. Wir geben den Befehl:
ls / dev /



Die Namen, die uns interessieren, sind rot hervorgehoben. Etwas viel von ihnen. Welcher Port entspricht was? Wer sich mit Linux auskennt, kennt Tausende von Zaubersprüchen für alle Fälle. Aber für diejenigen, die immer noch mit Windows 3.1 gearbeitet haben (nun ja, parallel zu der damals recht peppigen alten Frau RT-11), ist es immer noch schwer, sich zu erinnern, mit zunehmendem Alter ist es schwieriger, sich an die neue zu erinnern. Daher ist es auf einfache Weise einfacher, jedes Mal alles zu finden. Und ich habe den Eingang zu diesem einfachen Pfad mit einem grünen Rahmen hervorgehoben. Bedingtes Unterverzeichnis serial. Jetzt schauen wir uns den Namespace / dev / an . Und sehen wir uns das Leerzeichen / dev / serial an :



Großartig! Wir vertiefen uns in die Hierarchie, schauen uns das Leerzeichen / dev / serial / by-id an . Wenn Sie nur nach vorne schauen, sage ich, dass Sie für die korrekte Anzeige den Befehl ls mit der Option –l verwenden müssen (danke an meinen Chef für die Klarstellung). Das heißt, wir geben den Befehl:
ls –l / dev / serial / by-id



Einerseits ist alles in Ordnung. Jetzt wissen wir, welche Namen im Space / dev / ttyUSBX welchem ​​Gerät entsprechen. Von der FT4232 (Quad) Bridge organisierte Ports haben insbesondere Namen von ttyUSB3 bis ttyUSB6 . Andererseits habe ich bei der Betrachtung dieser Website festgestellt, dass es in Paris in der Kammer der Gewichte und Maße unbedingt einen Raum geben muss, in dem der Standard des Chaos liegt ... Denn irgendwie muss man in der Lage sein, seinen Wert zu messen. Nehmen wir an, das Fehlen der Ports / dev / ttyUSB0 und / dev / ttyUSB1 kann leicht erklärt werden. Aber wie lässt sich erklären, dass die "nativen" Ports, die auf den Nachkommen der installierten FTDI-Bridge basieren, von den ersten drei nummeriert sind und der für ein bestimmtes Projekt eingefügte Prolific-Controller eines Drittanbieters die Portnummer 2 hat? Wie kann man in einer solchen Umgebung arbeiten? Morgen wird jemand einen anderen Controller an den Komplex anschließen (da der Komplex es verschiedenen Entwicklergruppen ermöglicht, gleichzeitig mit verschiedenen Geräten zu arbeiten), und die Anschlüsse werden wieder freigegeben. Welche Ports müssen in der Konfigurationsdatei für eine funktionierende Anwendung registriert werden?

Es stellt sich heraus, dass nicht alles so schlimm ist. Erstens sind der gelbe Name / dev / ttyUSB3 und der blaue Name / dev / serial / by-id / usb-FTDI_Quad_RS232-HS-if00-port0 zwei Aliase desselben Geräts. Die zweite Option kann auch als Portname angegeben werden, ist aber bereits dauerhafter als die erste. Es stimmt, in diesem Fall ist alles etwas schlecht. Ein externer Controller, der auf FT4232 basiert, kann an den Komplex angeschlossen werden, und es ist bereits erforderlich, sich mit deren Nummerierung zu befassen. Und hier kommt uns "zweitens" zu Hilfe. Nämlich eine andere alternative Namenskonvention. Wir erinnern uns, dass das Verzeichnis / dev / serial nicht nur das Unterverzeichnis / by-id enthielt, sondern auch das Unterverzeichnis / by-path . Wir überprüfen den Inhalt (er befindet sich am unteren Rand der nächsten Abbildung unter einer roten Linie).



Alles hier ist an die physische Architektur gebunden. Und ich habe bereits viele Male gesagt, dass alle Controller im Komplex an die Platinen gelötet sind, sodass sich die interne Hierarchie nicht ändert. Daher ist der Name /dev/serial/by-path/pci-0000:00:15.0-usb-0:6.5:1.0-port0 der schwierigste.

Insgesamt haben wir folgende Möglichkeiten, um nach dem Portnamen zu suchen (sollte einmal durchgeführt werden, die Ergebnisse für Ihre Instanz des Komplexes können in die Tabelle eingetragen und ständig verwendet werden):

  1. Geben Sie den Befehl ls –l / dev / serial / by-id ein .
  2. Geben Sie den Befehl ls –l / dev / serial / by-path ein .
  3. Suchen Sie aus den Ergebnissen von Punkt 1 den Portnamen, der dem erforderlichen Port der erforderlichen Bridge entspricht. Suchen Sie den gleichen Anschlussnamen in den Ergebnissen von Absatz 2. Nehmen Sie den physischen Namen, der diesem Absatz entspricht.

Bei den Ports, die vom Controller auf dem Motherboard bedient werden, ist alles etwas komplizierter. Hier können Sie den Weg vom einfachsten Befehl " ls / dev " nicht zurücklegen , aber Sie müssen sich an etwas erinnern (oder zumindest daran, dass Sie sich hier an uns wenden können, um Hilfe zu erhalten). Überall heißt es, dass die typischen Portnamen ttyS0-ttyS3 sind . Es bleibt die Frage, auf welchen Namen sich die realen Ports in unserem System befinden. Ich habe den folgenden Spruch gefunden, der diese Frage beantwortet:
ls / sys / class / tty / * / device / driver

Hier ist die Antwort des Systems:



Es stellt sich heraus, dass wir die Namen / dev / ttyS2 und / dev / ttyS3 verwenden müssen . Warum - ich weiß es nicht. Eines ist jedoch erfreulich: Hier sind keine besonderen Änderungen vorgesehen, sodass diese Konstanten gespeichert und verwendet werden können, ohne befürchten zu müssen, dass sie sich ändern werden.

Code-Entwicklung


Bei der Entwicklung sollten Sie das wunderbare Handbuch zur seriellen Programmierung für POSIX-Betriebssysteme verwenden (der erste direkte Link, den Sie erhalten, lautet https://www.cmrr.umn.edu/~strupp/serial.html , aber niemand weiß, wie lange es hält). Es ist besonders wichtig, dass Sie wissen, wie Sie mit einem vollständigen Satz von Signalen arbeiten, da die Ports im Komplex vollständig implementiert sind. Es ist wahr, heute werden wir nur die Tx- und Rx-Leitungen verwenden.

Normalerweise gebe ich die Ergebnisse des Oszillogramms an, aber jetzt stellt sich heraus, dass ich mich in einem nahezu realen Zustand befinde: Der Komplex befindet sich dort, wo meine Hände nicht reichen, sodass ich den Oszilloskop-Tastkopf nicht anschließen kann. Um zumindest einige Ergebnisse zu sehen, haben Kollegen auf meine Bitte hin dem Komplex einige Einträge nach dem folgenden klassischen Schema hinzugefügt:



Versuchen wir, von einem Port auf einen anderen zu übertragen. In unserem Fall sind die Ports /dev/serial/by-path/pci-0000:00:15.0-usb-0:6.5:1.2-port0 und /dev/serial/by-path/pci-0000:00:15.0- verbunden usb-0: 6.5: 1.3-port0 .

Wie Programme für den Redd-Zentralprozessor geschrieben werden, haben wir bereits in einem der vorherigen Artikel besprochen. Deshalb beschränken wir uns heute nur auf den Programmtext, der unter dem Eindruck des Dokuments Serial Programming Guide für POSIX-Betriebssysteme geschrieben wurde . Tatsächlich ist der wichtigste interessante Punkt die Umstellung der Empfangsstrategie auf blockierungsfreies Lesen, der Rest ist trivial. In Anbetracht der Unordnung in den Beispielen im Netzwerk zu diesem Thema ist es jedoch besser, ein einfaches Beispiel zur Hand zu haben (es wird später gezeigt, dass selbst ein Beispiel, das auf diesem wunderbaren Dokument basiert, nicht zu 100% funktioniert hat, der folgende Code unterscheidet sich von den darin beschriebenen Kanonen in einer Zeile, aber mehr dazu weiter unten).

Der gleiche Beispielcode
#include <cstdio> #include <unistd.h> /* UNIX standard function definitions */ #include <fcntl.h> /* File control definitions */ #include <errno.h> /* Error number definitions */ #include <termios.h> /* POSIX terminal control definitions */ int OpenUART(const char* portName, speed_t baudRate) { //   int fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY); //     if (fd == -1) { return fd; } //     fcntl(fd, F_SETFL, FNDELAY); //    termios options; tcgetattr(fd, &options); // ,       // ,   .  ... cfsetspeed(&options, baudRate); //    ... // 1  ,   , 8    options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_cflag |= (CLOCAL | CREAD); // , ... tcsetattr(fd, TCSANOW, &options); return fd; } int main() { printf("hello from ReddUARTTest!\n"); int fd1 = OpenUART("/dev/serial/by-path/pci-0000:00:15.0-usb-0:6.5:1.3-port0", 9600); int fd2 = OpenUART("/dev/serial/by-path/pci-0000:00:15.0-usb-0:6.5:1.2-port0", 9600); if ((fd1 != -1) && (fd2 != -1)) { static const unsigned char dataForSend[] = {0xff,0xfe,0xfd,0xfb}; //      write(fd1, dataForSend, sizeof(dataForSend)); unsigned char dataForReceive[128]; ssize_t cnt = 0; //     ,  , //         int readSteps = 0; //      ,   while (cnt < (ssize_t)sizeof(dataForSend)) { readSteps += 1; ssize_t rd = read(fd2, dataForReceive + cnt, sizeof(dataForReceive) - cnt); //   - ,     if (rd <= 0) { usleep(1000); } else //  -   { cnt += rd; } } //   printf("%d read operations\n", readSteps); printf("Read Data: "); for (unsigned int i = 0; i < cnt; i++) { printf("%X ", dataForReceive[i]); } printf("\n"); } else { printf("Error with any port open!\n"); } //   if (fd1 != -1) { close(fd1); } if (fd2 != -1) { close(fd2); } return 0; } 


Laufen - wir erhalten das vorhergesagte Ergebnis:

 hello from ReddUARTTest! 14 read operations Read Data: FF FE FD FB 

Es ist ersichtlich, dass 4 Bytes 14 Versuche in Anspruch nahmen, das heißt, das Lesen wurde nicht blockiert. Manchmal gab das System den Status "Keine neuen Daten" zurück und das Programm ging für eine Millisekunde in den Ruhezustand.

Im Allgemeinen ist alles in Ordnung, aber ohne ein Oszilloskop kann ich nicht sicher sein, dass zwei auf demselben Chip basierende Ports die Geschwindigkeit wirklich festlegen. Ich bin bereits auf die Tatsache gesprungen, dass die Geschwindigkeit die gleiche war (dafür hatte er einen Controller), aber nicht den, den ich bestellt habe. Lassen Sie uns zumindest irgendwie überprüfen, ob es zumindest kontrolliert wird. Dazu stelle ich die Geschwindigkeit des Empfangsanschlusses auf das Doppelte der Geschwindigkeit des Sendeanschlusses ein. Wenn Sie die Physik des Datenübertragungsprozesses kennen, können Sie vorhersagen, wie diese Daten während des Empfangs verzerrt werden. Betrachten wir die Übertragung des 0xff-Bytes in grafischer Form. S - Startbit (es gibt immer Null), P - Stopbit (es gibt immer Eins), 0-7 - Datenbits (für die Konstante 0xFF - alle Einheiten).



Überlagern wir diese Ansicht nun mit der Ansicht, wie alles von einem Empfänger angezeigt wird, der mit der doppelten Geschwindigkeit arbeitet:



Großartig. Der Wert "1111 1110" sollte akzeptiert werden (die Daten gehen das niedrigstwertige Bit vorwärts), dh 0xFE. Die zweite Hälfte des übertragenen Wertes hat keinen Einfluss auf den Empfang, da die Einheiten der Stille in der Leitung entsprechen. Das heißt, wir haben ein Byte übertragen, ein Byte wird auch kommen.

Wir werden zur Verifizierung das gleiche Diagramm erstellen, das dem übertragenen 0xFE-Wert entspricht:



Erwarten Sie den Wert "1111 1000" oder 0xF8. Nun, lassen Sie uns überprüfen, was mit dem übergebenen Wert 0xFD zu erwarten ist:



Wir bekommen den Wert 0xE6. Nun, für den übertragenen Wert 0xFB erhalten wir den empfangenen 0x9E (Sie können die Grafik zeichnen und selbst sehen). Großartig! Wir ändern eine einzelne Zeile in der Testanwendung und ersetzen die Geschwindigkeit von 9600 durch 19200:

  int fd2 = OpenUART("/dev/serial/by-path/pci-0000:00:15.0-usb-0:6.5:1.2-port0", 19200); 

Wir fangen an und bekommen dieses Ergebnis der Arbeit:

 hello from ReddUARTTest! 9 read operations Read Data: FE F8 E6 9E 

Übrigens habe ich diese Überprüfung nicht vergeblich durchgeführt. Zuerst habe ich andere Geschwindigkeitseinstellungsfunktionen verwendet (cfsetispeed / cfsetospeed pair) und sie haben nicht funktioniert! Dank dieses Tests wurde das Problem rechtzeitig erkannt und behoben. Wenn Sie mit Geräten arbeiten, können Sie nie der Intuition vertrauen. Alles sollte überprüft werden!

Power Line Management 220 Volt


Im Allgemeinen beziehen sich 220-Volt-Stromleitungen nicht auf das Thema des Artikels (FTDI-Brücken), sondern auf das Thema dieses Abschnitts (serielle Schnittstellen). Werfen wir einen kurzen Blick auf sie.



Als wir die Ports aufgelistet haben, sahen wir diesen Namen:



Dies ist eine virtuelle serielle Schnittstelle. Es ist so virtuell, dass es keine Rolle spielt, welche Parameter es hat (Portgeschwindigkeit, Anzahl der Bits, Paritätsformat usw.). Egal welche Parameter er eingestellt hat, er wird immer noch perfekt mit Befehlen umgehen können. Und genau diese Teams steuern die Steckdosen des Komplexes.



Bei der Entwicklung des Befehlssystems wurde beschlossen, auf komplexe Befehlsschnittstellen zu verzichten. Die Verwaltung benötigt ein Byte, ohne Framing-Strings und andere Details, obwohl das Byte in Textform vorliegt (damit es beim Debuggen bequem vom Terminal übertragen werden kann). Diese Prägnanz lässt sich leicht erklären: Über die String-Schnittstelle können Sie Störungen in einem unsicheren UART-Kanal behandeln. In unserem Fall läuft die Arbeit jedoch physisch über den USB-Kanal, der durch zyklische Steuercodes geschützt ist. Die Verarbeitung des Rücklaufs erfordert entweder das Schreiben von zusätzlichem Code oder das permanente Leeren von Puffern, was nicht immer praktisch ist. Deshalb gibt es keine Benchmarks für Strings, es gibt keine Antworten. Es wird angenommen, dass der Kanal stabil ist. Wenn Sie eine Antwort wünschen, können Sie diese explizit anfordern. Das heißt, die Leistung des Blocks kann jederzeit einfach überprüft werden, indem nach dem Befehl ein zusätzliches Byte gesendet wird.

Betrachten Sie die Befehle, die gesendet werden können:
Das teamTermin
'A'Schalten Sie die erste Steckdose ein
'a'Schalten Sie die erste Steckdose aus
'B'Schalten Sie die zweite Steckdose ein
'b'Schalten Sie die zweite Steckdose aus
'C'Schalten Sie die dritte Steckdose ein (falls vorhanden)
'c'Schalten Sie die dritte Steckdose aus (falls vorhanden)
'?'Outlet-Status wiederherstellen

Der Befehl '?' (Fragezeichen) ist das einzige, das eine Antwort zurückgibt. Als Antwort darauf kommen immer 3 Bytes, von denen jedes dem Zustand eines der Ausgänge entspricht. Tatsächlich entsprechen die Zustände den Befehlen. Beispiel: 'abc' - alle drei Ausgänge sind jetzt ausgeschaltet, 'Abc' - der erste ist eingeschaltet, der zweite und der dritte sind ausgeschaltet usw.

Für Experimente mit diesem Subsystem empfehle ich, kein spezielles Programm zu schreiben (es unterscheidet sich nicht von dem oben angegebenen, nur die an die Ports gesendeten Daten sind unterschiedlich), sondern die OS-Tools zu verwenden und interaktiv mit Sockets zu spielen.

Nach vielen Experimenten mit dem Verfolgen des Ports über den Befehl cat und dem Senden von Befehlen in einem parallelen Fenster mithilfe des Echoprogramms wurde mir klar, dass ich aus irgendeinem Grund keine Ergebnisse mit zwei putty-basierten ssh-Terminals erzielen kann (auch wenn ich nur mit diesen Ports spiele dass er perfekt mit seinem Programm experimentiert hat). Daher musste ich das Standard-Minicom-Programm installieren. Ich erinnere Sie an den Installationsbefehl:
sudo apt-get minicom

Führen Sie als Nächstes den folgenden Befehl aus:
minicom –D / dev / ttyACM0

Der Portname ist kurz, da er bei manuellen Experimenten am einfachsten einzugeben ist. In der Software-Arbeit ist es wie immer besser, einen Namen zu verwenden, der an die Hardware-Hierarchie gebunden ist. Wieder einmal stelle ich fest, dass ich keine anderen Portparameter konfiguriere, da es virtuell ist. Es funktioniert mit allen Einstellungen.

Dann drücken wir das Fragezeichen im Terminal und erhalten sofort (ohne Zeilenvorschub) eine Antwort



Dies bedeutet, dass derzeit alle Steckdosen ausgeschaltet sind. Nehmen wir an, wir möchten die zweite Steckdose einschalten. Drücken Sie die Großbuchstabe 'B'. Es erfolgt keine Reaktion auf dem Bildschirm. Drücken Sie '?'. Wieder erhalten wir eine neue Zeile mit der Antwort:



Alles arbeitet. Vergessen Sie nicht, 220 Volt auszuschalten (Befehl 'b'). Sie können das Terminal verlassen, indem Sie nacheinander Strg + A und dann X drücken. Das Experiment ist abgeschlossen.

SPI und I 2 C Reifen


SPI-Busse (die auch im Quad-SPI-Modus arbeiten können) und I 2 C werden in Kombination mit Universal Bridges implementiert. Das heißt, der Komplex hat im Allgemeinen zwei Brücken, von denen jede entweder im SPI-Modus oder in I 2 C eingeschaltet werden kann. Im Strukturdiagramm sieht der entsprechende Abschnitt folgendermaßen aus:



Das Wesentliche beim Einschalten der Endbusse ist aus dem elektrischen Schaltplan ersichtlich. Betrachten Sie nur einen von zwei Controllern:



Somit kreuzen sich die SPI- und I 2 C-Busse in keiner Weise. Einschränkungen für die gemeinsame Verwendung werden nur durch die von FTDI im FT4222H-Controller auferlegten Einschränkungen bestimmt. Leider heißt es in der Dokumentation, dass immer nur eine Schnittstelle aktiv sein kann:



Wie Sie die Leitungen CFG1_0..CFG1_1 und CFG2_0..CFG2_1 verwalten, erfahren Sie im nächsten Artikel. Jetzt glauben wir, dass sie alle aufgehoben sind.

Im Allgemeinen ist die Arbeit mit dem Controller in dem Dokument FT4222H USB2.0 TO QUADSPI / I2C BRIDGE IC sehr gut beschrieben. Daher werden die Funktionen der Betriebsmodi der Controller nicht berücksichtigt. Aus dem genannten Dokument geht alles sehr klar hervor.

Die Beschreibung des Software-Supports finden Sie im nicht minder bemerkenswerten Dokument AN_329 User Guide For LibFT4222 . Wir haben bereits zweimal mit der FTDI-Brücke gearbeitet: in der zweiten Hälfte dieses Artikels und in der zweiten Hälfte davon . Wenn Sie dieses Dokument mit diesen Artikeln vergleichen, können Sie es schnell herausfinden und Ihren eigenen Code schreiben. Lassen Sie mich nur den Referenzcode zeigen, der Daten an den SPI-Bus sendet, ohne auf die Details seiner Implementierung einzugehen. Es sieht schmerzhaft aus, als wäre er bereits mit FT2232 analysiert worden.

Code, der Daten an den SPI-Bus sendet.
 #include "../ftd2xx/ftd2xx.h" #include "../LibFT4222/inc/LibFT4222.h" void SpiTest (int pos) { FT_HANDLE ftHandle = NULL; FT_STATUS ftStatus; FT4222_STATUS ft4222Status; //   ftStatus = FT_Open(pos, &ftHandle); if (FT_OK != ftStatus) { // open failed printf ("error: Cannot Open FTDI Device\n"); return; } ft4222Status = FT4222_SPIMaster_Init(ftHandle, SPI_IO_SINGLE, CLK_DIV_4, CLK_IDLE_LOW, CLK_LEADING, 0x01); if (FT4222_OK != ft4222Status) { printf ("error: Cannot switch to SPI Master Mode\n"); // spi master init failed return; } uint8 wrBuf [] = {0x9f,0xff,0xff,0xff,0xff,0xff,0xff}; uint8 rdBuf [sizeof (wrBuf)]; uint16 dwRead; ft4222Status = FT4222_SPIMaster_SingleReadWrite (ftHandle,rdBuf,wrBuf,sizeof (wrBuf),&dwRead,TRUE); if (FT4222_OK != ft4222Status) { printf ("error: Error on ReadWrite\n"); } else { printf ("received: "); for (int i=0;i<6;i++) { printf ("0x%X ",rdBuf[i]); } printf ("\n"); } FT4222_UnInitialize(ftHandle); FT_Close(ftHandle); } 


SPI-Bus-Teile


Codeentwickler für Mikrocontroller verwenden häufig den SPI-Bus als Generator für eine vorbestimmte Frequenz. Tatsächlich hängen rein programmatisch über GPIO-Leitungen erzeugte Impulse von vielen Faktoren ab. Erstens erfordert das Verzweigen, das Drehen der Schleife, Prozessorzyklen. Zweitens können Unterbrechungen, DMA und andere unvorhergesehene Faktoren den Prozessor stören. SPI ist mehr oder weniger stabil, wissen Sie selbst, wie Sie es schaffen, Bytes in den Puffer zu legen. Eine typische Anwendung des SPI-Blocks, die keinen direkten Bezug zu diesem SPI selbst hat, ist die Steuerung von RGB-LEDs, für die die Genauigkeit der Einstellung der Impulsdauer sehr wichtig ist.

Leider ist dies für FTDI-Brücken nicht akzeptabel. Das obige Codefragment erzeugt diese Impulse auf dem Bus:



In diesem Fall werden die SPI-Betriebsregeln nicht verletzt, aus Sicht dieses Busses funktioniert alles einwandfrei. Denken Sie daran, dass auf Controllern übliche kundenspezifische Lösungen hier nicht funktionieren. Es stimmt, der Komplex hat viele freie USB-Anschlüsse. Alle nicht standardmäßigen Blöcke können separat entwickelt und mit ihnen verbunden werden.

Reifenteile I 2 C


Das einzige, was Sinn macht, ist das Fehlen von Pull-up-Widerständen für den I 2 C-Bus auf der Seite des Komplexes anzuzeigen. Das ist aber normal: An der Seite des Arbeitsgeräts befindet sich noch ein Aufzug. Heutzutage kann ein Pull-up auf eine beliebige Spannung eingestellt werden, daher ist es logisch, dass es auf dem Zielgerät eingestellt ist.

Fazit


Heute haben wir praktische Kenntnisse in der Arbeit mit Reifen erworben, die von FTDI-Brücken implementiert wurden. Im Allgemeinen ist die Arbeit mit ihnen Standard, es ist nur so, dass das gesamte Wissen in einem einzigen Artikel zusammengefasst wird, um nicht Stück für Stück nach ihnen zu suchen. Das nächste Mal werden wir ein Modul in Betracht ziehen, das nicht standardmäßige Geräte steuert und auf der Basis des STM32-Controllers implementiert wird. Im Strukturdiagramm entspricht dieser Abschnitt:



Aber eigentlich ist dort alles etwas interessanter ...

Source: https://habr.com/ru/post/de477662/


All Articles