
Dies ist der erste (einleitende) Artikel in der Reihe darüber, wie ich das Mediensystem des Autos verfeinern werde. Das Projekt selbst ist in Bearbeitung, es gibt keine Zeit, wie alle anderen auch, liebe Leser, bitte haben Sie etwas Geduld, denn ich verspreche oft nicht, Artikel zu nieten.
Alles begann damit, dass ich einen Prius hatte.
Und das erste, was mir aufgefallen ist, waren die Probleme bei der Aktualisierung der Navigation. Die folgenden sind sehr dürftig, aber an einigen Stellen notwendige Funktionen eines Geräts namens "Multifunktionsdisplay" (bei gewöhnlichen Menschen - der Kopf). Und dies vor dem Hintergrund einer großen Anzahl chinesischer Radios mit Android an Bord und vielen Annehmlichkeiten. Ihre regelmäßige Installation impliziert jedoch den Entzug solcher "Brötchen" als Diagramm der Energieverteilung und der Klimatisierung.
Die Idee war geboren, das Android-Radio irgendwie enger mit dem Auto zu verbinden, als die chinesischen Brüder vermuten. Über diesen und den Artikel.
Ausgangssituation
Also. An Bord befindet sich ein 7-Zoll-Display mit einem resistiven Touchscreen, das über TX + - und TX- -Leitungen mit anderen elektronischen Geräten verbunden ist. Und es gibt bereits 3 solcher Paare vom Kopf. In der Schaltung heißt dieses Wunder AVC-LAN und sieht so aus:

Teil 1: Innen schauen
Wie Sie sehen können, befindet sich der Kopf in der Lücke des Netzwerks zwischen dem Router und der weiteren Funkkette, dem Verstärker (ich habe ihn separat), und ein separater Kanal sollte an die Navigationseinheit angeschlossen werden. An anderer Stelle hängt eine Parkeinheit, die in meinen Plänen in keiner Weise erwähnt wird. Gut, gut ... Ich habe beschlossen, die Nähe damit auf bessere Zeiten zu verschieben. Darüber hinaus ist das Parken eher eine Spielfunktion als ein echtes Bedürfnis.
Nachdem wir alle unnötigen Elemente entfernt haben, erhalten wir ungefähr das folgende Blockdiagramm der Geräte:

Reflexionen
Es gab eine Idee, die Navigationseinheit einfach durch etwas Android zu ersetzen, aber sie starb aus, als ich tiefer verstand, wie sie mit dem Kopf kommunizieren. Zusätzlich zu AVC-LAN sind diese Module auch über die GVIF-Leitung (Gigabit Video InterFace) verbunden, und dasselbe Gesicht von Konverterherstellern kann versehentlich Risse bekommen, wenn ich für mehr als 100 US-Dollar auch einen Videosignalkonverter in GVIF kaufe. „Ohne Gesicht zu leben, muss sein es mag schwierig sein, aber ... "- klang in meinem Kopf nach dem Motiv eines berühmten Liedes, und die Entscheidung gefiel mir nicht.
Es gab Lösungen im Netzwerk mit der Installation eines chinesischen Radios anstelle eines Funkempfängers. Dies passte nicht zu mir, da die beiden Anzeigen eine unangemessene Redundanz aufweisen. IMHO.
Lösung
Die folgende Lösung wurde geboren: Ersetzen Sie den gesamten Kopf und schließen Sie das Android-Radio ab, indem Sie sich mit dem Prius anfreunden.
- Entwerfen Sie einen USB <-> AVC-LAN-Hardwarekonverter
- Entwickeln Sie eine Firmware dafür, damit sie sich wie ein USB-HID verbindet.
- Machen Sie es so zusammengesetzt, dass eine der Funktionen wie eine normale Hardwaretastatur erkannt wird (um sie über die Schaltflächen auf dem Bedienfeld als native Steuerung zu verwenden).
- Entwickeln Sie eine Android-Anwendung mit Funktionen, die dem nativen Priusovsky ähnlich (oder überlegen) sind
- Richten Sie die Rückfahrkamera aus
- Lösen Sie Probleme im mechanischen Teil (Installation an einem normalen Ort)
Dabei muss eine weitere Anwendung für Android entwickelt werden - ein gewöhnlicher Sniffer, damit Pakete in AVC-LAN bequemer rückgängig gemacht werden können. Zur gleichen Zeit und üben.
Es sollte so aussehen:

Als Hardware-Basis wurde beschlossen, ein Trainingsboard für den SM32F103 zu verwenden:

Bestellt bei AliExpress für 2,05 USD.
Oder SuchspoilerVielleicht wurde das Los bereits vom Verkäufer gelöscht, also gebe ich die magische Zeichenfolge, um nach Ali zu suchen:
STM32F103C8T6 ARM STM32 Minimum System Development Board-Modul
Was ich an ihr mag:
- USB-Hardwaremodul (Gerät) an Bord des Prozessors
- Angemessener USB-Stack des Herstellers (im Gegensatz zum Freescale-Ovsky bei Nacht nicht in Erinnerung bleiben).
- Kostenlose GPIO-Anschlüsse, über die normale Tasten an den Seiten des Monitors angeschlossen werden können. Möglicherweise werden dadurch die Hardwaretasten des Radios unter dem Bedienfeld ausgeblendet. Ich weiß nicht, was sie sein wird
- Und darauf können Sie den AVC-LAN-Konverter in logische Ebenen hängen
Ich werde in der Reihenfolge der Umsetzung weiter beschreiben, was vor allem auf mein persönliches Wissen zurückzuführen ist. Das heißt, Ich versuchte die Orte zu erkennen, an denen sie nicht ganz am Anfang waren, und am Ende zu verlassen, was sicherlich passieren sollte.
In jedem Fall sind mehrere Artikel in verschiedenen Hubs geplant. Das Projekt stellt sich als viel FullStack heraus - von der Hardwareverbindung bis zur Android-Anwendung.
Teil 2: USB, HID, Deskriptoren und alles, um einen Pilotprototyp zu erhalten
Der erste Schritt war, dass ich ein paar Geräte und Telefone besorgen wollte, damit das Gerät das Paket auf das Telefon übertragen konnte, und das - um es in der Anwendung anzuzeigen.
Wie Gagarin sagte: Lass uns gehen!
USB HID Composite-Gerät auf STM32
Ich entschied mich dafür, das ST-Beispiel von meinen Aufgaben anzupassen und ein USB-Gerät zu erhalten, das vom Host als Teil der Tastatur und „etwas anderes“ erkannt wird - das RAW HID-Gerät. Die erste ist, wie bereits erwähnt, für die native Android-Steuerung vorgesehen, die zweite für den direkten Austausch von AVC-LAN-Paketen mit dem Programm auf dem Gerät.
Basierend auf CubeMX von STM und nachdem ich viele Artikel zur Implementierung von benutzerdefiniertem HID gelesen hatte, fand ich eine unangenehme Sache im Netzwerk: Das Problem der Erstellung von Verbundgeräten ist praktisch nicht vorhanden oder sehr selten.
Quellcodes werden später seinIch lade die Quellcodes noch nicht hoch, da das Projekt jetzt in einem experimentellen Trainingsmodus implementiert wird. Wenn das Projekt erfolgreich abgeschlossen wurde, ziehen Sie sie auf Github und bearbeiten Sie den Artikel mit einem Link zu ihnen.
In der Form, in der sie sich befinden, macht das Hochladen keinen Sinn - ohne mich gibt es im Internet genug Chaos.
USB, Composite, HID
Nur ein paar Worte zu diesem Thema. Es wird davon ausgegangen, dass Sie mit dem USB-Standard mehr oder weniger vertraut sind. Wenn nicht, ist es besser, sich zuerst mit Beispielen aus CubeMX vertraut zu machen und mit ihnen zu experimentieren.
Also haben wir:
Beispiel für die Implementierung eines STM-USB-Stacks und einer Maus. Dort haben wir einige Deskriptoren und einen funktionalen Endpunkt konfiguriert. Dies gilt zusätzlich zu einem Paar von 0x00 und 0x80 zur Steuerung des gesamten Geräts.
Um mein Projekt zu implementieren, muss der Tastaturendpunkt bidirektional sein (ich weiß nicht warum - es ist nützlich) und einige weitere Endpunkte, die zum Datenaustausch mit der zweiten RAW-Funktion verwendet werden. Fügen Sie sie hinzu.
Wir machen den Punkt bidirektional, indem wir den OUT-Punkt zum Deskriptor hinzufügen:
Konfigurationsdeskriptor.Achten Sie beim Bearbeiten eines Deskriptors auf Indizes und Größen.
(2c5cf968121f0d8fa43a6755c09e15ef3a317791):
0x07, USB_DESC_TYPE_ENDPOINT, HID_EPOUT_ADDR, 0x03, HID_EPOUT_SIZE, 0x00, HID_FS_BINTERVAL,
Und noch ein paar Punkte hinzufügen:
Konfigurationsdeskriptor(bc2bd583c98715e106fcb3ab07b266bc9221be36):
0x07, USB_DESC_TYPE_ENDPOINT, HID_EPIN_ADDR2, 0x03, HID_EPIN_SIZE, 0x00, HID_FS_BINTERVAL, 0x07, USB_DESC_TYPE_ENDPOINT, HID_EPOUT_ADDR2, 0x03, HID_EPOUT_SIZE, 0x00, HID_FS_BINTERVAL,
Es war ein Konfigurationsdeskriptor. Jetzt wird der Host sicher sein, dass wir eine Art zusammengesetztes HID-Gerät haben, und Sie können Daten an alle diese Punkte senden. Das ist aber nicht so.
Um dies wahr zu machen:
1. Unser Controller verfügt über einen speziell zugewiesenen Speicher, der zusammen mit CAN- und USB-Modulen getaktet wird. Da das USB-Modul unabhängig am Empfang / Senden eines Datenpakets beteiligt ist, müssen Sie für jeden einzelnen Endpunkt Puffer in diesem Speicher festlegen:
USBD_LL_Init in der Datei usbd_conf.c HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR , PCD_SNG_BUF, 0x100); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR , PCD_SNG_BUF, 0x140); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR2 , PCD_SNG_BUF, 0x180); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR2 , PCD_SNG_BUF, 0x1B0);
Pufferadressen sind willkürlich, wenn sie sich nur nicht überlappen würden.
Aus irgendeinem Grund wird der ST-Stapel mit der Erwartung geschrieben, dass das Gerät nicht mehr als einen bidirektionalen Endpunkt hat. Daher werden wir den Stapel ein wenig ändern:
Übertragen
Benennen Sie die Prozedur USBD_HID_SendReport in USBD_HID_SendReportEP um und fügen Sie einen weiteren Parameter hinzu - die Endpunktnummer. Wir belassen die Prozedur aus Gründen der Abwärtskompatibilität mit dem alten Namen, rufen jedoch im Hauptteil USBD_HID_SendReportEP mit einer Konstante in Form eines Endpunkts auf. Die Lösung ist immer noch nicht die ästhetischste, aber sie wird für das Experiment funktionieren, und selbst wenn sie bestehen bleibt, wird sie ein bestimmtes Projekt nicht beeinträchtigen.
usbd_hid.c uint8_t USBD_HID_SendReportEP (USBD_HandleTypeDef *pdev, uint8_t ep, uint8_t *report, uint16_t len) { ... , USBD_HID_SendReport } uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len) { return USBD_HID_SendReportEP(pdev,HID_EPIN_ADDR,report,len); }
Jetzt ist alles bereit, Daten zu senden, es bleibt nur zum richtigen Zeitpunkt, um diese Funktion aufzurufen.
Finalisierung
Aus Gründen der Reihenfolge suchen wir nach dem Projekt und rufen USBD_LL_CloseEP erneut auf, jedoch nach den neu erstellten Endpunkten.
Rezeption
Damit die Endpunkte moralisch so funktionieren, dass sie funktionieren, müssen Sie USBD_LL_PrepareReceive für sie aufrufen. Ich empfehle dem Leser, die Suche nach dem Projekt für diese Zeile durchzugehen und diese Aufrufe an Ihre Bedürfnisse anzupassen.
Ich habe diesen hässlichen Tintenfisch in meinem Code:
usbd_core.c USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR+(epnum&0x7F)-1 , hhid->Report_buf, USBD_HID_OUTREPORT_BUF_SIZE);
Das heißt, Ich ging davon aus, dass die Anzahl der Endpunkte hintereinander liegt. Das ist schlecht, IMHO. Tu das nicht. Mag aber auch nicht ST.
Sie müssen nur noch in die Datei usbd_hid.c und speziell in die Funktion USBD_HID_DataOut gehen und sicherstellen, dass der Aufruf des empfangenen Datenhandlers Ihren persönlichen Vorstellungen über das Schöne entspricht. Es ist mir auch nicht gelungen, daher werden Code und Beschreibung lang und unverständlich sein. Einfacher selbst zu machen.
Bericht
Alles, an dieser Stelle haben wir ein zusammengesetztes Gerät, das Daten über zwei bidirektionale Punkte austauschen kann. Beim letzten Schlag haben wir die Neugier des HID-Fahrers „zum Schweigen gebracht“ und einen solchen Berichtsdeskriptor beschrieben:
__ALIGN_BEGIN static uint8_t HID_ReportDesc2[33] __ALIGN_END = { 0x06, 0x00, 0xff,
Dieser Bericht teilt dem HID-Treiber mit: Es werden ungefähr 31 Datenbytes vorhanden sein. Sie müssen nicht herausfinden, was sie sind - geben Sie sie einfach an das Programm weiter, das dieses Gerät geöffnet hat. In einem physischen Bericht entspricht das Nullbyte dem Berichtsindex (REPORT_ID (2)). Dementsprechend werden insgesamt 32 Bytes kommen.
Und geben Sie die Daten dazu in usbd-hid.c ein, Funktion USBD_HID_Setup .:
usbd-hid.c switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) {
Weiter im Programm:
- Montage des AVC-LAN-Logikpegelwandlers und Anschluss an die Karte. Analyse der physikalischen Schicht von AVC-LAN, reale Wellenformen.
- Verarbeitung der Schnittstelle auf Controller-Ebene und Senden von Paketen mit Berichten
- End-to-End-Schnittstelle und Reverse Engineering Prius. Paket Sniffer (oder meine erste Android App)
PS
- Ich habe beschlossen, einen Artikel zu schreiben, weil ich (fast) gezwungen war, davon zu überzeugen, dass dies geteilt werden sollte. Selbst wenn ich das Projekt nicht beende, können einige der neuesten Informationen jemandem auch auf "rohe" Weise helfen.
- Kritik am Projekt ist willkommen, wie Ich selbst kann mir noch nicht ganz vorstellen, dass es klappen wird.
- Kritik am Artikel, Design, Präsentation - vor allem, weil Dies ist der erste Artikel für die Ressource. Mit der Fortsetzung der Arbeit möchte ich meine Gedanken in der für die Leser üblichen und leicht verdaulichen Form ausdrücken